diff mbox

[FFmpeg-devel] libavformat: not treat 0 as EOF

Message ID 20171016091449.9220-1-daniel.kucera@gmail.com
State Superseded
Headers show

Commit Message

Daniel Kucera Oct. 16, 2017, 9:14 a.m. UTC
transfer_func variable passed to retry_transfer_wrapper
are h->prot->url_read and h->prot->url_write functions.
These need to return EOF or other error properly.
In case of returning >= 0, url_read/url_write is retried
until error is returned.

Signed-off-by: Daniel Kucera <daniel.kucera@gmail.com>
---
 libavformat/avio.c    |  6 ++++--
 libavformat/aviobuf.c | 20 ++++++++++++--------
 libavformat/cache.c   |  4 ++--
 libavformat/concat.c  |  9 +++++----
 4 files changed, 23 insertions(+), 16 deletions(-)

Comments

Michael Niedermayer Oct. 17, 2017, 12:13 a.m. UTC | #1
On Mon, Oct 16, 2017 at 11:14:49AM +0200, Daniel Kucera wrote:
> transfer_func variable passed to retry_transfer_wrapper
> are h->prot->url_read and h->prot->url_write functions.
> These need to return EOF or other error properly.
> In case of returning >= 0, url_read/url_write is retried
> until error is returned.
> 
> Signed-off-by: Daniel Kucera <daniel.kucera@gmail.com>
> ---
>  libavformat/avio.c    |  6 ++++--
>  libavformat/aviobuf.c | 20 ++++++++++++--------
>  libavformat/cache.c   |  4 ++--
>  libavformat/concat.c  |  9 +++++----
>  4 files changed, 23 insertions(+), 16 deletions(-)

this seems to break http

./ffmpeg -i matrixbench_mpeg2.mpg -listen 1 -f nut http://127.0.0.1:8889 </dev/null & sleep 1 ; ./ffmpeg -i http://127.0.0.1:8889 -c copy -y out-http.nut

above never exits

[...]
James Almer Oct. 17, 2017, 2:48 a.m. UTC | #2
On 10/16/2017 9:13 PM, Michael Niedermayer wrote:
> On Mon, Oct 16, 2017 at 11:14:49AM +0200, Daniel Kucera wrote:
>> transfer_func variable passed to retry_transfer_wrapper
>> are h->prot->url_read and h->prot->url_write functions.
>> These need to return EOF or other error properly.
>> In case of returning >= 0, url_read/url_write is retried
>> until error is returned.
>>
>> Signed-off-by: Daniel Kucera <daniel.kucera@gmail.com>
>> ---
>>  libavformat/avio.c    |  6 ++++--
>>  libavformat/aviobuf.c | 20 ++++++++++++--------
>>  libavformat/cache.c   |  4 ++--
>>  libavformat/concat.c  |  9 +++++----
>>  4 files changed, 23 insertions(+), 16 deletions(-)
> 
> this seems to break http
> 
> ./ffmpeg -i matrixbench_mpeg2.mpg -listen 1 -f nut http://127.0.0.1:8889 </dev/null & sleep 1 ; ./ffmpeg -i http://127.0.0.1:8889 -c copy -y out-http.nut
> 
> above never exits

http.c has a call to ffurl_read() where the check for the return value
should apparently be adapted. In fact, several other files call that
function as well.
diff mbox

Patch

diff --git a/libavformat/avio.c b/libavformat/avio.c
index 64248e098b..d3004c007f 100644
--- a/libavformat/avio.c
+++ b/libavformat/avio.c
@@ -391,8 +391,10 @@  static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
                 }
                 av_usleep(1000);
             }
-        } else if (ret < 1)
-            return (ret < 0 && ret != AVERROR_EOF) ? ret : len;
+        } else if (ret == AVERROR_EOF)
+	    return (len > 0) ? len : AVERROR_EOF;
+        else if (ret < 0)
+            return ret;
         if (ret) {
             fast_retries = FFMAX(fast_retries, 2);
             wait_since = 0;
diff --git a/libavformat/aviobuf.c b/libavformat/aviobuf.c
index 636cb46161..0d4eb051e1 100644
--- a/libavformat/aviobuf.c
+++ b/libavformat/aviobuf.c
@@ -572,13 +572,14 @@  static void fill_buffer(AVIOContext *s)
     if (s->read_packet)
         len = s->read_packet(s->opaque, dst, len);
     else
-        len = 0;
-    if (len <= 0) {
+        len = AVERROR_EOF;
+    if (len == AVERROR_EOF) {
         /* do not modify buffer if EOF reached so that a seek back can
            be done without rereading data */
         s->eof_reached = 1;
-        if (len < 0)
-            s->error = len;
+    } else if (len < 0) {
+        s->eof_reached = 1;
+        s->error= len;
     } else {
         s->pos += len;
         s->buf_ptr = dst;
@@ -646,13 +647,16 @@  int avio_read(AVIOContext *s, unsigned char *buf, int size)
                 // bypass the buffer and read data directly into buf
                 if(s->read_packet)
                     len = s->read_packet(s->opaque, buf, size);
-
-                if (len <= 0) {
+                else
+                    len = AVERROR_EOF;
+                if (len == AVERROR_EOF) {
                     /* do not modify buffer if EOF reached so that a seek back can
                     be done without rereading data */
                     s->eof_reached = 1;
-                    if(len<0)
-                        s->error= len;
+                    break;
+                } else if (len < 0) {
+                    s->eof_reached = 1;
+                    s->error= len;
                     break;
                 } else {
                     s->pos += len;
diff --git a/libavformat/cache.c b/libavformat/cache.c
index 6aabca2e78..66bbbf54c9 100644
--- a/libavformat/cache.c
+++ b/libavformat/cache.c
@@ -201,7 +201,7 @@  static int cache_read(URLContext *h, unsigned char *buf, int size)
     }
 
     r = ffurl_read(c->inner, buf, size);
-    if (r == 0 && size>0) {
+    if (r == AVERROR_EOF && size>0) {
         c->is_true_eof = 1;
         av_assert0(c->end >= c->logical_pos);
     }
@@ -263,7 +263,7 @@  resolve_eof:
                 if (whence == SEEK_SET)
                     size = FFMIN(sizeof(tmp), pos - c->logical_pos);
                 ret = cache_read(h, tmp, size);
-                if (ret == 0 && whence == SEEK_END) {
+                if (ret == AVERROR_EOF && whence == SEEK_END) {
                     av_assert0(c->is_true_eof);
                     goto resolve_eof;
                 }
diff --git a/libavformat/concat.c b/libavformat/concat.c
index 46b520fe80..36dbc3c5a7 100644
--- a/libavformat/concat.c
+++ b/libavformat/concat.c
@@ -135,19 +135,20 @@  static int concat_read(URLContext *h, unsigned char *buf, int size)
 
     while (size > 0) {
         result = ffurl_read(nodes[i].uc, buf, size);
-        if (result < 0)
-            return total ? total : result;
-        if (!result) {
+        if (result == AVERROR_EOF) {
             if (i + 1 == data->length ||
                 ffurl_seek(nodes[++i].uc, 0, SEEK_SET) < 0)
                 break;
+	    result = 0;
         }
+        if (result < 0)
+            return total ? total : result;
         total += result;
         buf   += result;
         size  -= result;
     }
     data->current = i;
-    return total;
+    return total ? total : result;
 }
 
 static int64_t concat_seek(URLContext *h, int64_t pos, int whence)