summaryrefslogtreecommitdiff
path: root/libavcodec/vp8.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/vp8.c')
-rw-r--r--libavcodec/vp8.c406
1 files changed, 212 insertions, 194 deletions
diff --git a/libavcodec/vp8.c b/libavcodec/vp8.c
index bf1b03e9f7..1e8808c46f 100644
--- a/libavcodec/vp8.c
+++ b/libavcodec/vp8.c
@@ -7,20 +7,20 @@
* Copyright (C) 2012 Daniel Kang
* Copyright (C) 2014 Peter Ross
*
- * 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
*/
@@ -38,6 +38,14 @@
# include "arm/vp8.h"
#endif
+#if CONFIG_VP7_DECODER && CONFIG_VP8_DECODER
+#define VPX(vp7, f) (vp7 ? vp7_ ## f : vp8_ ## f)
+#elif CONFIG_VP7_DECODER
+#define VPX(vp7, f) vp7_ ## f
+#else // CONFIG_VP8_DECODER
+#define VPX(vp7, f) vp8_ ## f
+#endif
+
static void free_buffers(VP8Context *s)
{
int i;
@@ -64,30 +72,16 @@ static int vp8_alloc_frame(VP8Context *s, VP8Frame *f, int ref)
if ((ret = ff_thread_get_buffer(s->avctx, &f->tf,
ref ? AV_GET_BUFFER_FLAG_REF : 0)) < 0)
return ret;
- if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height)))
- goto fail;
- if (s->avctx->hwaccel) {
- const AVHWAccel *hwaccel = s->avctx->hwaccel;
- if (hwaccel->frame_priv_data_size) {
- f->hwaccel_priv_buf = av_buffer_allocz(hwaccel->frame_priv_data_size);
- if (!f->hwaccel_priv_buf)
- goto fail;
- f->hwaccel_picture_private = f->hwaccel_priv_buf->data;
- }
+ if (!(f->seg_map = av_buffer_allocz(s->mb_width * s->mb_height))) {
+ ff_thread_release_buffer(s->avctx, &f->tf);
+ return AVERROR(ENOMEM);
}
return 0;
-
-fail:
- av_buffer_unref(&f->seg_map);
- ff_thread_release_buffer(s->avctx, &f->tf);
- return AVERROR(ENOMEM);
}
static void vp8_release_frame(VP8Context *s, VP8Frame *f)
{
av_buffer_unref(&f->seg_map);
- av_buffer_unref(&f->hwaccel_priv_buf);
- f->hwaccel_picture_private = NULL;
ff_thread_release_buffer(s->avctx, &f->tf);
}
@@ -105,12 +99,6 @@ static int vp8_ref_frame(VP8Context *s, VP8Frame *dst, VP8Frame *src)
vp8_release_frame(s, dst);
return AVERROR(ENOMEM);
}
- if (src->hwaccel_picture_private) {
- dst->hwaccel_priv_buf = av_buffer_ref(src->hwaccel_priv_buf);
- if (!dst->hwaccel_priv_buf)
- return AVERROR(ENOMEM);
- dst->hwaccel_picture_private = dst->hwaccel_priv_buf->data;
- }
return 0;
}
@@ -152,7 +140,7 @@ static VP8Frame *vp8_find_free_buffer(VP8Context *s)
av_log(s->avctx, AV_LOG_FATAL, "Ran out of free frames!\n");
abort();
}
- if (frame->tf.f->buf[0])
+ if (frame->tf.f->data[0])
vp8_release_frame(s, frame);
return frame;
@@ -164,7 +152,7 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7)
AVCodecContext *avctx = s->avctx;
int i, ret;
- 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) {
vp8_decode_flush_impl(s->avctx, 1);
@@ -177,7 +165,7 @@ int update_dimensions(VP8Context *s, int width, int height, int is_vp7)
s->mb_height = (s->avctx->coded_height + 15) / 16;
s->mb_layout = is_vp7 || avctx->active_thread_type == FF_THREAD_SLICE &&
- FFMIN(s->num_coeff_partitions, avctx->thread_count) > 1;
+ avctx->thread_count > 1;
if (!s->mb_layout) { // Frame threading and one thread
s->macroblocks_base = av_mallocz((s->mb_width + s->mb_height * 2 + 1) *
sizeof(*s->macroblocks));
@@ -223,15 +211,15 @@ static int vp8_update_dimensions(VP8Context *s, int width, int height)
return update_dimensions(s, width, height, IS_VP8);
}
+
static void parse_segment_info(VP8Context *s)
{
VP56RangeCoder *c = &s->c;
int i;
s->segmentation.update_map = vp8_rac_get(c);
- s->segmentation.update_feature_data = vp8_rac_get(c);
- if (s->segmentation.update_feature_data) {
+ if (vp8_rac_get(c)) { // update segment feature data
s->segmentation.absolute_vals = vp8_rac_get(c);
for (i = 0; i < 4; i++)
@@ -273,6 +261,7 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
{
const uint8_t *sizes = buf;
int i;
+ int ret;
s->num_coeff_partitions = 1 << vp8_rac_get_uint(&s->c, 2);
@@ -285,17 +274,14 @@ static int setup_partitions(VP8Context *s, const uint8_t *buf, int buf_size)
int size = AV_RL24(sizes + 3 * i);
if (buf_size - size < 0)
return -1;
- s->coeff_partition_size[i] = size;
- ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);
+ ret = ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, size);
+ if (ret < 0)
+ return ret;
buf += size;
buf_size -= size;
}
-
- s->coeff_partition_size[i] = buf_size;
- ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
-
- return 0;
+ return ff_vp56_init_range_decoder(&s->coeff_partition[i], buf, buf_size);
}
static void vp7_get_quants(VP8Context *s)
@@ -317,33 +303,33 @@ static void vp7_get_quants(VP8Context *s)
s->qmat[0].chroma_qmul[1] = vp7_yac_qlookup[uvac_qi];
}
-static void get_quants(VP8Context *s)
+static void vp8_get_quants(VP8Context *s)
{
VP56RangeCoder *c = &s->c;
int i, base_qi;
- s->quant.yac_qi = vp8_rac_get_uint(c, 7);
- s->quant.ydc_delta = vp8_rac_get_sint(c, 4);
- s->quant.y2dc_delta = vp8_rac_get_sint(c, 4);
- s->quant.y2ac_delta = vp8_rac_get_sint(c, 4);
- s->quant.uvdc_delta = vp8_rac_get_sint(c, 4);
- s->quant.uvac_delta = vp8_rac_get_sint(c, 4);
+ int yac_qi = vp8_rac_get_uint(c, 7);
+ int ydc_delta = vp8_rac_get_sint(c, 4);
+ int y2dc_delta = vp8_rac_get_sint(c, 4);
+ int y2ac_delta = vp8_rac_get_sint(c, 4);
+ int uvdc_delta = vp8_rac_get_sint(c, 4);
+ int uvac_delta = vp8_rac_get_sint(c, 4);
for (i = 0; i < 4; i++) {
if (s->segmentation.enabled) {
base_qi = s->segmentation.base_quant[i];
if (!s->segmentation.absolute_vals)
- base_qi += s->quant.yac_qi;
+ base_qi += yac_qi;
} else
- base_qi = s->quant.yac_qi;
+ base_qi = yac_qi;
- s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.ydc_delta, 7)];
+ s->qmat[i].luma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + ydc_delta, 7)];
s->qmat[i].luma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi, 7)];
- s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.y2dc_delta, 7)] * 2;
+ s->qmat[i].luma_dc_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + y2dc_delta, 7)] * 2;
/* 101581>>16 is equivalent to 155/100 */
- s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.y2ac_delta, 7)] * 101581 >> 16;
- s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + s->quant.uvdc_delta, 7)];
- s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + s->quant.uvac_delta, 7)];
+ s->qmat[i].luma_dc_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + y2ac_delta, 7)] * 101581 >> 16;
+ s->qmat[i].chroma_qmul[0] = vp8_dc_qlookup[av_clip_uintp2(base_qi + uvdc_delta, 7)];
+ s->qmat[i].chroma_qmul[1] = vp8_ac_qlookup[av_clip_uintp2(base_qi + uvac_delta, 7)];
s->qmat[i].luma_dc_qmul[1] = FFMAX(s->qmat[i].luma_dc_qmul[1], 8);
s->qmat[i].chroma_qmul[0] = FFMIN(s->qmat[i].chroma_qmul[0], 132);
@@ -438,7 +424,7 @@ static void update_refs(VP8Context *s)
s->update_altref = ref_to_update(s, update_altref, VP56_FRAME_GOLDEN2);
}
-static void copy_luma(AVFrame *dst, AVFrame *src, int width, int height)
+static void copy_chroma(AVFrame *dst, AVFrame *src, int width, int height)
{
int i, j;
@@ -449,16 +435,16 @@ static void copy_luma(AVFrame *dst, AVFrame *src, int width, int height)
}
}
-static void fade(uint8_t *dst, uint8_t *src,
- int width, int height, ptrdiff_t linesize,
+static void fade(uint8_t *dst, ptrdiff_t dst_linesize,
+ const uint8_t *src, ptrdiff_t src_linesize,
+ int width, int height,
int alpha, int beta)
{
int i, j;
-
for (j = 0; j < height; j++) {
for (i = 0; i < width; i++) {
- uint8_t y = src[j * linesize + i];
- dst[j * linesize + i] = av_clip_uint8(y + ((y * beta) >> 8) + alpha);
+ uint8_t y = src[j * src_linesize + i];
+ dst[j * dst_linesize + i] = av_clip_uint8(y + ((y * beta) >> 8) + alpha);
}
}
}
@@ -474,8 +460,11 @@ static int vp7_fade_frame(VP8Context *s, VP56RangeCoder *c)
int height = s->mb_height * 16;
AVFrame *src, *dst;
- if (!s->framep[VP56_FRAME_PREVIOUS])
+ if (!s->framep[VP56_FRAME_PREVIOUS] ||
+ !s->framep[VP56_FRAME_GOLDEN]) {
+ av_log(s->avctx, AV_LOG_WARNING, "Discarding interframe without a prior keyframe!\n");
return AVERROR_INVALIDDATA;
+ }
dst =
src = s->framep[VP56_FRAME_PREVIOUS]->tf.f;
@@ -484,15 +473,16 @@ static int vp7_fade_frame(VP8Context *s, VP56RangeCoder *c)
if (s->framep[VP56_FRAME_GOLDEN] == s->framep[VP56_FRAME_PREVIOUS]) {
s->framep[VP56_FRAME_PREVIOUS] = vp8_find_free_buffer(s);
if ((ret = vp8_alloc_frame(s, s->framep[VP56_FRAME_PREVIOUS], 1)) < 0)
- return ret;
+ return ret;
dst = s->framep[VP56_FRAME_PREVIOUS]->tf.f;
- copy_luma(dst, src, width, height);
+ copy_chroma(dst, src, width, height);
}
- fade(dst->data[0], src->data[0],
- width, height, dst->linesize[0], alpha, beta);
+ fade(dst->data[0], dst->linesize[0],
+ src->data[0], src->linesize[0],
+ width, height, alpha, beta);
}
return 0;
@@ -519,16 +509,19 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
s->invisible = 0;
part1_size = AV_RL24(buf) >> 4;
- buf += 4 - s->profile;
- buf_size -= 4 - s->profile;
-
- if (buf_size < part1_size) {
+ if (buf_size < 4 - s->profile + part1_size) {
+ av_log(s->avctx, AV_LOG_ERROR, "Buffer size %d is too small, needed : %d\n", buf_size, 4 - s->profile + part1_size);
return AVERROR_INVALIDDATA;
}
+ buf += 4 - s->profile;
+ buf_size -= 4 - s->profile;
+
memcpy(s->put_pixels_tab, s->vp8dsp.put_vp8_epel_pixels_tab, sizeof(s->put_pixels_tab));
- ff_vp56_init_range_decoder(c, buf, part1_size);
+ ret = ff_vp56_init_range_decoder(c, buf, part1_size);
+ if (ret < 0)
+ return ret;
buf += part1_size;
buf_size -= part1_size;
@@ -571,7 +564,7 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
if (vp7_feature_value_size[s->profile][i])
for (j = 0; j < 4; j++)
s->feature_value[i][j] =
- vp8_rac_get(c) ? vp8_rac_get_uint(c, vp7_feature_value_size[s->profile][i]) : 0;
+ vp8_rac_get(c) ? vp8_rac_get_uint(c, vp7_feature_value_size[s->profile][i]) : 0;
}
}
@@ -580,7 +573,9 @@ static int vp7_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
s->lf_delta.enabled = 0;
s->num_coeff_partitions = 1;
- ff_vp56_init_range_decoder(&s->coeff_partition[0], buf, buf_size);
+ ret = ff_vp56_init_range_decoder(&s->coeff_partition[0], buf, buf_size);
+ if (ret < 0)
+ return ret;
if (!s->macroblocks_base || /* first frame */
width != s->avctx->width || height != s->avctx->height ||
@@ -654,6 +649,11 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
int width = s->avctx->width;
int height = s->avctx->height;
+ if (buf_size < 3) {
+ av_log(s->avctx, AV_LOG_ERROR, "Insufficent data (%d) for header\n", buf_size);
+ return AVERROR_INVALIDDATA;
+ }
+
s->keyframe = !(buf[0] & 1);
s->profile = (buf[0]>>1) & 7;
s->invisible = !(buf[0] & 0x10);
@@ -661,8 +661,6 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
buf += 3;
buf_size -= 3;
- s->header_partition_size = header_size;
-
if (s->profile > 3)
av_log(s->avctx, AV_LOG_WARNING, "Unknown profile %d\n", s->profile);
@@ -706,7 +704,9 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
memset(&s->lf_delta, 0, sizeof(s->lf_delta));
}
- ff_vp56_init_range_decoder(c, buf, header_size);
+ ret = ff_vp56_init_range_decoder(c, buf, header_size);
+ if (ret < 0)
+ return ret;
buf += header_size;
buf_size -= header_size;
@@ -726,11 +726,9 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
s->filter.level = vp8_rac_get_uint(c, 6);
s->filter.sharpness = vp8_rac_get_uint(c, 3);
- if ((s->lf_delta.enabled = vp8_rac_get(c))) {
- s->lf_delta.update = vp8_rac_get(c);
- if (s->lf_delta.update)
+ if ((s->lf_delta.enabled = vp8_rac_get(c)))
+ if (vp8_rac_get(c))
update_lf_deltas(s);
- }
if (setup_partitions(s, buf, buf_size)) {
av_log(s->avctx, AV_LOG_ERROR, "Invalid partitions\n");
@@ -738,11 +736,12 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
}
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 = vp8_update_dimensions(s, width, height)) < 0)
return ret;
- get_quants(s);
+ vp8_get_quants(s);
if (!s->keyframe) {
update_refs(s);
@@ -769,27 +768,22 @@ static int vp8_decode_frame_header(VP8Context *s, const uint8_t *buf, int buf_si
vp78_update_pred16x16_pred8x8_mvc_probabilities(s, VP8_MVC_SIZE);
}
- // Record the entropy coder state here so that hwaccels can use it.
- s->c.code_word = vp56_rac_renorm(&s->c);
- s->coder_state_at_header_end.input = s->c.buffer - (-s->c.bits / 8);
- s->coder_state_at_header_end.range = s->c.high;
- s->coder_state_at_header_end.value = s->c.code_word >> 16;
- s->coder_state_at_header_end.bit_count = -s->c.bits % 8;
-
return 0;
}
static av_always_inline
void clamp_mv(VP8Context *s, VP56mv *dst, const VP56mv *src)
{
- dst->x = av_clip(src->x, s->mv_min.x, s->mv_max.x);
- dst->y = av_clip(src->y, s->mv_min.y, s->mv_max.y);
+ dst->x = av_clip(src->x, av_clip(s->mv_min.x, INT16_MIN, INT16_MAX),
+ av_clip(s->mv_max.x, INT16_MIN, INT16_MAX));
+ dst->y = av_clip(src->y, av_clip(s->mv_min.y, INT16_MIN, INT16_MAX),
+ av_clip(s->mv_max.y, INT16_MIN, INT16_MAX));
}
/**
* Motion vector coding, 17.1.
*/
-static int read_mv_component(VP56RangeCoder *c, const uint8_t *p, int vp7)
+static av_always_inline int read_mv_component(VP56RangeCoder *c, const uint8_t *p, int vp7)
{
int bit, x = 0;
@@ -817,6 +811,16 @@ static int read_mv_component(VP56RangeCoder *c, const uint8_t *p, int vp7)
return (x && vp56_rac_get_prob(c, p[1])) ? -x : x;
}
+static int vp7_read_mv_component(VP56RangeCoder *c, const uint8_t *p)
+{
+ return read_mv_component(c, p, 1);
+}
+
+static int vp8_read_mv_component(VP56RangeCoder *c, const uint8_t *p)
+{
+ return read_mv_component(c, p, 0);
+}
+
static av_always_inline
const uint8_t *get_submv_prob(uint32_t left, uint32_t top, int is_vp7)
{
@@ -1007,8 +1011,8 @@ void vp7_decode_mvs(VP8Context *s, VP8Macroblock *mb,
mb->mode = VP8_MVMODE_SPLIT;
mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP7) - 1];
} else {
- mb->mv.y += read_mv_component(c, s->prob->mvc[0], IS_VP7);
- mb->mv.x += read_mv_component(c, s->prob->mvc[1], IS_VP7);
+ mb->mv.y += vp7_read_mv_component(c, s->prob->mvc[0]);
+ mb->mv.x += vp7_read_mv_component(c, s->prob->mvc[1]);
mb->bmv[0] = mb->mv;
}
} else {
@@ -1107,8 +1111,8 @@ void vp8_decode_mvs(VP8Context *s, VP8Macroblock *mb,
mb->mode = VP8_MVMODE_SPLIT;
mb->mv = mb->bmv[decode_splitmvs(s, c, mb, layout, IS_VP8) - 1];
} else {
- mb->mv.y += read_mv_component(c, s->prob->mvc[0], IS_VP8);
- mb->mv.x += read_mv_component(c, s->prob->mvc[1], IS_VP8);
+ mb->mv.y += vp8_read_mv_component(c, s->prob->mvc[0]);
+ mb->mv.x += vp8_read_mv_component(c, s->prob->mvc[1]);
mb->bmv[0] = mb->mv;
}
} else {
@@ -1132,7 +1136,7 @@ void decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb,
{
uint8_t *intra4x4 = mb->intra4x4_pred_mode_mb;
- if (layout == 1) {
+ if (layout) {
VP8Macroblock *mb_top = mb - s->mb_width - 1;
memcpy(mb->intra4x4_pred_mode_top, mb_top->intra4x4_pred_mode_top, 4);
}
@@ -1140,7 +1144,7 @@ void decode_intra4x4_modes(VP8Context *s, VP56RangeCoder *c, VP8Macroblock *mb,
int x, y;
uint8_t *top;
uint8_t *const left = s->intra4x4_pred_mode_left;
- if (layout == 1)
+ if (layout)
top = mb->intra4x4_pred_mode_top;
else
top = s->intra4x4_pred_mode_top + 4 * mb_x;
@@ -1175,7 +1179,7 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
*segment = 0;
for (i = 0; i < 4; i++) {
if (s->feature_enabled[i]) {
- if (vp56_rac_get_prob(c, s->feature_present_prob[i])) {
+ if (vp56_rac_get_prob_branchy(c, s->feature_present_prob[i])) {
int index = vp8_rac_get_tree(c, vp7_feature_index_tree,
s->feature_index_prob[i]);
av_log(s->avctx, AV_LOG_WARNING,
@@ -1184,9 +1188,10 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
}
}
}
- } else if (s->segmentation.update_map)
- *segment = vp8_rac_get_tree(c, vp8_segmentid_tree, s->prob->segmentid);
- else if (s->segmentation.enabled)
+ } else 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;
@@ -1201,7 +1206,7 @@ void decode_mb_mode(VP8Context *s, VP8Macroblock *mb, int mb_x, int mb_y,
} else {
const uint32_t modes = (is_vp7 ? vp7_pred4x4_mode
: vp8_pred4x4_mode)[mb->mode] * 0x01010101u;
- if (s->mb_layout == 1)
+ if (s->mb_layout)
AV_WN32A(mb->intra4x4_pred_mode_top, modes);
else
AV_WN32A(s->intra4x4_pred_mode_top + 4 * mb_x, modes);
@@ -1365,6 +1370,7 @@ static int vp8_decode_block_coeffs_internal(VP56RangeCoder *r,
* @param zero_nhood the initial prediction context for number of surrounding
* all-zero blocks (only left/top, so 0-2)
* @param qmul array holding the dc/ac dequant factor at position 0/1
+ * @param scan scan pattern (VP7 only)
*
* @return 0 if no coeffs were decoded
* otherwise, the index of the last coeff decoded plus one
@@ -1629,7 +1635,7 @@ void intra_predict(VP8Context *s, VP8ThreadData *td, uint8_t *dst[3],
int copy = 0;
ptrdiff_t linesize = s->linesize;
uint8_t *dst = ptr + 4 * x;
- DECLARE_ALIGNED(4, uint8_t, copy_dst)[5 * 8];
+ LOCAL_ALIGNED(4, uint8_t, copy_dst, [5 * 8]);
if ((y == 0 || x == 3) && mb_y == 0) {
topright = tr_top;
@@ -1735,8 +1741,8 @@ void vp8_mc_luma(VP8Context *s, VP8ThreadData *td, uint8_t *dst,
if (AV_RN32A(mv)) {
ptrdiff_t src_linesize = linesize;
- int mx = (mv->x << 1) & 7, mx_idx = subpel_idx[0][mx];
- int my = (mv->y << 1) & 7, my_idx = subpel_idx[0][my];
+ int mx = (mv->x * 2) & 7, mx_idx = subpel_idx[0][mx];
+ int my = (mv->y * 2) & 7, my_idx = subpel_idx[0][my];
x_off += mv->x >> 2;
y_off += mv->y >> 2;
@@ -1806,7 +1812,8 @@ void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1,
s->vdsp.emulated_edge_mc(td->edge_emu_buffer,
src1 - my_idx * linesize - mx_idx,
EDGE_EMU_LINESIZE, linesize,
- block_w + subpel_idx[1][mx], block_h + subpel_idx[1][my],
+ block_w + subpel_idx[1][mx],
+ block_h + subpel_idx[1][my],
x_off - mx_idx, y_off - my_idx, width, height);
src1 = td->edge_emu_buffer + mx_idx + EDGE_EMU_LINESIZE * my_idx;
mc_func[my_idx][mx_idx](dst1, linesize, src1, EDGE_EMU_LINESIZE, block_h, mx, my);
@@ -1814,7 +1821,8 @@ void vp8_mc_chroma(VP8Context *s, VP8ThreadData *td, uint8_t *dst1,
s->vdsp.emulated_edge_mc(td->edge_emu_buffer,
src2 - my_idx * linesize - mx_idx,
EDGE_EMU_LINESIZE, linesize,
- block_w + subpel_idx[1][mx], block_h + subpel_idx[1][my],
+ block_w + subpel_idx[1][mx],
+ block_h + subpel_idx[1][my],
x_off - mx_idx, y_off - my_idx, width, height);
src2 = td->edge_emu_buffer + mx_idx + EDGE_EMU_LINESIZE * my_idx;
mc_func[my_idx][mx_idx](dst2, linesize, src2, EDGE_EMU_LINESIZE, block_h, mx, my);
@@ -2250,7 +2258,7 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame,
td->wait_mb_pos = INT_MAX; \
pthread_mutex_unlock(&otd->lock); \
} \
- } while (0);
+ } while (0)
#define update_pos(td, mb_y, mb_x) \
do { \
@@ -2269,13 +2277,13 @@ static void vp8_decode_mv_mb_modes(AVCodecContext *avctx, VP8Frame *cur_frame,
pthread_cond_broadcast(&td->cond); \
pthread_mutex_unlock(&td->lock); \
} \
- } while (0);
+ } while (0)
#else
-#define check_thread_pos(td, otd, mb_x_check, mb_y_check)
-#define update_pos(td, mb_y, mb_x)
+#define check_thread_pos(td, otd, mb_x_check, mb_y_check) while(0)
+#define update_pos(td, mb_y, mb_x) while(0)
#endif
-static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
+static av_always_inline int decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
int jobnr, int threadnr, int is_vp7)
{
VP8Context *s = avctx->priv_data;
@@ -2291,6 +2299,10 @@ static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
curframe->tf.f->data[1] + 8 * mb_y * s->uvlinesize,
curframe->tf.f->data[2] + 8 * mb_y * s->uvlinesize
};
+
+ if (c->end <= c->buffer && c->bits >= 0)
+ return AVERROR_INVALIDDATA;
+
if (mb_y == 0)
prev_td = td;
else
@@ -2319,6 +2331,8 @@ static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
s->mv_max.x = ((s->mb_width - 1) << 6) + MARGIN;
for (mb_x = 0; mb_x < s->mb_width; mb_x++, mb_xy++, mb++) {
+ if (c->end <= c->buffer && c->bits >= 0)
+ return AVERROR_INVALIDDATA;
// Wait for previous thread to read mb_x+2, and reach mb_y-1.
if (prev_td != td) {
if (threadnr != 0) {
@@ -2394,9 +2408,22 @@ static void vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
update_pos(td, mb_y, mb_x);
}
}
+ return 0;
}
-static void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata,
+static int vp7_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
+ int jobnr, int threadnr)
+{
+ return decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 1);
+}
+
+static int vp8_decode_mb_row_no_filter(AVCodecContext *avctx, void *tdata,
+ int jobnr, int threadnr)
+{
+ return decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, 0);
+}
+
+static av_always_inline void filter_mb_row(AVCodecContext *avctx, void *tdata,
int jobnr, int threadnr, int is_vp7)
{
VP8Context *s = avctx->priv_data;
@@ -2455,6 +2482,18 @@ static void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata,
}
}
+static void vp7_filter_mb_row(AVCodecContext *avctx, void *tdata,
+ int jobnr, int threadnr)
+{
+ filter_mb_row(avctx, tdata, jobnr, threadnr, 1);
+}
+
+static void vp8_filter_mb_row(AVCodecContext *avctx, void *tdata,
+ int jobnr, int threadnr)
+{
+ filter_mb_row(avctx, tdata, jobnr, threadnr, 0);
+}
+
static av_always_inline
int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr,
int threadnr, int is_vp7)
@@ -2464,15 +2503,18 @@ int vp78_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata, int jobnr,
VP8ThreadData *next_td = NULL, *prev_td = NULL;
VP8Frame *curframe = s->curframe;
int mb_y, num_jobs = s->num_jobs;
+ int ret;
td->thread_nr = threadnr;
for (mb_y = jobnr; mb_y < s->mb_height; mb_y += num_jobs) {
- if (mb_y >= s->mb_height)
- break;
td->thread_mb_pos = mb_y << 16;
- vp8_decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr, is_vp7);
+ ret = s->decode_mb_row_no_filter(avctx, tdata, jobnr, threadnr);
+ if (ret < 0) {
+ update_pos(td, s->mb_height, INT_MAX & 0xFFFF);
+ return ret;
+ }
if (s->deblock_filter)
- vp8_filter_mb_row(avctx, tdata, jobnr, threadnr, is_vp7);
+ s->filter_mb_row(avctx, tdata, jobnr, threadnr);
update_pos(td, mb_y, INT_MAX & 0xFFFF);
s->mv_min.y -= 64;
@@ -2497,6 +2539,7 @@ static int vp8_decode_mb_row_sliced(AVCodecContext *avctx, void *tdata,
return vp78_decode_mb_row_sliced(avctx, tdata, jobnr, threadnr, IS_VP8);
}
+
static av_always_inline
int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
AVPacket *avpkt, int is_vp7)
@@ -2514,23 +2557,6 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
if (ret < 0)
goto err;
- if (!is_vp7 && s->pix_fmt == AV_PIX_FMT_NONE) {
- enum AVPixelFormat pix_fmts[] = {
-#if CONFIG_VP8_VAAPI_HWACCEL
- AV_PIX_FMT_VAAPI,
-#endif
- AV_PIX_FMT_YUV420P,
- AV_PIX_FMT_NONE,
- };
-
- s->pix_fmt = ff_get_format(s->avctx, pix_fmts);
- if (s->pix_fmt < 0) {
- ret = AVERROR(EINVAL);
- goto err;
- }
- avctx->pix_fmt = s->pix_fmt;
- }
-
prev_frame = s->framep[VP56_FRAME_CURRENT];
referenced = s->update_last || s->update_golden == VP56_FRAME_CURRENT ||
@@ -2581,10 +2607,8 @@ int vp78_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)
@@ -2604,70 +2628,55 @@ int vp78_decode_frame(AVCodecContext *avctx, void *data, int *got_frame,
s->next_framep[VP56_FRAME_CURRENT] = curframe;
- ff_thread_finish_setup(avctx);
+ if (avctx->codec->update_thread_context)
+ ff_thread_finish_setup(avctx);
- if (avctx->hwaccel) {
- ret = avctx->hwaccel->start_frame(avctx, avpkt->data, avpkt->size);
- if (ret < 0)
- goto err;
+ s->linesize = curframe->tf.f->linesize[0];
+ s->uvlinesize = curframe->tf.f->linesize[1];
- ret = avctx->hwaccel->decode_slice(avctx, avpkt->data, avpkt->size);
- if (ret < 0)
- goto err;
-
- ret = avctx->hwaccel->end_frame(avctx);
- if (ret < 0)
- goto err;
+ memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz));
+ /* Zero macroblock structures for top/top-left prediction
+ * from outside the frame. */
+ if (!s->mb_layout)
+ memset(s->macroblocks + s->mb_height * 2 - 1, 0,
+ (s->mb_width + 1) * sizeof(*s->macroblocks));
+ if (!s->mb_layout && s->keyframe)
+ memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4);
- } else {
- s->linesize = curframe->tf.f->linesize[0];
- s->uvlinesize = curframe->tf.f->linesize[1];
-
- memset(s->top_nnz, 0, s->mb_width * sizeof(*s->top_nnz));
- /* Zero macroblock structures for top/top-left prediction
- * from outside the frame. */
- if (!s->mb_layout)
- memset(s->macroblocks + s->mb_height * 2 - 1, 0,
- (s->mb_width + 1) * sizeof(*s->macroblocks));
- if (!s->mb_layout && s->keyframe)
- memset(s->intra4x4_pred_mode_top, DC_PRED, s->mb_width * 4);
-
- memset(s->ref_count, 0, sizeof(s->ref_count));
-
- if (s->mb_layout == 1) {
- // Make sure the previous frame has read its segmentation map,
- // if we re-use the same map.
- if (prev_frame && s->segmentation.enabled &&
- !s->segmentation.update_map)
- ff_thread_await_progress(&prev_frame->tf, 1, 0);
- if (is_vp7)
- vp7_decode_mv_mb_modes(avctx, curframe, prev_frame);
- else
- vp8_decode_mv_mb_modes(avctx, curframe, prev_frame);
- }
-
- if (avctx->active_thread_type == FF_THREAD_FRAME)
- num_jobs = 1;
- else
- num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count);
- s->num_jobs = num_jobs;
- s->curframe = curframe;
- s->prev_frame = prev_frame;
- s->mv_min.y = -MARGIN;
- s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
- for (i = 0; i < MAX_THREADS; i++) {
- s->thread_data[i].thread_mb_pos = 0;
- s->thread_data[i].wait_mb_pos = INT_MAX;
- }
+ memset(s->ref_count, 0, sizeof(s->ref_count));
+ if (s->mb_layout == 1) {
+ // Make sure the previous frame has read its segmentation map,
+ // if we re-use the same map.
+ if (prev_frame && s->segmentation.enabled &&
+ !s->segmentation.update_map)
+ ff_thread_await_progress(&prev_frame->tf, 1, 0);
if (is_vp7)
- avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL,
- num_jobs);
+ vp7_decode_mv_mb_modes(avctx, curframe, prev_frame);
else
- avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL,
- num_jobs);
+ vp8_decode_mv_mb_modes(avctx, curframe, prev_frame);
}
+ if (avctx->active_thread_type == FF_THREAD_FRAME)
+ num_jobs = 1;
+ else
+ num_jobs = FFMIN(s->num_coeff_partitions, avctx->thread_count);
+ s->num_jobs = num_jobs;
+ s->curframe = curframe;
+ s->prev_frame = prev_frame;
+ s->mv_min.y = -MARGIN;
+ s->mv_max.y = ((s->mb_height - 1) << 6) + MARGIN;
+ for (i = 0; i < MAX_THREADS; i++) {
+ s->thread_data[i].thread_mb_pos = 0;
+ s->thread_data[i].wait_mb_pos = INT_MAX;
+ }
+ if (is_vp7)
+ avctx->execute2(avctx, vp7_decode_mb_row_sliced, s->thread_data, NULL,
+ num_jobs);
+ else
+ avctx->execute2(avctx, vp8_decode_mb_row_sliced, s->thread_data, NULL,
+ num_jobs);
+
ff_thread_report_progress(&curframe->tf, INT_MAX, 0);
memcpy(&s->framep[0], &s->next_framep[0], sizeof(s->framep[0]) * 4);
@@ -2708,6 +2717,9 @@ av_cold int ff_vp8_decode_free(AVCodecContext *avctx)
VP8Context *s = avctx->priv_data;
int i;
+ if (!s)
+ return 0;
+
vp8_decode_flush_impl(avctx, 1);
for (i = 0; i < FF_ARRAY_ELEMS(s->frames); i++)
av_frame_free(&s->frames[i].tf.f);
@@ -2733,7 +2745,7 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7)
int ret;
s->avctx = avctx;
- s->pix_fmt = AV_PIX_FMT_NONE;
+ s->vp7 = avctx->codec->id == AV_CODEC_ID_VP7;
avctx->pix_fmt = AV_PIX_FMT_YUV420P;
avctx->internal->allocate_progress = 1;
@@ -2743,9 +2755,13 @@ int vp78_decode_init(AVCodecContext *avctx, int is_vp7)
if (CONFIG_VP7_DECODER && is_vp7) {
ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP7, 8, 1);
ff_vp7dsp_init(&s->vp8dsp);
+ s->decode_mb_row_no_filter = vp7_decode_mb_row_no_filter;
+ s->filter_mb_row = vp7_filter_mb_row;
} else if (CONFIG_VP8_DECODER && !is_vp7) {
ff_h264_pred_init(&s->hpc, AV_CODEC_ID_VP8, 8, 1);
ff_vp8dsp_init(&s->vp8dsp);
+ s->decode_mb_row_no_filter = vp8_decode_mb_row_no_filter;
+ s->filter_mb_row = vp8_filter_mb_row;
}
/* does not change for VP8 */
@@ -2772,6 +2788,7 @@ av_cold int ff_vp8_decode_init(AVCodecContext *avctx)
}
#if CONFIG_VP8_DECODER
+#if HAVE_THREADS
static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx)
{
VP8Context *s = avctx->priv_data;
@@ -2787,7 +2804,7 @@ static av_cold int vp8_decode_init_thread_copy(AVCodecContext *avctx)
return 0;
}
-#define REBASE(pic) pic ? pic - &s_src->frames[0] + &s->frames[0] : NULL
+#define REBASE(pic) ((pic) ? (pic) - &s_src->frames[0] + &s->frames[0] : NULL)
static int vp8_decode_update_thread_context(AVCodecContext *dst,
const AVCodecContext *src)
@@ -2822,6 +2839,7 @@ static int vp8_decode_update_thread_context(AVCodecContext *dst,
return 0;
}
+#endif /* HAVE_THREADS */
#endif /* CONFIG_VP8_DECODER */
#if CONFIG_VP7_DECODER