[FFmpeg-cvslog] vp8: WebP decoding support

Michael Niedermayer git at videolan.org
Fri Mar 22 15:25:05 CET 2013


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Fri Mar 22 11:38:46 2013 +0100| [076c1c956c55887ca63a797baf0143f56dd30879] | committer: Michael Niedermayer

vp8: WebP decoding support

VP8L, padding and bounds checks by Pascal Massimino

Reviewed-by: Pascal Massimino <pascal.massimino at gmail.com>
Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=076c1c956c55887ca63a797baf0143f56dd30879
---

 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),
+};



More information about the ffmpeg-cvslog mailing list