swfdec: support compressed swf
authorClément Bœsch <ubitux@gmail.com>
Wed, 2 Dec 2015 23:41:00 +0000 (18:41 -0500)
committerVittorio Giovara <vittorio.giovara@gmail.com>
Mon, 11 Jan 2016 20:32:56 +0000 (15:32 -0500)
Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
Changelog
configure
libavformat/swf.h
libavformat/swfdec.c

index 675288e..92c694b 100644 (file)
--- a/Changelog
+++ b/Changelog
@@ -50,6 +50,7 @@ version <next>:
 - support encoding 16-bit RLE SGI images
 - support Apple AVFoundation video capture
 - G.723.1 muxer and encoder
 - support encoding 16-bit RLE SGI images
 - support Apple AVFoundation video capture
 - G.723.1 muxer and encoder
+- compressed SWF
 
 
 version 11:
 
 
 version 11:
index 23e4037..d44fa08 100755 (executable)
--- 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"
 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"
 tak_demuxer_select="tak_parser"
 tg2_muxer_select="mov_muxer"
 tgp_muxer_select="mov_muxer"
index 8eb3f70..f18aa7c 100644 (file)
 #ifndef AVFORMAT_SWF_H
 #define AVFORMAT_SWF_H
 
 #ifndef AVFORMAT_SWF_H
 #define AVFORMAT_SWF_H
 
+#include "config.h"
+
+#if CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
 #include "libavutil/fifo.h"
 #include "avformat.h"
 #include "avio.h"
 #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;
     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[];
 } SWFContext;
 
 extern const AVCodecTag ff_swf_codec_tags[];
index d7a5314..7b5cd35 100644 (file)
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include "config.h"
+
+#if CONFIG_ZLIB
+#include <zlib.h>
+#endif
+
 #include "libavutil/channel_layout.h"
 #include "libavutil/intreadwrite.h"
 #include "swf.h"
 #include "libavutil/channel_layout.h"
 #include "libavutil/intreadwrite.h"
 #include "swf.h"
@@ -61,6 +67,39 @@ static int swf_probe(AVProbeData *p)
         return 0;
 }
 
         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;
 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;
     int nbits, len, tag;
 
     tag = avio_rb32(pb) & 0xffffff00;
+    avio_rl32(pb);
 
     if (tag == MKBETAG('C', 'W', 'S', 0)) {
 
     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);
         return AVERROR(EIO);
-    }
-    if (tag != MKBETAG('F', 'W', 'S', 0))
+#endif
+    } else if (tag != MKBETAG('F', 'W', 'S', 0))
         return AVERROR(EIO);
         return AVERROR(EIO);
-    avio_rl32(pb);
     /* skip rectangle size */
     nbits = avio_r8(pb) >> 3;
     len = (4 * nbits - 3 + 7) / 8;
     /* 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;
 
     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);
     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)"),
 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,
     .read_probe     = swf_probe,
     .read_header    = swf_read_header,
     .read_packet    = swf_read_packet,
+#if CONFIG_ZLIB
+    .read_close     = swf_read_close,
+#endif
 };
 };