[FFmpeg-devel] [PATCH 1/2] vp8: WebP decoding support

Pascal Massimino pascal.massimino at gmail.com
Fri Mar 22 09:45:02 CET 2013


Michael,

On Thu, Mar 21, 2013 at 7:51 PM, Michael Niedermayer <michaelni at gmx.at>wrote:

> Signed-off-by: Michael Niedermayer <michaelni at gmx.at>
> ---
>  libavcodec/vp8.c |   19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)
>
> diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
> index ac929d0..1dbe959 100644
> --- a/libavcodec/vp8.c
> +++ b/libavcodec/vp8.c
> @@ -304,6 +304,25 @@ static int decode_frame_header(VP8Context *s, const
> uint8_t *buf, int buf_size)
>      int width  = s->avctx->width;
>      int height = s->avctx->height;
>
> +    if (   AV_RL32(buf   ) == AV_RL32("RIFF")
> +        && AV_RL32(buf+ 8) == AV_RL32("WEBP")) {
> +        if (AV_RL32(buf+12) == AV_RL32("VP8X") && AV_RL32(buf+16) <
> (unsigned)buf_size) {
> +            unsigned size = AV_RL32(buf+16) + 8;
> +            buf      += size;
> +            buf_size -= size;
> +        }
> +        if (AV_RL32(buf+12) == AV_RL32("ALPH") && AV_RL32(buf+16) <
> (unsigned)buf_size) {
> +            unsigned size = AV_RL32(buf+16) + 8 + 1;
> +            buf      += size;
> +            buf_size -= size;
> +            av_log(s->avctx, AV_LOG_WARNING, "Skiping alpha plane\n");
> +        }
> +        if (AV_RL32(buf+12) == AV_RL32("VP8 ")) {
> +            buf      += 20;
> +            buf_size -= 20;
> +        }
> +    }
> +
>      s->keyframe  = !(buf[0] & 1);
>      s->profile   =  (buf[0]>>1) & 7;
>      s->invisible = !(buf[0] & 0x10);
>
>
There seems to be some problem with this patch:
  * there were some missing bound checks of size against buf_size
  * VP8L chunks should be taken care of (lossless format)
  * padding needs to be applied to odd sizes

here's a revised patch fixing that hopefully:


iff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index ac929d0..1acc35c 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -297,6 +297,8 @@ static void update_refs(VP8Context *s)
     s->update_altref = ref_to_update(s, update_altref, VP56_FRAME_GOLDEN2);
 }

+static unsigned apply_padding(unsigned size) { return size + (size & 1); }
+
 static int decode_frame_header(VP8Context *s, const uint8_t *buf, int
buf_size)
 {
     VP56RangeCoder *c = &s->c;
@@ -304,6 +306,38 @@ static int decode_frame_header(VP8Context *s, const
uint8_t *buf, int buf_size)
     int width  = s->avctx->width;
     int height = s->avctx->height;

+    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(s->avctx, AV_LOG_ERROR, "Incomplete header.\n");
+            return AVERROR_INVALIDDATA;
+        }
+        if (AV_RL32(buf) == AV_RL32("VP8L")) {
+            av_log(s->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(s->avctx, AV_LOG_WARNING, "Skipping alpha plane\n");
+        }
+        if (buf_size >= 8 && AV_RL32(buf) == AV_RL32("VP8 ")) {
+            buf      += 8;
+            buf_size -= 8;
+        }
+    }
+
     s->keyframe  = !(buf[0] & 1);
     s->profile   =  (buf[0]>>1) & 7;
     s->invisible = !(buf[0] & 0x10);


More information about the ffmpeg-devel mailing list