The easiest thing is to do something like this. During
initialization, you call Segment::Load; this parses the Cues element
(as well as everything else).
To do the actual seek, you call Cues::Find to get a cue point. Then
call Cues::GetBlock with the cue point to get the block.
If you don't have a Cues element, there are other ways to seek. You
can call Segment::FindCluster to get the cluster, then call
Cluster::GetEntry to get the block.
> I am trying to seek using the
> Segment::FindCluster method and this seems to work the first time but
> then the second seek results in an assertion on (m_entries!=NULL).
This searches for a cluster, given a time. That's probably not quite
what you want.
> I
> also notice there is a Seek method off of Track and VideoTrack and
> AudioTrack but I am not sure if I should be calling those or not. I
> would appreciate any pointers.
That would work too.
libwebm is optimized around incremental parsing of a webm file as it
is being downloaded from a network (meaning that you don't necessarily
have all of the file available, but in spite of that seeking is still
possible), so there are often various ways of doing things, depending
on different scenarios. I would study the source code for the
webmsource filter (DirectShow), or the webmmfsource media source
object (Media Foundation), to get some ideas.
-Matt
If you have a Cues element, that will get you a keyframe (see my
previous message). If you don't have a Cues element, call
Segment::FindCluster, and then call Cluster::GetEntry.
Not necessarily. There's no guarantee that you even have a Cues element.
If you have video + audio. use the Cues to find the block entry for
the video track, and then grab the audio on the same cluster as the
keyframe you just found.
(If you have an audio-only file, use the time to search for a cluster
(Segment::FindCluster), and then use the audio on the cluster.)
> I am wondering because
> my Find is always returning false. I step through the function and
> its the very last pTP = pCP->Find(pTrack); fails to find a track. Not
> sure if it matters buy the webm's I am testing do not have audio
> tracks.
It's OK if you don't have audio.
Assuming you have video, if you have a Cues element, but Cues::Find is
returning false, then something is probably wrong. If you're in a
debugger, then what is the value of the CuePoint?
Is this the track number of your video track?
> m_pos = 12583651
> m_block = 1
> m_track_positions_count = 1
So this cue point has exactly one track position. The value returned
by pTrack->GetNumber() should match the m_track value.
Track numbers should be small, positive integers. Something's wrong here.
> The
> function is trying to find a track where the number = 1. Is there an
> additional step I need to do to initialize these numbers? I am
> calling Segment::Load.
Call Segment::Load, query the segment object for the Tracks, and then
query the Tracks for the (video) Track. You first need to figure out
why your VideoTrack object is corrupt.
> However I am detereming my track numbers early
> on so I know which is my video track and this portion is correctly
> finding track "1".
The VideoTrack derives from Track. What is the value of
Track::m_info.number and Track::m_info.type? (You can query these
outside of a debugger by calling Track::GetType and Track::GetNumber.)
If you call Segment::Load, this loads everything (this is
non-incremental parsing), so you should be able to just say
Cues::GetBlock. You'd only need to use FindOrPreloadCluster if you're
doing incremental loading (in which case, you would not be calling
Segment::Load).
It doesn't sound like you want FindOrPreloadCluster, because that only
gets you a cluster. You want an actual block (in your case, you're
doing a seek, so you also need a keyframe), and that's what
Cues::GetBlock does.
> I noticed
> in the dshow source you use the Preload method to check for Unparsed()
> data. Does this FindOrPreloadCluster do the same thing or can you
> explain what the Preload() function does and if I need it?
If you're calling Segment::Load, then Segment::Unparsed should return 0.
Pre-loading clusters is only required when you're doing incremental
parsing, and you need to use a cue point to seek to a cluster not
already loaded. You're doing non-incremental parsing, so you don't
have to worry about pre-loading clusters during a seek.
I think Track::GetNext should work for you. It accepts a current
block entry, and returns the next block entry for this track. The
operation navigates across clusters as necessary.
Incremental parsing is much more complicated than reading from a local
file. You can study the webmsplit filter (part of the DirectShow
filters), or the webmsource media source (webmmfsource, in the
mediafoundation folder).
For various reasons, I never got the webmsplit filter fully working
(for a URL source via the AsyncReader -- it works fine if you use the
FileReader), but it might be close enough for your needs. The
webmmfsource media source actually does work, so you can study that
for ideas. If you install the media foundation filters, you can use
WMP12 (on Win7) to stream from a URL source.
The webmsource filter also does a kind of incremental parsing (IIRC,
it does not use Segment::Load), but it only works for local files.