From 858db4b01fa2b55ee55056c033054ca54ac9b0fd Mon Sep 17 00:00:00 2001 From: Daniel Kucera Date: Tue, 17 Oct 2017 10:29:30 +0200 Subject: [PATCH] libavformat: not treat 0 as EOF 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 --- libavformat/avio.c | 6 ++++-- libavformat/aviobuf.c | 20 ++++++++++++-------- libavformat/cache.c | 4 ++-- libavformat/concat.c | 9 +++++---- libavformat/http.c | 5 ++++- 5 files changed, 27 insertions(+), 17 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index 64248e098b..4718753b7b 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..19c83c309a 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) diff --git a/libavformat/http.c b/libavformat/http.c index 668cd51986..bd9148f45d 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -1296,8 +1296,11 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) "Chunked encoding data size: %"PRIu64"'\n", s->chunksize); - if (!s->chunksize) + if (!s->chunksize) { + av_log(h, AV_LOG_DEBUG, "Last chunk received, closing conn\n"); + ffurl_closep(&s->hd); return 0; + } else if (s->chunksize == UINT64_MAX) { av_log(h, AV_LOG_ERROR, "Invalid chunk size %"PRIu64"\n", s->chunksize);