[FFmpeg-devel] [PATCH] avoid infinite loop when seeking flv and non seekable input
Baptiste Coudurier
baptiste.coudurier
Mon Jul 28 02:08:47 CEST 2008
Michael Niedermayer wrote:
> On Sat, Jul 26, 2008 at 09:56:17PM -0700, Baptiste Coudurier wrote:
>> Michael Niedermayer wrote:
>>> On Wed, Jul 23, 2008 at 08:35:49PM -0700, Baptiste Coudurier wrote:
>>>> Hi Michael,
>>>>
>>>> Michael Niedermayer wrote:
>>>>> On Tue, Jul 22, 2008 at 07:41:51PM -0700, Baptiste Coudurier wrote:
>>>>>> Hi,
>>>>>>
>>>>>> $subject,
>>>>>>
>>>>>> Reproduceable when trying to seek and input is non seekable (like http
>>>>>> through ffserver).
>>>>>>
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2705408, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2763520, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2818048, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2856192, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2889728, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 0, size 11469089, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2949120, flags 0
>>>>>> [flv @ 0x8e27eb0]skipping flv packet: type 32, size 2987264, flags 0
>>>>>>
>>>>>> With patch resync happens faster:
>>>>> I dont understand the problem, "trying to seek and input is non seekable"
>>>>> makes no sense to me. If the input is unseekable, seeking wont succeed
>>>>> anyway.
>>>> It will it when seeking forward, aviobuf.c:
>>>> } else if(s->is_streamed && !s->write_flag &&
>>>> offset1 >= 0 && offset1 < (s->buf_end - s->buffer) + (1<<16)){
>>> indeed
>>> this could be fixed by removing "offset1 < (s->buf_end - s->buffer) + (1<<16)"
>>> or increasing (1<<16)
>>> feel free to change that.
>>>
>> I checked more deeply and here comes patches.
>>
>> av_read_frame_flush needs to be done after seek in case of failure, this
>> hunk will be applied before and separately.
>>
>> url_fseek is checked for error, and when is_streamed is set but seeking
>> forward is not possible, return error.
>
> [...]
>
>> @@ -1465,14 +1466,14 @@
>> if (index < 0)
>> return -1;
>>
>> - av_read_frame_flush(s);
>> if (s->iformat->read_seek){
>> if(s->iformat->read_seek(s, stream_index, timestamp, flags) >= 0)
>> return 0;
>> }
>> ie = &st->index_entries[index];
>> if ((ret = url_fseek(s->pb, ie->pos, SEEK_SET)) < 0)
>> return ret;
>> + av_read_frame_flush(s);
>> av_update_cur_dts(s, st, ie->timestamp);
>>
>> return 0;
>
> Does this pass the regression tests?
Yes.
> What concerns me is that av_read_frame_flush() is not done anymore when
> s->iformat->read_seek is set and it succeeds
Yes, but I don't understand the code either, iformat->read_seek will be
called before
calling av_seek_frame_generic anyway, and it would have failed.
It seems to me that seeking internals needs to be cleaned up,
personnally I would not try generic seeking if native failed, and I even
sent a patch for this.
Also I also wondered what was "timestamp" supposed to be, dts or pts ?
Because mpeg ps returns dts for read_timestamps.
>> Index: libavformat/aviobuf.c
>> ===================================================================
>> --- libavformat/aviobuf.c (revision 14275)
>> +++ libavformat/aviobuf.c (working copy)
>> @@ -149,13 +149,17 @@
>> offset1 >= 0 && offset1 < (s->buf_end - s->buffer)) {
>> /* can do the seek inside the buffer */
>> s->buf_ptr = s->buffer + offset1;
>> - } else if(s->is_streamed && !s->write_flag &&
>> + } else if(s->is_streamed) {
>> + if (!s->write_flag &&
>> offset1 >= 0 && offset1 < (s->buf_end - s->buffer) + (1<<16)){
>> while(s->pos < offset && !s->eof_reached)
>> fill_buffer(s);
>> if (s->eof_reached)
>> return AVERROR(EPIPE);
>> s->buf_ptr = s->buf_end + offset - s->pos;
>> + } else {
>> + return AVERROR(EPIPE);
>> + }
>> } else {
>> offset_t res = AVERROR(EPIPE);
>
> This is not the correct solution i think.
> I think the code in the else below may be buggy when seek() fails, it can
> fail for non streamed things as well (network problems, old scratched cd...)
> I think moving
> s->buf_end = s->buffer;
> }
> s->buf_ptr = s->buffer;
>
> after
> if (!s->seek || (res = s->seek(s->opaque, offset, SEEK_SET)) < 0)
> return res;
>
> might help ?
>
I see, it works but seek regression tests fail:
Patch and regression diff attached.
--
Baptiste COUDURIER GnuPG Key Id: 0x5C1ABAAA
Smartjog USA Inc. http://www.smartjog.com
Key fingerprint 8D77134D20CC9220201FC5DB0AC9325C5C1ABAAA
-------------- next part --------------
A non-text attachment was scrubbed...
Name: url_fseek_fail.patch
Type: text/x-diff
Size: 788 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080727/3046b06b/attachment.patch>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: seek_regression.patch
Type: text/x-diff
Size: 28938 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20080727/3046b06b/attachment-0001.patch>
More information about the ffmpeg-devel
mailing list