libwebm seek example?

385 views
Skip to first unread message

Ben Siroshton

unread,
Jan 24, 2011, 8:33:41 PM1/24/11
to WebM Discussion
Can someone point me to or write a quick libwebm example to
demonstrate seeking? 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). 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.

Thanks.

-=ben

btw, if your a libwebm author reading this by chance, you might look
at your implemention of the MkvReader::IsOpen method. ;)

Ben Siroshton

unread,
Jan 24, 2011, 8:53:21 PM1/24/11
to WebM Discussion

Ah, my mistake; I overlooked wrapping my seek code with my playback
mutex. doh! :/

A follow up question then. Is there a built in way to do a key frame
seek or will I need to find the nearest key frame manually?

Thanks.

-=ben

Matthew Heaney

unread,
Jan 24, 2011, 10:41:33 PM1/24/11
to webm-d...@webmproject.org
On Mon, Jan 24, 2011 at 8:33 PM, Ben Siroshton <mirs...@gmail.com> wrote:
> Can someone point me to or write a quick libwebm example to
> demonstrate seeking?

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

Matthew Heaney

unread,
Jan 24, 2011, 10:43:12 PM1/24/11
to webm-d...@webmproject.org
On Mon, Jan 24, 2011 at 8:53 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
> A follow up question then.  Is there a built in way to do a key frame
> seek or will I need to find the nearest key frame manually?

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.

Ben Siroshton

unread,
Jan 25, 2011, 12:33:35 PM1/25/11
to WebM Discussion


On Jan 24, 7:43 pm, Matthew Heaney <matthewjhea...@google.com> wrote:
> On Mon, Jan 24, 2011 at 8:53 PM, Ben Siroshton <mirsw...@gmail.com> wrote:
>
> > A follow up question then.  Is there a built in way to do a key frame
> > seek or will I need to find the nearest key frame manually?
>
> 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.

Great, thanks for the insight. I'll check it out.
-=ben

Ben Siroshton

unread,
Jan 25, 2011, 2:00:41 PM1/25/11
to WebM Discussion
> 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.

Do all webm's have useable Cues for seeking? 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.

Thanks.
-=ben

Matthew Heaney

unread,
Jan 25, 2011, 2:09:53 PM1/25/11
to webm-d...@webmproject.org
On Tue, Jan 25, 2011 at 2:00 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
> Do all webm's have useable Cues for seeking?

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?

Ben Siroshton

unread,
Jan 25, 2011, 2:25:31 PM1/25/11
to WebM Discussion

> 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?

breaking on the pCP->Find(pTrack) line my pCP values are:

m_element_start = 25104093
m_element_size = 16
m_index = 45
m_timecode = 45000
m_track = 1
m_pos = 12583651
m_block = 1
m_track_positions_count = 1

-=ben

Matthew Heaney

unread,
Jan 25, 2011, 2:29:47 PM1/25/11
to webm-d...@webmproject.org
On Tue, Jan 25, 2011 at 2:25 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
>> 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?
>
> breaking on the pCP->Find(pTrack) line my pCP values are:
>
> m_element_start = 25104093
> m_element_size = 16
> m_index = 45
> m_timecode = 45000
> m_track = 1

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.

Ben Siroshton

unread,
Jan 25, 2011, 2:31:49 PM1/25/11
to WebM Discussion
> > 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?
>
> breaking on the pCP->Find(pTrack) line my pCP values are:
>
...

In addition when I step into CuePoint::Find pTrack->GetNumber() is
returning a huge value of 199252865136, this does not seem right. 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. 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".

-=ben

Ben Siroshton

unread,
Jan 25, 2011, 2:39:30 PM1/25/11
to WebM Discussion
> So this cue point has exactly one track position.  The value returned
> by pTrack->GetNumber() should match the m_track value.

My mistake, I was thinking the track value would be returned from Find
not supplied. I understand now your notation for in/out variables.
Updating my code now...
-=ben

Matthew Heaney

unread,
Jan 25, 2011, 2:40:20 PM1/25/11
to webm-d...@webmproject.org
On Tue, Jan 25, 2011 at 2:31 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
> In addition when I step into CuePoint::Find pTrack->GetNumber() is
> returning a huge value of 199252865136, this does not seem right.

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.)

Ben Siroshton

unread,
Jan 25, 2011, 3:09:20 PM1/25/11
to WebM Discussion
> 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.

Awesome, got it working! The only thing left I had to do was update my
main cluster using FindOrPreloadCluster(trackPos->m_pos). 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?

Thanks again!

-=ben

Matthew Heaney

unread,
Jan 25, 2011, 3:21:02 PM1/25/11
to webm-d...@webmproject.org
On Tue, Jan 25, 2011 at 3:09 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
> Awesome, got it working! The only thing left I had to do was update my
> main cluster using FindOrPreloadCluster(trackPos->m_pos).

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.

Ben Siroshton

unread,
Jan 25, 2011, 3:30:53 PM1/25/11
to WebM Discussion

> 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 needed to get the cluster for the found block so that my next
cluster.GetNext would succeed.

Is this the correct way to do this?

-=ben

Ben Siroshton

unread,
Jan 25, 2011, 3:34:06 PM1/25/11
to WebM Discussion
> 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.

Speaking of which is there an example that shows how to read webm over
http and parse incrementally?

Thanks.

-=ben

Matthew Heaney

unread,
Jan 25, 2011, 3:39:08 PM1/25/11
to webm-d...@webmproject.org
On Tue, Jan 25, 2011 at 3:30 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
> I needed to get the cluster for the found block so that my next
> cluster.GetNext would succeed.
>
> Is this the correct way to do this?

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.

Matthew Heaney

unread,
Jan 25, 2011, 3:46:20 PM1/25/11
to webm-d...@webmproject.org
On Tue, Jan 25, 2011 at 3:34 PM, Ben Siroshton <mirs...@gmail.com> wrote:
>
> Speaking of which is there an example that shows how to read webm over
> http and parse incrementally?

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.

Ben Siroshton

unread,
Jan 25, 2011, 3:56:24 PM1/25/11
to WebM Discussion
Thanks again for all your help. I think I have what I need for now,
you have been most helpful. :)

-=ben
Reply all
Reply to author
Forward
0 new messages