|
|
|
@ -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 |
|
|
|
|
}; |
|
|
|
|