Commit 6bab3430 authored by Zhang Rui's avatar Zhang Rui Committed by Michael Niedermayer

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: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 274a50ab
...@@ -29,6 +29,10 @@ ...@@ -29,6 +29,10 @@
#include "url.h" #include "url.h"
#include "libavutil/opt.h" #include "libavutil/opt.h"
#if CONFIG_ZLIB
#include <zlib.h>
#endif
/* XXX: POST protocol is not completely implemented because ffmpeg uses /* XXX: POST protocol is not completely implemented because ffmpeg uses
only a subset of it. */ only a subset of it. */
...@@ -70,6 +74,11 @@ typedef struct { ...@@ -70,6 +74,11 @@ typedef struct {
int icy; int icy;
char *icy_metadata_headers; char *icy_metadata_headers;
char *icy_metadata_packet; char *icy_metadata_packet;
#if CONFIG_ZLIB
int compressed;
z_stream inflate_stream;
uint8_t *inflate_buffer;
#endif
} HTTPContext; } HTTPContext;
#define OFFSET(x) offsetof(HTTPContext, x) #define OFFSET(x) offsetof(HTTPContext, x)
...@@ -396,6 +405,22 @@ static int process_line(URLContext *h, char *line, int line_count, ...@@ -396,6 +405,22 @@ static int process_line(URLContext *h, char *line, int line_count,
return AVERROR(ENOMEM); return AVERROR(ENOMEM);
av_freep(&s->icy_metadata_headers); av_freep(&s->icy_metadata_headers);
s->icy_metadata_headers = buf; 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; return 1;
...@@ -685,6 +710,38 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size) ...@@ -685,6 +710,38 @@ static int http_buf_read(URLContext *h, uint8_t *buf, int size)
return len; 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) static int http_read(URLContext *h, uint8_t *buf, int size)
{ {
HTTPContext *s = h->priv_data; HTTPContext *s = h->priv_data;
...@@ -746,6 +803,10 @@ static int http_read(URLContext *h, uint8_t *buf, int size) ...@@ -746,6 +803,10 @@ static int http_read(URLContext *h, uint8_t *buf, int size)
} }
size = FFMIN(size, remaining); 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); return http_buf_read(h, buf, size);
} }
...@@ -797,6 +858,11 @@ static int http_close(URLContext *h) ...@@ -797,6 +858,11 @@ static int http_close(URLContext *h)
int ret = 0; int ret = 0;
HTTPContext *s = h->priv_data; HTTPContext *s = h->priv_data;
#if CONFIG_ZLIB
inflateEnd(&s->inflate_stream);
av_freep(&s->inflate_buffer);
#endif
if (!s->end_chunked_post) { if (!s->end_chunked_post) {
/* Close the write direction by sending the end of chunked encoding. */ /* Close the write direction by sending the end of chunked encoding. */
ret = http_shutdown(h, h->flags); ret = http_shutdown(h, h->flags);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment