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

Anssi Hannula anssi.hannula at iki.fi
Mon Jul 25 22:13:03 EEST 2016


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.


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