mirror of https://git.ffmpeg.org/ffmpeg.git
swfdec: support compressed swf
Signed-off-by: Vittorio Giovara <vittorio.giovara@gmail.com>
This commit is contained in:
parent
34d45b3616
commit
7570c9e04f
|
@ -50,6 +50,7 @@ version <next>:
|
||||||
- support encoding 16-bit RLE SGI images
|
- support encoding 16-bit RLE SGI images
|
||||||
- support Apple AVFoundation video capture
|
- support Apple AVFoundation video capture
|
||||||
- G.723.1 muxer and encoder
|
- G.723.1 muxer and encoder
|
||||||
|
- compressed SWF
|
||||||
|
|
||||||
|
|
||||||
version 11:
|
version 11:
|
||||||
|
|
|
@ -2256,6 +2256,7 @@ sdp_demuxer_select="rtpdec"
|
||||||
smoothstreaming_muxer_select="ismv_muxer"
|
smoothstreaming_muxer_select="ismv_muxer"
|
||||||
spdif_muxer_select="aac_parser"
|
spdif_muxer_select="aac_parser"
|
||||||
spx_muxer_select="ogg_muxer"
|
spx_muxer_select="ogg_muxer"
|
||||||
|
swf_demuxer_suggest="zlib"
|
||||||
tak_demuxer_select="tak_parser"
|
tak_demuxer_select="tak_parser"
|
||||||
tg2_muxer_select="mov_muxer"
|
tg2_muxer_select="mov_muxer"
|
||||||
tgp_muxer_select="mov_muxer"
|
tgp_muxer_select="mov_muxer"
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
#ifndef AVFORMAT_SWF_H
|
#ifndef AVFORMAT_SWF_H
|
||||||
#define AVFORMAT_SWF_H
|
#define AVFORMAT_SWF_H
|
||||||
|
|
||||||
|
#include "config.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"
|
||||||
|
@ -77,6 +83,13 @@ typedef struct SWFContext {
|
||||||
AVFifoBuffer *audio_fifo;
|
AVFifoBuffer *audio_fifo;
|
||||||
AVCodecContext *audio_enc, *video_enc;
|
AVCodecContext *audio_enc, *video_enc;
|
||||||
AVStream *video_st;
|
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;
|
} SWFContext;
|
||||||
|
|
||||||
extern const AVCodecTag ff_swf_codec_tags[];
|
extern const AVCodecTag ff_swf_codec_tags[];
|
||||||
|
|
|
@ -20,6 +20,12 @@
|
||||||
* 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/channel_layout.h"
|
||||||
#include "libavutil/intreadwrite.h"
|
#include "libavutil/intreadwrite.h"
|
||||||
#include "swf.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)
|
static int swf_read_header(AVFormatContext *s)
|
||||||
{
|
{
|
||||||
SWFContext *swf = s->priv_data;
|
SWFContext *swf = s->priv_data;
|
||||||
|
@ -68,14 +107,33 @@ 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, "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);
|
||||||
}
|
#endif
|
||||||
if (tag != MKBETAG('F', 'W', 'S', 0))
|
} 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;
|
||||||
|
@ -95,6 +153,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);
|
||||||
|
@ -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 = {
|
AVInputFormat ff_swf_demuxer = {
|
||||||
.name = "swf",
|
.name = "swf",
|
||||||
.long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
|
.long_name = NULL_IF_CONFIG_SMALL("SWF (ShockWave Flash)"),
|
||||||
|
@ -247,4 +322,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
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue