diff options
author | wm4 <nfxjfg@googlemail.com> | 2014-03-02 20:26:19 +0100 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-03-05 22:49:36 +0100 |
commit | 636273d3d4a8c42f51832e8bf83e566e875916bf (patch) | |
tree | eefc02e9ac0447a48a0d578566d9b1c9fed19e23 | |
parent | 9deecdf85f0c1cebcc0a157114bf6dbc02a0a120 (diff) | |
download | ffmpeg-636273d3d4a8c42f51832e8bf83e566e875916bf.tar.gz |
http: handle ICY in presence of chunked transfer encoding
Some http servers send an ICY stream in combination with chunked
transfer encoding. This case was handled incorrectly by the ICY code:
instead of handling chunked encoding before anything ICY related, both
were mixed.
Fix this by separating the ICY code from normal http reading. Move the
normal http reading to a new function http_read_stream(), while
http_read() handles ICY on top of http_read_stream().
The server identified itself as: cloudflare-nginx
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/http.c | 54 |
1 files changed, 39 insertions, 15 deletions
diff --git a/libavformat/http.c b/libavformat/http.c index 69c4d6d7a0..7a0ba6cedd 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -768,7 +768,6 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) } if (len > 0) { s->off += len; - s->icy_data_read += len; if (s->chunksize > 0) s->chunksize -= len; } @@ -807,7 +806,7 @@ static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size) } #endif -static int http_read(URLContext *h, uint8_t *buf, int size) +static int http_read_stream(URLContext *h, uint8_t *buf, int size) { HTTPContext *s = h->priv_data; int err, new_location; @@ -842,6 +841,31 @@ static int http_read(URLContext *h, uint8_t *buf, int size) } size = FFMIN(size, s->chunksize); } +#if CONFIG_ZLIB + if (s->compressed) + return http_buf_read_compressed(h, buf, size); +#endif + return http_buf_read(h, buf, size); +} + +// Like http_read_stream(), but no short reads. +// Assumes partial reads are an error. +static int http_read_stream_all(URLContext *h, uint8_t *buf, int size) +{ + int pos = 0; + while (pos < size) { + int len = http_read_stream(h, buf + pos, size - pos); + if (len < 0) + return len; + pos += len; + } + return pos; +} + +static int http_read(URLContext *h, uint8_t *buf, int size) +{ + HTTPContext *s = h->priv_data; + if (s->icy_metaint > 0) { int remaining = s->icy_metaint - s->icy_data_read; /* until next metadata packet */ if (!remaining) { @@ -849,17 +873,18 @@ static int http_read(URLContext *h, uint8_t *buf, int size) // which sets the length of the packet (divided by 16). If it's 0, // the metadata doesn't change. After the packet, icy_metaint bytes // of normal data follow. - int ch = http_getc(s); - if (ch < 0) - return ch; + uint8_t ch; + int len = http_read_stream_all(h, &ch, 1); + if (len < 1) + return len; if (ch > 0) { char data[255 * 16 + 1]; - int n; int ret; - ch *= 16; - for (n = 0; n < ch; n++) - data[n] = http_getc(s); - data[ch + 1] = 0; + len = ch * 16; + ret = http_read_stream_all(h, data, len); + if (ret < len) + return ret; + data[len + 1] = 0; if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0) return ret; } @@ -868,11 +893,10 @@ static int http_read(URLContext *h, uint8_t *buf, int size) } size = FFMIN(size, remaining); } -#if CONFIG_ZLIB - if (s->compressed) - return http_buf_read_compressed(h, buf, size); -#endif - return http_buf_read(h, buf, size); + size = http_read_stream(h, buf, size); + if (size > 0) + s->icy_data_read += size; + return size; } /* used only when posting data */ |