Commit 588eaa10 authored by Clément Bœsch's avatar Clément Bœsch

swfdec: support compressed swf.

parent 38477e19
...@@ -23,6 +23,10 @@ ...@@ -23,6 +23,10 @@
#ifndef AVFORMAT_SWF_H #ifndef AVFORMAT_SWF_H
#define AVFORMAT_SWF_H #define AVFORMAT_SWF_H
#if CONFIG_ZLIB
#include <zlib.h>
#endif
#include "libavutil/fifo.h" #include "libavutil/fifo.h"
#include "avformat.h" #include "avformat.h"
#include "avio.h" #include "avio.h"
...@@ -76,6 +80,13 @@ typedef struct { ...@@ -76,6 +80,13 @@ typedef struct {
int tag; int tag;
AVFifoBuffer *audio_fifo; AVFifoBuffer *audio_fifo;
AVCodecContext *audio_enc, *video_enc; 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; } SWFContext;
static const AVCodecTag swf_codec_tags[] = { static const AVCodecTag swf_codec_tags[] = {
......
...@@ -52,6 +52,39 @@ static int swf_probe(AVProbeData *p) ...@@ -52,6 +52,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 < 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) static int swf_read_header(AVFormatContext *s)
{ {
SWFContext *swf = s->priv_data; SWFContext *swf = s->priv_data;
...@@ -59,14 +92,29 @@ static int swf_read_header(AVFormatContext *s) ...@@ -59,14 +92,29 @@ static int swf_read_header(AVFormatContext *s)
int nbits, len, tag; int nbits, len, tag;
tag = avio_rb32(pb) & 0xffffff00; 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, "SWF compressed file detected\n");
return AVERROR(EIO); #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);
} }
if (tag != MKBETAG('F', 'W', 'S', 0)) pb = swf->zpb;
#else
av_log(s, AV_LOG_ERROR, "zlib support is required to read SWF compressed files\n");
return AVERROR(EIO);
#endif
} else if (tag != MKBETAG('F', 'W', 'S', 0))
return AVERROR(EIO); return AVERROR(EIO);
avio_rl32(pb);
/* skip rectangle size */ /* skip rectangle size */
nbits = avio_r8(pb) >> 3; nbits = avio_r8(pb) >> 3;
len = (4 * nbits - 3 + 7) / 8; len = (4 * nbits - 3 + 7) / 8;
...@@ -86,6 +134,11 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -86,6 +134,11 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt)
AVStream *vst = NULL, *ast = NULL, *st = 0; AVStream *vst = NULL, *ast = NULL, *st = 0;
int tag, len, i, frame, v, res; int tag, len, i, frame, v, res;
#if CONFIG_ZLIB
if (swf->zpb)
pb = swf->zpb;
#endif
for(;;) { for(;;) {
uint64_t pos = avio_tell(pb); uint64_t pos = avio_tell(pb);
tag = get_swf_tag(pb, &len); tag = get_swf_tag(pb, &len);
...@@ -209,6 +262,18 @@ static int swf_read_packet(AVFormatContext *s, AVPacket *pkt) ...@@ -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 = { AVInputFormat ff_swf_demuxer = {
.name = "swf", .name = "swf",
.long_name = NULL_IF_CONFIG_SMALL("Flash format"), .long_name = NULL_IF_CONFIG_SMALL("Flash format"),
...@@ -216,4 +281,7 @@ AVInputFormat ff_swf_demuxer = { ...@@ -216,4 +281,7 @@ AVInputFormat ff_swf_demuxer = {
.read_probe = swf_probe, .read_probe = swf_probe,
.read_header = swf_read_header, .read_header = swf_read_header,
.read_packet = swf_read_packet, .read_packet = swf_read_packet,
#if CONFIG_ZLIB
.read_close = swf_read_close,
#endif
}; };
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