summaryrefslogtreecommitdiff
path: root/libavcodec/vp8.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/vp8.c')
-rw-r--r--libavcodec/vp8.c84
1 files changed, 72 insertions, 12 deletions
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index 3c60aa3409..d7fac64411 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -6,20 +6,20 @@
* Copyright (C) 2010 Jason Garrett-Glaser
* Copyright (C) 2012 Daniel Kang
*
- * This file is part of Libav.
+ * This file is part of FFmpeg.
*
- * Libav is free software; you can redistribute it and/or
+ * FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * Libav is distributed in the hope that it will be useful,
+ * FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with Libav; if not, write to the Free Software
+ * License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
@@ -116,7 +116,7 @@ static int update_dimensions(VP8Context *s, int width, int height)
AVCodecContext *avctx = s->avctx;
int i;
- if (width != s->avctx->width ||
+ if (width != s->avctx->width || ((width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) && s->macroblocks_base ||
height != s->avctx->height) {
if (av_image_check_size(width, height, 0, s->avctx))
return AVERROR_INVALIDDATA;
@@ -384,7 +384,7 @@ static int decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_size)
}
if (!s->macroblocks_base || /* first frame */
- width != s->avctx->width || height != s->avctx->height) {
+ width != s->avctx->width || height != s->avctx->height || (width+15)/16 != s->mb_width || (height+15)/16 != s->mb_height) {
if ((ret = update_dimensions(s, width, height)) < 0)
return ret;
}
@@ -700,9 +700,10 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
{
VP56RangeCoder *c = &s->c;
- if (s->segmentation.update_map)
- *segment = vp8_rac_get_tree(c, vp8_segmentid_tree, s->prob->segmentid);
- else if (s->segmentation.enabled)
+ if (s->segmentation.update_map) {
+ int bit = vp56_rac_get_prob(c, s->prob->segmentid[0]);
+ *segment = vp56_rac_get_prob(c, s->prob->segmentid[1+bit]) + 2*bit;
+ } else if (s->segmentation.enabled)
*segment = ref ? *ref : *segment;
mb->segment = *segment;
@@ -1917,10 +1918,8 @@ int ff_vp8_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
curframe->tf.f->key_frame = s->keyframe;
curframe->tf.f->pict_type = s->keyframe ? AV_PICTURE_TYPE_I : AV_PICTURE_TYPE_P;
- if ((ret = vp8_alloc_frame(s, curframe, referenced))) {
- av_log(avctx, AV_LOG_ERROR, "get_buffer() failed!\n");
+ if ((ret = vp8_alloc_frame(s, curframe, referenced)) < 0)
goto err;
- }
// check if golden and altref are swapped
if (s->update_altref != VP56_FRAME_NONE) {
@@ -2105,6 +2104,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 ff_vp8_decode_frame(avctx, data, data_size, &pkt);
+}
+
AVCodec ff_vp8_decoder = {
.name = "vp8",
.type = AVMEDIA_TYPE_VIDEO,
@@ -2119,3 +2164,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),
+// };