summaryrefslogtreecommitdiff
path: root/libavformat/http.c
diff options
context:
space:
mode:
authorZhang Rui <bbcallen@gmail.com>2013-07-23 04:07:10 +0800
committerMichael Niedermayer <michaelni@gmx.at>2013-07-24 04:15:15 +0200
commit6bab3430a775183f2f9acbd91d1376c71e87c026 (patch)
treef16ffa6f1bd2e559158845b2a5e40f2e25f45139 /libavformat/http.c
parent274a50ab57381c67946923acdf7ed6e2c7008790 (diff)
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>
Diffstat (limited to 'libavformat/http.c')
-rw-r--r--libavformat/http.c66
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);