[FFmpeg-trac] #941(avformat:new): Seek problems with ogg decoder
FFmpeg
trac at avcodec.org
Thu Jan 26 23:05:08 CET 2012
#941: Seek problems with ogg decoder
----------------------------------+---------------------------------------
Reporter: DonMoir | Type: defect
Status: new | Priority: normal
Component: avformat | Version: unspecified
Keywords: | Blocked By:
Blocking: | Reproduced by developer: 0
Analyzed by developer: 0 |
----------------------------------+---------------------------------------
ffmpeg-git-14d94a1
built on Jan 23 2012 17:40:00 with gcc 4.6.2
configuration: --disable-static --enable-shared --enable-gpl
--enable-version3 --disable-w32threads
--enable-runtime-cpudetect --enable-avisynth --enable-bzlib
--enable-frei0r --enable-libopencore-amrnb
--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
--enable-libxvid --enable-zlib
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:
http://sms.pangolin.com/temp/bad_seek_ogg_BuckBunny.zip (46 mb)
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.
--
Ticket URL: <https://ffmpeg.org/trac/ffmpeg/ticket/941>
FFmpeg <http://ffmpeg.org>
FFmpeg issue tracker
More information about the FFmpeg-trac
mailing list