mirror of https://git.ffmpeg.org/ffmpeg.git
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>
This commit is contained in:
parent
9deecdf85f
commit
636273d3d4
|
@ -768,7 +768,6 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size)
|
||||||
}
|
}
|
||||||
if (len > 0) {
|
if (len > 0) {
|
||||||
s->off += len;
|
s->off += len;
|
||||||
s->icy_data_read += len;
|
|
||||||
if (s->chunksize > 0)
|
if (s->chunksize > 0)
|
||||||
s->chunksize -= len;
|
s->chunksize -= len;
|
||||||
}
|
}
|
||||||
|
@ -807,7 +806,7 @@ static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size)
|
||||||
}
|
}
|
||||||
#endif
|
#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;
|
HTTPContext *s = h->priv_data;
|
||||||
int err, new_location;
|
int err, new_location;
|
||||||
|
@ -842,6 +841,31 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
|
||||||
}
|
}
|
||||||
size = FFMIN(size, s->chunksize);
|
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) {
|
if (s->icy_metaint > 0) {
|
||||||
int remaining = s->icy_metaint - s->icy_data_read; /* until next metadata packet */
|
int remaining = s->icy_metaint - s->icy_data_read; /* until next metadata packet */
|
||||||
if (!remaining) {
|
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,
|
// 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
|
// the metadata doesn't change. After the packet, icy_metaint bytes
|
||||||
// of normal data follow.
|
// of normal data follow.
|
||||||
int ch = http_getc(s);
|
uint8_t ch;
|
||||||
if (ch < 0)
|
int len = http_read_stream_all(h, &ch, 1);
|
||||||
return ch;
|
if (len < 1)
|
||||||
|
return len;
|
||||||
if (ch > 0) {
|
if (ch > 0) {
|
||||||
char data[255 * 16 + 1];
|
char data[255 * 16 + 1];
|
||||||
int n;
|
|
||||||
int ret;
|
int ret;
|
||||||
ch *= 16;
|
len = ch * 16;
|
||||||
for (n = 0; n < ch; n++)
|
ret = http_read_stream_all(h, data, len);
|
||||||
data[n] = http_getc(s);
|
if (ret < len)
|
||||||
data[ch + 1] = 0;
|
return ret;
|
||||||
|
data[len + 1] = 0;
|
||||||
if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
|
if ((ret = av_opt_set(s, "icy_metadata_packet", data, 0)) < 0)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -868,11 +893,10 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
|
||||||
}
|
}
|
||||||
size = FFMIN(size, remaining);
|
size = FFMIN(size, remaining);
|
||||||
}
|
}
|
||||||
#if CONFIG_ZLIB
|
size = http_read_stream(h, buf, size);
|
||||||
if (s->compressed)
|
if (size > 0)
|
||||||
return http_buf_read_compressed(h, buf, size);
|
s->icy_data_read += size;
|
||||||
#endif
|
return size;
|
||||||
return http_buf_read(h, buf, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* used only when posting data */
|
/* used only when posting data */
|
||||||
|
|
Loading…
Reference in New Issue