Bo Thorsen
2007-Apr-12 02:46 UTC
[theora] Seek problem 2 - reinitialization of the decoder
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) bufferData(); while (ogg_page_serialno(&page) != tstream.serialno) if (ogg_sync_pageout(&sync, &page) <= 0) // Find a Theora page, not Vorbis. bufferData(); (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)) queuePage(); while (isPlaying) { const int result = ogg_stream_packetout(&tstream, &packet); if (result == 0) { // Not enough data... load some more pages! bufferData(); } 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 http://www.thorsen-consulting.dk
Ralph Giles
2007-Apr-12 10:42 UTC
[theora] Seek problem 2 - reinitialization of the decoder
On Tue, Apr 03, 2007 at 01:51:09PM +0200, Bo Thorsen wrote:> Unfortunately, the theora_packet_iskeyframe() fails about 5% of the times.theora_packet_iskeyframe() can't fail. It returns -1 if it doesn't recognize the packet, but otherwise it just looks for the bit flag in the packet. The problem must lie elsewhere. How do you know it's failing? -r