mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
vp8: WebP decoding support
VP8L, padding and bounds checks by Pascal Massimino Reviewed-by: Pascal Massimino <pascal.massimino@gmail.com> Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
c0ff2aaa49
commit
076c1c956c
@ -461,6 +461,7 @@ OBJS-$(CONFIG_VP8_DECODER) += vp8.o vp8dsp.o vp56rac.o
|
||||
OBJS-$(CONFIG_VPLAYER_DECODER) += textdec.o ass.o
|
||||
OBJS-$(CONFIG_VQA_DECODER) += vqavideo.o
|
||||
OBJS-$(CONFIG_WAVPACK_DECODER) += wavpack.o
|
||||
OBJS-$(CONFIG_WEBP_DECODER) += vp8.o vp8dsp.o vp56rac.o
|
||||
OBJS-$(CONFIG_WEBVTT_DECODER) += webvttdec.o
|
||||
OBJS-$(CONFIG_WMALOSSLESS_DECODER) += wmalosslessdec.o wma_common.o
|
||||
OBJS-$(CONFIG_WMAPRO_DECODER) += wmaprodec.o wma.o wma_common.o
|
||||
|
@ -283,6 +283,7 @@ void avcodec_register_all(void)
|
||||
REGISTER_DECODER(VP6F, vp6f);
|
||||
REGISTER_DECODER(VP8, vp8);
|
||||
REGISTER_DECODER(VQA, vqa);
|
||||
REGISTER_DECODER(WEBP, webp);
|
||||
REGISTER_ENCDEC (WMV1, wmv1);
|
||||
REGISTER_ENCDEC (WMV2, wmv2);
|
||||
REGISTER_DECODER(WMV3, wmv3);
|
||||
|
@ -292,6 +292,7 @@ enum AVCodecID {
|
||||
AV_CODEC_ID_MVC1 = MKBETAG('M','V','C','1'),
|
||||
AV_CODEC_ID_MVC2 = MKBETAG('M','V','C','2'),
|
||||
AV_CODEC_ID_SNOW = MKBETAG('S','N','O','W'),
|
||||
AV_CODEC_ID_WEBP = MKBETAG('W','E','B','P'),
|
||||
|
||||
/* various PCM "codecs" */
|
||||
AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs
|
||||
|
@ -1037,6 +1037,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
|
||||
.long_name = NULL_IF_CONFIG_SMALL("Google VP9"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_WEBP,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.name = "webp",
|
||||
.long_name = NULL_IF_CONFIG_SMALL("WebP"),
|
||||
.props = AV_CODEC_PROP_LOSSY,
|
||||
},
|
||||
{
|
||||
.id = AV_CODEC_ID_PICTOR,
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
|
@ -2094,6 +2094,52 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst, const AVCodecCo
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned apply_padding(unsigned size) { return size + (size & 1); }
|
||||
|
||||
static int webp_decode_frame(AVCodecContext *avctx, void *data, int *data_size,
|
||||
AVPacket *avpkt)
|
||||
{
|
||||
const uint8_t *buf = avpkt->data;
|
||||
int buf_size = avpkt->size;
|
||||
AVPacket pkt = *avpkt;
|
||||
|
||||
if (buf_size >= 16
|
||||
&& AV_RL32(buf ) == AV_RL32("RIFF")
|
||||
&& AV_RL32(buf+ 8) == AV_RL32("WEBP")) {
|
||||
unsigned riff_size = apply_padding(AV_RL32(buf+4)) + 8;
|
||||
buf += 12; // Skip over main header
|
||||
buf_size -= 12;
|
||||
if (buf_size < 8 || riff_size < 8) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Incomplete header.\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
if (AV_RL32(buf) == AV_RL32("VP8L")) {
|
||||
av_log(avctx, AV_LOG_ERROR, "Unsupported WebP lossless format.\n");
|
||||
return AVERROR_PATCHWELCOME;
|
||||
}
|
||||
if (AV_RL32(buf) == AV_RL32("VP8X") && AV_RL32(buf+4) < (unsigned)buf_size) {
|
||||
unsigned size = apply_padding(AV_RL32(buf+4) + 8);
|
||||
buf += size;
|
||||
buf_size -= size;
|
||||
}
|
||||
if (buf_size >= 8
|
||||
&& AV_RL32(buf) == AV_RL32("ALPH") && AV_RL32(buf+4) < (unsigned)buf_size) {
|
||||
unsigned size = apply_padding(AV_RL32(buf+4) + 8);
|
||||
buf += size;
|
||||
buf_size -= size;
|
||||
av_log(avctx, AV_LOG_WARNING, "Skipping alpha plane\n");
|
||||
}
|
||||
if (buf_size >= 8 && AV_RL32(buf) == AV_RL32("VP8 ")) {
|
||||
buf += 8;
|
||||
buf_size -= 8;
|
||||
}
|
||||
}
|
||||
pkt.data = buf;
|
||||
pkt.size = buf_size;
|
||||
|
||||
return vp8_decode_frame(avctx, data, data_size, &pkt);
|
||||
}
|
||||
|
||||
AVCodec ff_vp8_decoder = {
|
||||
.name = "vp8",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
@ -2108,3 +2154,18 @@ AVCodec ff_vp8_decoder = {
|
||||
.init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy),
|
||||
.update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context),
|
||||
};
|
||||
|
||||
AVCodec ff_webp_decoder = {
|
||||
.name = "webp",
|
||||
.type = AVMEDIA_TYPE_VIDEO,
|
||||
.id = AV_CODEC_ID_WEBP,
|
||||
.priv_data_size = sizeof(VP8Context),
|
||||
.init = vp8_decode_init,
|
||||
.close = vp8_decode_free,
|
||||
.decode = webp_decode_frame,
|
||||
.capabilities = CODEC_CAP_DR1 | CODEC_CAP_FRAME_THREADS | CODEC_CAP_SLICE_THREADS,
|
||||
.flush = vp8_decode_flush,
|
||||
.long_name = NULL_IF_CONFIG_SMALL("WebP"),
|
||||
.init_thread_copy = ONLY_IF_THREADS_ENABLED(vp8_decode_init_thread_copy),
|
||||
.update_thread_context = ONLY_IF_THREADS_ENABLED(vp8_decode_update_thread_context),
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user