diff options
author | Clément Bœsch <ubitux@gmail.com> | 2012-04-03 01:33:03 +0200 |
---|---|---|
committer | Clément Bœsch <ubitux@gmail.com> | 2012-04-03 19:12:52 +0200 |
commit | 588eaa106d8dd0ebce9d2e903aa0a1bbe022c988 (patch) | |
tree | 05053c0b72375d33b838eb95c2e717ad9f54c46d | |
parent | 38477e1981a7729b02d9a2f45142c53dc78625fe (diff) | |
download | ffmpeg-588eaa106d8dd0ebce9d2e903aa0a1bbe022c988.tar.gz |
swfdec: support compressed swf.
-rw-r--r-- | libavformat/swf.h | 11 | ||||
-rw-r--r-- | libavformat/swfdec.c | 76 |
2 files changed, 83 insertions, 4 deletions
diff --git a/libavformat/swf.h b/libavformat/swf.h index affebe9c73..8a99c9624d 100644 --- a/libavformat/swf.h +++ b/libavformat/swf.h @@ -23,6 +23,10 @@ #ifndef AVFORMAT_SWF_H #define AVFORMAT_SWF_H +#if CONFIG_ZLIB +#include <zlib.h> +#endif + #include "libavutil/fifo.h" #include "avformat.h" #include "avio.h" @@ -76,6 +80,13 @@ typedef struct { int tag; AVFifoBuffer *audio_fifo; AVCodecContext *audio_enc, *video_enc; +#if CONFIG_ZLIB + AVIOContext *zpb; +#define ZBUF_SIZE 4096 + uint8_t *zbuf_in; + uint8_t *zbuf_out; + z_stream zstream; +#endif } SWFContext; static const AVCodecTag swf_codec_tags[] = { diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index 4a2c3d5403..10a2ed733a 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -52,6 +52,39 @@ static int swf_probe(AVProbeData *p) return 0; } +#if CONFIG_ZLIB +static int zlib_refill(void *opaque, uint8_t *buf, int buf_size) +{ + AVFormatContext *s = opaque; + SWFContext *swf = s->priv_data; + z_stream *z = &swf->zstream; + int ret; + +retry: + if (!z->avail_in) { + int n = avio_read(s->pb, swf->zbuf_in, ZBUF_SIZE); + if (n <= 0) + return n; + z->next_in = swf->zbuf_in; + z->avail_in = n; + } + + z->next_out = buf; + z->avail_out = buf_size; + + ret = inflate(z, Z_NO_FLUSH); + if (ret < 0) + return AVERROR(EINVAL); + if (ret == Z_STREAM_END) + return AVERROR_EOF; + + if (buf_size - z->avail_out == 0) + goto retry; + + return buf_size - z->avail_out; +} +#endif + static int swf_read_header(AVFormatContext *s) { SWFContext *swf = s->priv_data; @@ -59,14 +92,29 @@ static int swf_read_header(AVFormatContext *s) int nbits, len, tag; tag = avio_rb32(pb) & 0xffffff00; + avio_rl32(pb); if (tag == MKBETAG('C', 'W', 'S', 0)) { - av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n"); + av_log(s, AV_LOG_INFO, "SWF compressed file detected\n"); +#if CONFIG_ZLIB + swf->zbuf_in = av_malloc(ZBUF_SIZE); + swf->zbuf_out = av_malloc(ZBUF_SIZE); + swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s, + zlib_refill, NULL, NULL); + if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb) + return AVERROR(ENOMEM); + swf->zpb->seekable = 0; + if (inflateInit(&swf->zstream) != Z_OK) { + av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n"); + return AVERROR(EINVAL); + } + pb = swf->zpb; +#else + av_log(s, AV_LOG_ERROR, "zlib support is required to read SWF compressed files\n"); return AVERROR(EIO); - } - if (tag != MKBETAG('F', 'W', 'S', 0)) +#endif + } else if (tag != MKBETAG('F', 'W', 'S', 0)) return AVERROR(EIO); - avio_rl32(pb); /* skip rectangle size */ nbits = avio_r8(pb) >> 3; len = (4 * nbits - 3 + 7) / 8; @@ -86,6 +134,11 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) AVStream *vst = NULL, *ast = NULL, *st = 0; int tag, len, i, frame, v, res; +#if CONFIG_ZLIB + if (swf->zpb) + pb = swf->zpb; +#endif + for(;;) { uint64_t pos = avio_tell(pb); tag = get_swf_tag(pb, &len); @@ -209,6 +262,18 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) } } +#if CONFIG_ZLIB +static av_cold int swf_read_close(AVFormatContext *avctx) +{ + SWFContext *s = avctx->priv_data; + inflateEnd(&s->zstream); + av_freep(&s->zbuf_in); + av_freep(&s->zbuf_out); + av_freep(&s->zpb); + return 0; +} +#endif + AVInputFormat ff_swf_demuxer = { .name = "swf", .long_name = NULL_IF_CONFIG_SMALL("Flash format"), @@ -216,4 +281,7 @@ AVInputFormat ff_swf_demuxer = { .read_probe = swf_probe, .read_header = swf_read_header, .read_packet = swf_read_packet, +#if CONFIG_ZLIB + .read_close = swf_read_close, +#endif }; |