[FFmpeg-devel] Fixing av_seek
Don Moir
donmoir at comcast.net
Mon Jan 23 21:47:21 CET 2012
>>> Finnally getting around to looking more closely at seek problems in
>>> ffmpeg.
>>>
>>> This is a follow up to ticket #504.
>>> https://ffmpeg.org/trac/ffmpeg/ticket/504
>>>
>>> My goal is to write a higher level seek function that depends on the
>>> lower level ffmpeg seek functions. In some cases, patches to ffmpeg may
>>> need to be applied.
>>>
>>> The higher level function will only deal with a timestamp that might
>>> correspond to a slider or similiar, and will seek very close to that
>>> timestamp without image distortion.
>>>
>>> There are several categories of success or failure when seeking. This
>>> first group (Group A), deals with things that work or are easy to deal
>>> with.
>>>
>>> o - everything works and works well. There are plently of index_entries
>>> and the format in question does the right thing. CODEC_ID_FLV1 is an
>>> example that works well but some other formats work just as well.
>>>
>>> o - there are no index_entries or none of the index_entries are marked
>>> as AVINDEX_KEYFRAME. This will cause avformat_seek_file or av_seek_frame
>>> to fail. If there are index_entries and the first entry represents the
>>> first frame, then I have found that just marking this first index_entry
>>> with AVINDEX_KEYFRAME fixes the ffmpeg seek failure problem. If there
>>> are no index_entries then you can add one using av_add_index_entry using
>>> the correct parameters for the first frame and marking it as
>>> AVINDEX_KEYFRAME. This assumes the first frame must be a keyframe and
>>> easier to deal with this at startup rather then trying to deal with it
>>> when doing a seek.
>>>
>>> o - lower level seek functions mostly deal with keyframes and thats all
>>> good, but thats not good enough for an end user trying to use a slider
>>> to seek. So get as close as possible using one of the ffmpeg seek
>>> functions and then proceed forward to the timestamp of interest. This
>>> works pretty good and is fast enough. Mostly, good files will have
>>> enough AVINDEX_KEYFRAME index_entries to make this behave quite well.
>>> Even when there are not enough entries, it works good. You probably want
>>> to do this in a separate thread. Make sure you first seek to a timestamp
>>> that is less than or equal to the timestamp of interest so you can
>>> proceed forward. There are probably ways to improve on this.
>>>
>>> The second group (Group B) falls into the class of failures or bad
>>> behavior that is not easy to deal with. e.g. an inability to make it
>>> work as expected for various reasons.
>>>
>>> I am still dealing with trying to find out Group B problems. I have had
>>> issues with MPEG1, THEORA, and a few others, and I will know more about
>>> these problems as I get into it further.
>>>
>>> I use VLC and SMPlayer to cross check and both of these have their share
>>> of seek problems. I use my own player to test with.
>>
>> Using this h264 file, the index_entries are built on the fly and appear
>> to be incorrect.
>>
>> http://sms.pangolin.com/temp/bad_seek_index_h264.zip (2.5mb)
>>
>> codebase: git-67f5650 - after fixes with h264 seeking but I don't see any
>> difference with older codebase versions than this one.
>>
>> Just after av_open_input_file, there are 2 index_entries. The first one
>> has timestamp of 0 and 2nd has timestamp of 0x48f. The odd thing is they
>> both have the same pos which 0x122F. So seems strange from the start. As
>> playback progresses, the number of index_entries increases and this is
>> normal.
>>
>> When you try to seek on this file to a supposed keyframe, you don't get a
>> finished frame until much later (~4 seconds). What should happen is if
>> you have seeked to a keyframe, you should be getting a finished frame
>> immediately. This is the way I see it at any rate. So trying to seek into
>> this file breaks the playback, meaning you will get a long pause before
>> normal playback resumes because you are not getting a finsihed frame when
>> you should be. If I just seek to zero on this file, then all is good and
>> I get the finished frames as expected but of course it's slower to reach
>> the requested timestamp.
>>
>> I bring this up because I think this represents a key problem with some
>> of the codec types. That is index_entries are added that don't click with
>> actual keyframes. I asked a question about this relationship on the
>> original ticket but there was no response.
>>
>> I think getting this fixed will go a long way in fixing several seek
>> problems. But I need information from you if you have any on this. If you
>> don't have a answer, maybe "I or we don't know" would be better than no
>> answer. Also not to just focus on h264 here because I believe there are
>> other formats with this very same problem.
>
> This file identifies some problems with the ogg decoder when seeking:
>
> http://sms.pangolin.com/temp/bad_seek_ogg_BuckBunny.zip (46 mb)
>
> I am not making any attempt to cut some of these samples down to make sure
> all is relevant.
>
> This file plays fine in my own player without any problems. SMPlayer
> chokes on it abit, then a reload and it plays ok. ffplay plays it fine
> with maybe a few artifacts.
>
> The problems come in when you try to seek on it. The ogg decoder has just
> a basic seek that calls ff_seek_frame_binary. This can be found in
> libavformat\oggdec.c in the function ogg_read_seek. Seems seek was kind of
> an after thought and patched in to the orignial code.
>
> o - unlike many of the other decoders, the ogg decoder makes no attempt to
> build it's index_entries when you do a seek. This is the first cause of
> failure. Since it does not have these entries, it will fail in
> ff_seek_frame_binary if the file has not been read sufficiently to create
> it's index. Some ogg files work ok in this regard but BuckBunny will fail.
> I currently go ahead and build these entries if needbe before I call any
> seek for an ogg decoder file and this is a start to get this working.
> BuckBunny is THEORA but ogg decoder handles several CODEC id's.
>
> o - The ogg decoder keeps a private structure in AVFormatContext.priv_data
> (struct ogg) and within this it keeps some private stream information
> (struct ogg_stream). In the ogg_stream it keeps track of lastdts and
> lastpts. When you do a seek everything seems to be ok like position
> information etc. But these 2 variables are not reset to AV_NOTPTS_VALUE
> and they contain the values that were in effect before you did the seek.
> So on the first read after a seek, you will get the right packet but the
> pts and dts values will be wrong for the packet. No amount of flushing etc
> seems to fix it and this is just a bug. I believe the ogg_read_seek
> functions just needs to set these 2 vairaibles to the proper values. With
> the second read after the seek the dts and pts values seem ok.
>
> For my own code I fixed the above issues and now seeking for this file
> works fine. I still have some painting artifacts but this is more of a
> general problem and I will deal with that later.
>
> I develop under windows because thats what most of our users use. Some mac
> too. My experinece with linux is somewhat limited but I used to run that
> using vmware. The application I use to test ffmpeg is designed for windows
> and so it's a bit of a pain to debug and trace thru ffmpeg under windows
> but this is just busy work.
>
> I can idenify and pinpoint these various problems but I am just not setup
> to provide proper patches. I have people yelling at me already about
> spending too much time on this and I have to earn a living. So while I
> will continue to do this and idenify the problems, I will have to leave it
> up to you to do the patches. Finding the problems is the most work anyway.
>
> So the 2 things for the ogg decoder is to make sure the index_entries are
> built before you do a seek. Most of the other decoders do this correctly.
> Make sure the lastpts and lastdts variables (struct ogg_stream) are set to
> proper values in the ogg_read_seek function. ogg_read_seek should also
> make sure the index_entries are built up to the timestamp of interest at
> least before calling ff_seek_frame_binary. Note: just reading the packets
> with no decoding is quick and sufficient to build the index_entries. I
> don't do it if sufficient entries are built alreadly and stop when I have
> built up to the timestamp of interest. These entries are normally built on
> the fly as you read packets when processing the file. I think some
> decoders mght have more elegant ways to do it but this is a good fallback.
>
> ffplay complains about first frame not being key frame when you try to
> seek with ffplay but that doesn't seem to be a problem and may be related
> to the above bugs. Seeking fails badly in SMPlayer for this file and
> generally seeking does not work well at all in ffplay for this file. For
> my own app with the above fixes, it now works perfect outside of some
> artifacts but thats a different issue.
The attached file contains the code fragments along with comments that I am
using to fix seeking with the ogg decoder. Not a patch but details the
basics on fixing seeking for ogg related files. I tested it with a couple
THEORA files and so far so good. This would need to be applied to
libavformat\oggdec.c. The attached file contains a function for creating the
index_entries if needbe and sets the lastpts and lastdts to AV_NOPTS_VALUE
after a successful seek.
-------------- next part --------------
An embedded and charset-unspecified text was scrubbed...
Name: oggdec_changes.txt
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20120123/8923a336/attachment.txt>
More information about the ffmpeg-devel
mailing list