[FFmpeg-cvslog] avformat/async: Fix bug where async could not recover after seek to eof

Bryan Huh git at videolan.org
Fri Nov 13 13:54:06 CET 2015

ffmpeg | branch: master | Bryan Huh <bryan at box.com> | Wed Nov 11 02:00:21 2015 -0800| [d07585f04add2448c9a8760ba263f7ac64c910c7] | committer: Michael Niedermayer

avformat/async: Fix bug where async could not recover after seek to eof

When async issues its inner seek via ffurl_seek, it treats failures as
EOF being reached. This is not consistent with the behavior of other
protocols (e.g. http, cache) which continue to tolerate reads after
failed seeks, and therefore does not interact correctly with them.

A common pattern where this manifests itself is where avio_seek is
called with pos to be the end-of-file - the http range-request would
fail here, and async would set io_eof_reached to 1. The background
thread would then refuse to read more bytes, and subsequent reads would
only empty the fifo and end in an error.

Presumably the code may have expected subsequent seeks to unset the
io_eof_reached but this is not guaranteed to be true - a subsequent seek
that lands in the AVIOContext's buffer (the fact that the
previously-failed avio_seek leaves the AVIOContext's buffer intact also
suggests that follow-up reads are expected to be tolerated) would not be
issued to the async_seek function, and when that buffer is drained only
async_read calls would follow, leading to the same error just described.

Signed-off-by: Michael Niedermayer <michael at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d07585f04add2448c9a8760ba263f7ac64c910c7

 libavformat/async.c |    7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/libavformat/async.c b/libavformat/async.c
index f4474b8..4308c4b 100644
--- a/libavformat/async.c
+++ b/libavformat/async.c
@@ -195,19 +195,16 @@ static void *async_buffer_task(void *arg)
         if (c->seek_request) {
             seek_ret = ffurl_seek(c->inner, c->seek_pos, c->seek_whence);
-            if (seek_ret < 0) {
-                c->io_eof_reached = 1;
-                c->io_error       = (int)seek_ret;
-            } else {
+            if (seek_ret >= 0) {
                 c->io_eof_reached = 0;
                 c->io_error       = 0;
+                ring_reset(ring);
             c->seek_completed = 1;
             c->seek_ret       = seek_ret;
             c->seek_request   = 0;
-            ring_reset(ring);

More information about the ffmpeg-cvslog mailing list