From 7570c9e04f010c9b3bfdeb4338d330f2cdd25278 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20B=C5=93sch?= Date: Wed, 2 Dec 2015 18:41:00 -0500 Subject: [PATCH] swfdec: support compressed swf Signed-off-by: Vittorio Giovara --- Changelog | 1 + configure | 1 + libavformat/swf.h | 13 +++++++ libavformat/swfdec.c | 86 +++++++++++++++++++++++++++++++++++++++++--- 4 files changed, 97 insertions(+), 4 deletions(-) diff --git a/Changelog b/Changelog index 675288effc..92c694bcca 100644 --- a/Changelog +++ b/Changelog @@ -50,6 +50,7 @@ version : - support encoding 16-bit RLE SGI images - support Apple AVFoundation video capture - G.723.1 muxer and encoder +- compressed SWF version 11: diff --git a/configure b/configure index 23e4037bff..d44fa08449 100755 --- a/configure +++ b/configure @@ -2256,6 +2256,7 @@ sdp_demuxer_select="rtpdec" smoothstreaming_muxer_select="ismv_muxer" spdif_muxer_select="aac_parser" spx_muxer_select="ogg_muxer" +swf_demuxer_suggest="zlib" tak_demuxer_select="tak_parser" tg2_muxer_select="mov_muxer" tgp_muxer_select="mov_muxer" diff --git a/libavformat/swf.h b/libavformat/swf.h index 8eb3f70541..f18aa7cc58 100644 --- a/libavformat/swf.h +++ b/libavformat/swf.h @@ -23,6 +23,12 @@ #ifndef AVFORMAT_SWF_H #define AVFORMAT_SWF_H +#include "config.h" + +#if CONFIG_ZLIB +#include +#endif + #include "libavutil/fifo.h" #include "avformat.h" #include "avio.h" @@ -77,6 +83,13 @@ typedef struct SWFContext { AVFifoBuffer *audio_fifo; AVCodecContext *audio_enc, *video_enc; AVStream *video_st; +#if CONFIG_ZLIB +#define ZBUF_SIZE 4096 + AVIOContext *zpb; + uint8_t *zbuf_in; + uint8_t *zbuf_out; + z_stream zstream; +#endif } SWFContext; extern const AVCodecTag ff_swf_codec_tags[]; diff --git a/libavformat/swfdec.c b/libavformat/swfdec.c index d7a53145c6..7b5cd358ba 100644 --- a/libavformat/swfdec.c +++ b/libavformat/swfdec.c @@ -20,6 +20,12 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "config.h" + +#if CONFIG_ZLIB +#include +#endif + #include "libavutil/channel_layout.h" #include "libavutil/intreadwrite.h" #include "swf.h" @@ -61,6 +67,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 != Z_OK && ret != Z_STREAM_END) { + av_log(s, AV_LOG_ERROR, "Inflate error: %d\n", ret); + return AVERROR_UNKNOWN; + } + + 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; @@ -68,14 +107,33 @@ 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, "Compressed SWF file detected\n"); +#if CONFIG_ZLIB + if (inflateInit(&swf->zstream) != Z_OK) { + av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n"); + return AVERROR(EINVAL); + } + 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) { + av_freep(&swf->zbuf_in); + av_freep(&swf->zbuf_out); + av_freep(&swf->zpb); + return AVERROR(ENOMEM); + } + swf->zpb->seekable = 0; + pb = swf->zpb; +#else + av_log(s, AV_LOG_ERROR, "missing zlib support, unable to open\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; @@ -95,6 +153,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); @@ -240,6 +303,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("SWF (ShockWave Flash)"), @@ -247,4 +322,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 };