[theora] Seek problem 2 - reinitialization of the decoder

Bo Thorsen bo at thorsen-consulting.dk
Tue Apr 3 04:51:09 PDT 2007

Hi people,

Next issue at hand here is after I have done a seek in a theora file. At this 
point, I have to reinitialize the decoder so the viewing can continue. Again, 
I have code that works most of the time, but, well...

Just after the last file position seek, this code is run:

		while ((result = ogg_sync_pageout(&sync, &page)) == 0)
		while (ogg_page_serialno(&page) != tstream.serialno)
			if (ogg_sync_pageout(&sync, &page) <= 0)
				// Find a Theora page, not Vorbis.

(Same code as pasted in the the seek problem 1 mail)

Now, I need to get back into the decoding loop. I do this exactly the same way 
as when the decoder starts up just after the first initialization:

while (ogg_sync_pageout(&sync, &page))
while (isPlaying) {
  const int result = ogg_stream_packetout(&tstream, &packet);
  if (result == 0) {
	// Not enough data... load some more pages!
  } else if (result > 0) {
    theora_decode_packetin(&decoder, &packet);

    int videoBufferTime = theora_granule_time(&decoder, decoder.granulepos);
    int frameNo = theora_granule_frame(&decoder, decoder.granulepos);

    if (theora_packet_iskeyframe(&packet) == 1) {

The problem is that the time and framenumber are not correct - in fact they 
are offset with something that's either completely random or influenced by 
whatever state the decoder had before the seek (I don't know which).

So my immediate fix was to just read until the first keyframe and then assume 
the decoder picks up from there.

The assumption is correct. After the keyframe, the values actually do have a 
real meaning again. And this is necessary, because I report the frame number 
to the user and use the videoBufferTime to adjust the player (either drop 
frames or sleep a bit).

Unfortunately, the theora_packet_iskeyframe() fails about 5% of the times. For 
the frame number this only means the user sees the progress jump. But since 
the code sees it's now 239 seconds ahead (or some other random value), it 
freezes playback for a long time. Or, almost just as bad, it thinks we're 
several thousands seconds behind, so it starts dropping frames as much as 
possible (dropping only means skipping the theora_decode_YUVout and the yuv 
to rgb after it).

I hope the code I have sent here is sufficient to tell me where I do something 
bad, so I can have a 100% working reinitialization of the decoder. Any help 
is appreciated.

Bo Thorsen.


Thorsen Consulting ApS - Qt consulting services

More information about the theora mailing list