Ticket #941 (closed defect: fixed)
Seek problems with ogg decoder
|Reported by:||DonMoir||Owned by:|
|Blocking:||Reproduced by developer:||yes|
|Analyzed by developer:||no|
built on Jan 23 2012 17:40:00 with gcc 4.6.2
configuration: --disable-static --enable-shared --enable-gpl
--enable-runtime-cpudetect --enable-avisynth --enable-bzlib
--enable-libopencore-amrwb --enable-libfreetype --enable-libgsm
--enable-libmp3lame --enable-libopenjpeg --enable-librtmp
--enable-libschroedinger --enable-libspeex --enable-libtheora
--enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis
--enable-libvpx --enable-libx264 --enable-libxavs
libavutil 51. 34.101 / 51. 34.101
libavcodec 53. 57.105 / 53. 57.105
libavformat 53. 30.100 / 53. 30.100
libavdevice 53. 4.100 / 53. 4.100
libavfilter 2. 59.101 / 2. 59.101
libswscale 2. 1.100 / 2. 1.100
libswresample 0. 6.100 / 0. 6.100
libpostproc 52. 0.100 / 52. 0.100
There seems to be several problems with seeking in the ogg decoder (libavformat/oggdec.c)
This file can be used to identify some of the key problems:
There are no issues with playback of this file and only seeking is a problem. Fails to seek properly with SMPlayer, ffplay, and anything else using ffmpeg unless special handling is applied.
In reference to the function ogg_read_seek in file oggdec.c.
1) I see it makes no attempt to create (if needbe) the AVIndexEntry table for the stream which is pretty much required to make seeking work. Most of the other formats do this when you call it's read_seek function. So I find that I need to create this table prior to calling avformat_seek_file for ogg files. This table can be created by calling av_read_packet until the timestamp of interest is reached. This is pretty quick but it should only be done when needbe. Other formats have other and quicker means to do this, but the read packet method works well enough if nothing else is available. For ogg files, once I know that the index_entries have been created as best they are going to be, I then call av_index_search_timestamp(pStream,timestamp,AVSEEK_FLAG_BACKWARD) and I use the timestamp associated with the returned index for my seek time. The AVSEEK_FLAG_BACKWARD flag makes sure the returned timestamp will be less than or equal to my requested timestamp. If -1 is returned form av_index_search_timestamp I deal with it but this should not happen if the index_entries have been built and all else is good. Now we can call avformat_seek_file with the modified timestamp and expect reasonable results. If you don't do this read_timestamp will fail in ff_seek_frame_binary which is called from ogg_read_seek. Note that av_index_search_timestamp is also pretty much worthless for ogg files if the index_entries have not been created.
2) ogg_read_seek does not do the proper cleanup after a seek. That is, there is stale information left that was in place prior to a seek. The ogg decoder uses private data that it places in AVFormatContext.priv_data. This is known to ogg as struct ogg*. Within this structure, ogg also has information for each stream. This is known to ogg as struct ogg_stream*. The stale information that I know about within the ogg_stream is lastpts and lastdts. These are not modified by a seek and whatever was in there before the seek will be used after a seek and these values will be used by the next av_read_packet. After a seek, I am having to call ogg_reset (also in oggdec.c) but this is clearly not the right thing to do. This ogg_reset is not available to higher level code but I have it hacked in for the present. The packet now will contain AV_NOPTS_VALUE for the pts and dts and this is not right either, but at least I can deal with it. Additional packet reads straighten this out. The lastdts and lastpts should of course reflect the next packet that is read. Not really sure how to clean it all up after a seek to make sure all is normal for ogg files. All the other decoders I have tested do this correctly. I think more needs to be cleaned up in addition to lastpts and lastdts but not sure.
With the above changes, I can now seek into the buckbunny sample perfectly. Would be great if someone would revisit the seek code in the oggdec.c file and make sure it does the right thing.
There are some other problems with ogg but the above 2 things goes a long way in fixing some of them. For the most part, most of my ogg files work fine after the above changes, but there are still some anoying problems with some files. It's like the audio packets are being used to create index_entries for a video stream for some files and not video packets and so this will throw the index_entries off. So while the seek works fine, it may be some time before the next video frame is available but audio is dead on. Not sure about this one and this is just for some ogg files.
I can provide more information and code samples if required.
- Keywords ogg seek added
- Status changed from new to open
- Version changed from unspecified to git-master
- Reproduced by developer set
- Status changed from open to closed
- Resolution set to fixed