[FFmpeg-devel] [PATCH 2/2] vp8: WebP decoding support
Pascal Massimino
pascal.massimino at gmail.com
Fri Mar 22 13:47:22 CET 2013
Hi Michael,
On Fri, Mar 22, 2013 at 4:16 AM, Michael Niedermayer <michaelni at gmx.at>wrote:
> VP8L, padding and bounds checks by Pascal Massimino
>
> Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
>
LGTM. Tested both patches locally on a set of random-featured .webp files
and results were OK.
> ---
> libavcodec/Makefile | 1 +
> libavcodec/allcodecs.c | 1 +
> libavcodec/avcodec.h | 1 +
> libavcodec/codec_desc.c | 7 ++++++
> libavcodec/vp8.c | 61
> +++++++++++++++++++++++++++++++++++++++++++++++
> 5 files changed, 71 insertions(+)
>
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index 0d73067..bbb7083 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -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
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 1eaf2d3..4ff63ef 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -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);
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index c3bd534..1b5f9d4 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -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
> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
> index ded09c9..2b3eed7 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -1038,6 +1038,13 @@ static const AVCodecDescriptor codec_descriptors[]
> = {
> .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,
> .name = "pictor",
> diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
> index ac929d0..1ab76b5 100644
> --- a/libavcodec/vp8.c
> +++ b/libavcodec/vp8.c
> @@ -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),
> +};
> --
> 1.7.9.5
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel at ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
More information about the ffmpeg-devel
mailing list