[FFmpeg-devel] avio starting offset and hls regression in 3.1

Anssi Hannula anssi.hannula at iki.fi
Tue Jul 26 16:22:26 EEST 2016


25.07.2016, 22:13, Anssi Hannula kirjoitti:
> Hi all,
> 
> Commit d0fc5de3a643fe7f974ed14e410c2ac2f4147d7e [1] merged in
> commit 81306fd4bdeb5c17d4db771e4fec684773b5790f "hls: eliminate ffurl_*
> usage" from libav, which changed the hls demuxer to use AVIOContext
> instead of URLContext for its HTTP requests.
> 
> HLS demuxer uses the "offset" option for the http demuxer, requesting
> the initial file offset for the I/O (http URLProtocol uses the "Range:"
> HTTP header to try to accommodate that).
> 
> However, the code in libavformat/aviobuf.c seems to be doing its own
> accounting for the current file offset (AVIOContext.pos), with the
> assumption that the initial offset is always zero.
> 
> HLS demuxer does an explicit seek after open_url to account for cases
> where the "offset" was not effective (due to the URL being a local file
> or the HTTP server not obeying it), which should be a no-op in case the
> file offset is already at that position.
> 
> However, since aviobuf.c code thinks the starting offset is 0, this
> doesn't work properly.
> 
> E.g. this command, which worked fine in FFmpeg 3.0, now fails after
> approx. 10 seconds of playback:
> ffplay
> https://devimages.apple.com.edgekey.net/streaming/examples/bipbop_16x9/bipbop_16x9_variant.m3u8
> 
> 
> Now, what should be done to fix this regression?
> 
> I guess there are at least these options:
> 
> 1. Make aviobuf.c call seek() to check the offset after open:
> 
> --- a/libavformat/aviobuf.c
> +++ b/libavformat/aviobuf.c
> @@ -913,6 +913,14 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
>          (*s)->read_pause = io_read_pause;
>          (*s)->read_seek  = io_read_seek;
>      }
> +
> +    /* get initial buffer position (may be non-zero with e.g. offset
> option for http) */
> +    if ((*s)->seek) {
> +        int64_t pos = (*s)->seek((*s)->opaque, 0, SEEK_CUR);
> +        if (pos >= 0)
> +            (*s)->pos = pos;
> +    }
> +
>      (*s)->av_class = &ff_avio_class;
>      return 0;
>  fail:
> 
> I guess that has a high chance of further regressions (*if* it is even
> correct), though, as I guess there may be seek() handlers that don't
> have SEEK_CUR = 0 as a no-op.
> 
> 2. Revert the commit. I'm not familiar enough (or I've just forgotten
> that stuff) with avio/ffurl to know how big the benefit of using avio_
> instead of ffurl_ is, though...
> 
> 3. Drop the seek call from HLS demuxer in case protocol is http*, and
> assume the HTTP server obeyed the ranged request.

After thinking about it a bit, I think I'll go with this 3rd one to fix
the regression, unless a better idea surfaces.

It is quite trivial to implement, and server obeying ranged requests is
mandatory anyway in HLS specs when byte-ranged segments are used - the
failure mode in the non-spec-compliant will just be a bit different.

> 
> Any other ideas / opinions for the course of action?
> 
> 
> [1] https://github.com/FFmpeg/FFmpeg/commit/d0fc5de3a643fe7f974ed14
> 


-- 
Anssi Hannula


More information about the ffmpeg-devel mailing list