[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