Browse code

swfdec: support compressed swf

Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>

Clément Bœsch authored on 2015/12/03 08:41:00
Showing 4 changed files
... ...
@@ -50,6 +50,7 @@ version <next>:
50 50
 - support encoding 16-bit RLE SGI images
51 51
 - support Apple AVFoundation video capture
52 52
 - G.723.1 muxer and encoder
53
+- compressed SWF
53 54
 
54 55
 
55 56
 version 11:
... ...
@@ -2256,6 +2256,7 @@ sdp_demuxer_select="rtpdec"
2256 2256
 smoothstreaming_muxer_select="ismv_muxer"
2257 2257
 spdif_muxer_select="aac_parser"
2258 2258
 spx_muxer_select="ogg_muxer"
2259
+swf_demuxer_suggest="zlib"
2259 2260
 tak_demuxer_select="tak_parser"
2260 2261
 tg2_muxer_select="mov_muxer"
2261 2262
 tgp_muxer_select="mov_muxer"
... ...
@@ -23,6 +23,12 @@
23 23
 #ifndef AVFORMAT_SWF_H
24 24
 #define AVFORMAT_SWF_H
25 25
 
26
+#include "config.h"
27
+
28
+#if CONFIG_ZLIB
29
+#include <zlib.h>
30
+#endif
31
+
26 32
 #include "libavutil/fifo.h"
27 33
 #include "avformat.h"
28 34
 #include "avio.h"
... ...
@@ -77,6 +83,13 @@ typedef struct SWFContext {
77 77
     AVFifoBuffer *audio_fifo;
78 78
     AVCodecContext *audio_enc, *video_enc;
79 79
     AVStream *video_st;
80
+#if CONFIG_ZLIB
81
+#define ZBUF_SIZE 4096
82
+    AVIOContext *zpb;
83
+    uint8_t *zbuf_in;
84
+    uint8_t *zbuf_out;
85
+    z_stream zstream;
86
+#endif
80 87
 } SWFContext;
81 88
 
82 89
 extern const AVCodecTag ff_swf_codec_tags[];
... ...
@@ -20,6 +20,12 @@
20 20
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 21
  */
22 22
 
23
+#include "config.h"
24
+
25
+#if CONFIG_ZLIB
26
+#include <zlib.h>
27
+#endif
28
+
23 29
 #include "libavutil/channel_layout.h"
24 30
 #include "libavutil/intreadwrite.h"
25 31
 #include "swf.h"
... ...
@@ -61,6 +67,39 @@ static int swf_probe(AVProbeData *p)
61 61
         return 0;
62 62
 }
63 63
 
64
+#if CONFIG_ZLIB
65
+static int zlib_refill(void *opaque, uint8_t *buf, int buf_size)
66
+{
67
+    AVFormatContext *s = opaque;
68
+    SWFContext *swf = s->priv_data;
69
+    z_stream *z = &swf->zstream;
70
+    int ret;
71
+
72
+retry:
73
+    if (!z->avail_in) {
74
+        int n = avio_read(s->pb, swf->zbuf_in, ZBUF_SIZE);
75
+        if (n < 0)
76
+            return n;
77
+        z->next_in  = swf->zbuf_in;
78
+        z->avail_in = n;
79
+    }
80
+
81
+    z->next_out  = buf;
82
+    z->avail_out = buf_size;
83
+
84
+    ret = inflate(z, Z_NO_FLUSH);
85
+    if (ret != Z_OK && ret != Z_STREAM_END) {
86
+        av_log(s, AV_LOG_ERROR, "Inflate error: %d\n", ret);
87
+        return AVERROR_UNKNOWN;
88
+    }
89
+
90
+    if (buf_size - z->avail_out == 0)
91
+        goto retry;
92
+
93
+    return buf_size - z->avail_out;
94
+}
95
+#endif
96
+
64 97
 static int swf_read_header(AVFormatContext *s)
65 98
 {
66 99
     SWFContext *swf = s->priv_data;
... ...
@@ -68,14 +107,33 @@ static int swf_read_header(AVFormatContext *s)
68 68
     int nbits, len, tag;
69 69
 
70 70
     tag = avio_rb32(pb) & 0xffffff00;
71
+    avio_rl32(pb);
71 72
 
72 73
     if (tag == MKBETAG('C', 'W', 'S', 0)) {
73
-        av_log(s, AV_LOG_ERROR, "Compressed SWF format not supported\n");
74
+        av_log(s, AV_LOG_INFO, "Compressed SWF file detected\n");
75
+#if CONFIG_ZLIB
76
+        if (inflateInit(&swf->zstream) != Z_OK) {
77
+            av_log(s, AV_LOG_ERROR, "Unable to init zlib context\n");
78
+            return AVERROR(EINVAL);
79
+        }
80
+        swf->zbuf_in  = av_malloc(ZBUF_SIZE);
81
+        swf->zbuf_out = av_malloc(ZBUF_SIZE);
82
+        swf->zpb = avio_alloc_context(swf->zbuf_out, ZBUF_SIZE, 0, s,
83
+                                      zlib_refill, NULL, NULL);
84
+        if (!swf->zbuf_in || !swf->zbuf_out || !swf->zpb) {
85
+            av_freep(&swf->zbuf_in);
86
+            av_freep(&swf->zbuf_out);
87
+            av_freep(&swf->zpb);
88
+            return AVERROR(ENOMEM);
89
+        }
90
+        swf->zpb->seekable = 0;
91
+        pb = swf->zpb;
92
+#else
93
+        av_log(s, AV_LOG_ERROR, "missing zlib support, unable to open\n");
74 94
         return AVERROR(EIO);
75
-    }
76
-    if (tag != MKBETAG('F', 'W', 'S', 0))
95
+#endif
96
+    } else if (tag != MKBETAG('F', 'W', 'S', 0))
77 97
         return AVERROR(EIO);
78
-    avio_rl32(pb);
79 98
     /* skip rectangle size */
80 99
     nbits = avio_r8(pb) >> 3;
81 100
     len = (4 * nbits - 3 + 7) / 8;
... ...
@@ -95,6 +153,11 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
95 95
     AVStream *vst = NULL, *ast = NULL, *st = 0;
96 96
     int tag, len, i, frame, v, res;
97 97
 
98
+#if CONFIG_ZLIB
99
+    if (swf->zpb)
100
+        pb = swf->zpb;
101
+#endif
102
+
98 103
     for(;;) {
99 104
         uint64_t pos = avio_tell(pb);
100 105
         tag = get_swf_tag(pb, &len);
... ...
@@ -240,6 +303,18 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
240 240
     }
241 241
 }
242 242
 
243
+#if CONFIG_ZLIB
244
+static av_cold int swf_read_close(AVFormatContext *avctx)
245
+{
246
+    SWFContext *s = avctx->priv_data;
247
+    inflateEnd(&s->zstream);
248
+    av_freep(&s->zbuf_in);
249
+    av_freep(&s->zbuf_out);
250
+    av_freep(&s->zpb);
251
+    return 0;
252
+}
253
+#endif
254
+
243 255
 AVInputFormat ff_swf_demuxer = {
244 256
     .name           = "swf",
245 257
     .long_name      = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
... ...
@@ -247,4 +322,7 @@ AVInputFormat ff_swf_demuxer = {
247 247
     .read_probe     = swf_probe,
248 248
     .read_header    = swf_read_header,
249 249
     .read_packet    = swf_read_packet,
250
+#if CONFIG_ZLIB
251
+    .read_close     = swf_read_close,
252
+#endif
250 253
 };