diff options
author | Zhang Rui <bbcallen@gmail.com> | 2013-07-23 04:07:10 +0800 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2013-07-24 04:15:15 +0200 |
commit | 6bab3430a775183f2f9acbd91d1376c71e87c026 (patch) | |
tree | f16ffa6f1bd2e559158845b2a5e40f2e25f45139 | |
parent | 274a50ab57381c67946923acdf7ed6e2c7008790 (diff) | |
download | ffmpeg-6bab3430a775183f2f9acbd91d1376c71e87c026.tar.gz |
avformat/http: support reading compressed data
Derived from VLC's http module.
Original authors:
Antoine Cellerier <dionoea@videolan.org>
Sébastien Escudier <sebastien-devel@celeos.eu>
Rémi Duraffort <ivoire@videolan.org>
Rémi Denis-Courmont <remi@remlab.net>
Francois Cartegnie <fcvlcdev@free.fr>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavformat/http.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/libavformat/http.c b/libavformat/http.c index 0c26cd5eab..7b5b21ca88 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -29,6 +29,10 @@ #include "url.h" #include "libavutil/opt.h" +#if CONFIG_ZLIB +#include <zlib.h> +#endif + /* XXX: POST protocol is not completely implemented because ffmpeg uses only a subset of it. */ @@ -70,6 +74,11 @@ typedef struct { int icy; char *icy_metadata_headers; char *icy_metadata_packet; +#if CONFIG_ZLIB + int compressed; + z_stream inflate_stream; + uint8_t *inflate_buffer; +#endif } HTTPContext; #define OFFSET(x) offsetof(HTTPContext, x) @@ -396,6 +405,22 @@ static int process_line(URLContext *h, char *line, int line_count, return AVERROR(ENOMEM); av_freep(&s->icy_metadata_headers); s->icy_metadata_headers = buf; + } else if (!av_strcasecmp (tag, "Content-Encoding")) { + if (!av_strncasecmp(p, "gzip", 4) || !av_strncasecmp(p, "deflate", 7)) { +#if CONFIG_ZLIB + s->compressed = 1; + inflateEnd(&s->inflate_stream); + if (inflateInit2(&s->inflate_stream, 32 + 15) != Z_OK) + av_log(h, AV_LOG_WARNING, "Error during zlib initialisation: %s", + s->inflate_stream.msg); + if (zlibCompileFlags() & (1 << 17)) + av_log(h, AV_LOG_WARNING, "Your zlib was compiled without gzip support."); +#else + av_log(h, AV_LOG_WARNING, "Compressed(%s) content, need zlib support", p); +#endif + } + else + av_log(h, AV_LOG_WARNING, "Unknown content coding: %s", p); } } return 1; @@ -685,6 +710,38 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) return len; } +#if CONFIG_ZLIB +#define DECOMPRESS_BUF_SIZE (256 * 1024) +static int http_buf_read_compressed(URLContext *h, uint8_t *buf, int size) +{ + HTTPContext *s = h->priv_data; + int ret; + + if (!s->inflate_buffer) { + s->inflate_buffer = av_malloc(DECOMPRESS_BUF_SIZE); + if (!s->inflate_buffer) + return AVERROR(ENOMEM); + } + + if (s->inflate_stream.avail_in == 0) { + int read = http_buf_read(h, s->inflate_buffer, DECOMPRESS_BUF_SIZE); + if (read <= 0) + return read; + s->inflate_stream.next_in = s->inflate_buffer; + s->inflate_stream.avail_in = read; + } + + s->inflate_stream.avail_out = size; + s->inflate_stream.next_out = buf; + + ret = inflate(&s->inflate_stream, Z_SYNC_FLUSH); + if (ret != Z_OK && ret != Z_STREAM_END) + av_log(h, AV_LOG_WARNING, "inflate return value: %d, %s", ret, s->inflate_stream.msg); + + return size - s->inflate_stream.avail_out; +} +#endif + static int http_read(URLContext *h, uint8_t *buf, int size) { HTTPContext *s = h->priv_data; @@ -746,6 +803,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); } @@ -797,6 +858,11 @@ static int http_close(URLContext *h) int ret = 0; HTTPContext *s = h->priv_data; +#if CONFIG_ZLIB + inflateEnd(&s->inflate_stream); + av_freep(&s->inflate_buffer); +#endif + if (!s->end_chunked_post) { /* Close the write direction by sending the end of chunked encoding. */ ret = http_shutdown(h, h->flags); |