You've already forked FFmpeg
							
							
				mirror of
				https://github.com/FFmpeg/FFmpeg.git
				synced 2025-10-30 23:18:11 +02:00 
			
		
		
		
	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:
		| @@ -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 */ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user