[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