diff options
author | wm4 <nfxjfg@googlemail.com> | 2014-03-02 23:26:19 +0400 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-03-16 06:29:12 +0400 |
commit | facd3dbc6e0788f0e693a83e6ef16918b7eb960b (patch) | |
tree | 2acf4a7b8dba1edd4ac74a3db235d11fced7e8db /libavformat | |
parent | 8796c3b7d3e2904d7bc8ebfe261b53c263098935 (diff) |
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>
(cherry picked from commit 636273d3d4a8c42f51832e8bf83e566e875916bf)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 67f67a3748a038d880ed8a642184d2e3c76e29bb)
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavformat')
-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 26157677b1..388452ea6c 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -774,7 +774,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; } @@ -813,7 +812,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; @@ -848,6 +847,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) { @@ -855,17 +879,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; } @@ -874,11 +899,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 */ |