return s->mb_type;
}
+static VP56mb vp56_conceal_mv(VP56Context *s, int row, int col)
+{
+ VP56mv *mv, vect = {0,0};
+ int b;
+
+ s->mb_type = VP56_MB_INTER_NOVEC_PF;
+ s->macroblocks[row * s->mb_width + col].type = s->mb_type;
+
+ mv = &vect;
+
+ s->macroblocks[row*s->mb_width + col].mv = *mv;
+
+ /* same vector for all blocks */
+ for (b=0; b<6; b++)
+ s->mv[b] = *mv;
+
+ return s->mb_type;
+}
+
static void vp56_add_predictors_dc(VP56Context *s, VP56Frame ref_frame)
{
int idx = s->idct_scantable[0];
}
}
-static void vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
+static av_always_inline void vp56_render_mb(VP56Context *s, int row, int col, int is_alpha, VP56mb mb_type)
{
- AVFrame *frame_current, *frame_ref;
- VP56mb mb_type;
- VP56Frame ref_frame;
int b, ab, b_max, plane, off;
-
- if (s->frames[VP56_FRAME_CURRENT]->key_frame)
- mb_type = VP56_MB_INTRA;
- else
- mb_type = vp56_decode_mv(s, row, col);
- ref_frame = ff_vp56_reference_frame[mb_type];
-
- s->parse_coeff(s);
+ AVFrame *frame_current, *frame_ref;
+ VP56Frame ref_frame = ff_vp56_reference_frame[mb_type];
vp56_add_predictors_dc(s, ref_frame);
}
}
+static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
+{
+ VP56mb mb_type;
+ int ret;
+
+ if (s->frames[VP56_FRAME_CURRENT]->key_frame)
+ mb_type = VP56_MB_INTRA;
+ else
+ mb_type = vp56_decode_mv(s, row, col);
+
+ ret = s->parse_coeff(s);
+ if (ret < 0)
+ return ret;
+
+ vp56_render_mb(s, row, col, is_alpha, mb_type);
+
+ return 0;
+}
+
+static int vp56_conceal_mb(VP56Context *s, int row, int col, int is_alpha)
+{
+ VP56mb mb_type;
+
+ if (s->frames[VP56_FRAME_CURRENT]->key_frame)
+ mb_type = VP56_MB_INTRA;
+ else
+ mb_type = vp56_conceal_mv(s, row, col);
+
+ vp56_render_mb(s, row, col, is_alpha, mb_type);
+
+ return 0;
+}
+
static int vp56_size_changed(VP56Context *s)
{
AVCodecContext *avctx = s->avctx;
s->plane_height[0] = s->plane_height[3] = avctx->coded_height;
s->plane_height[1] = s->plane_height[2] = avctx->coded_height/2;
+ s->have_undamaged_frame = 0;
+
for (i=0; i<4; i++)
s->stride[i] = s->flip * s->frames[VP56_FRAME_CURRENT]->linesize[i];
}
ret = ff_get_buffer(avctx, p, AV_GET_BUFFER_FLAG_REF);
- if (ret < 0)
+ if (ret < 0) {
+ if (res == VP56_SIZE_CHANGE)
+ ff_set_dimensions(avctx, 0, 0);
return ret;
+ }
if (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) {
av_frame_unref(s->alpha_context->frames[VP56_FRAME_CURRENT]);
if ((ret = av_frame_ref(s->alpha_context->frames[VP56_FRAME_CURRENT], p)) < 0) {
av_frame_unref(p);
+ if (res == VP56_SIZE_CHANGE)
+ ff_set_dimensions(avctx, 0, 0);
return ret;
}
}
}
}
+ s->discard_frame = 0;
avctx->execute2(avctx, ff_vp56_decode_mbs, 0, 0, (avctx->pix_fmt == AV_PIX_FMT_YUVA420P) + 1);
+ if (s->discard_frame)
+ return AVERROR_INVALIDDATA;
+
if ((res = av_frame_ref(data, p)) < 0)
return res;
*got_frame = 1;
int block, y, uv;
ptrdiff_t stride_y, stride_uv;
int res;
+ int damaged = 0;
if (p->key_frame) {
p->pict_type = AV_PICTURE_TYPE_I;
s->block_offset[5] = s->block_offset[4];
for (mb_col=0; mb_col<s->mb_width; mb_col++) {
- vp56_decode_mb(s, mb_row, mb_col, is_alpha);
+ if (!damaged) {
+ int ret = vp56_decode_mb(s, mb_row, mb_col, is_alpha);
+ if (ret < 0) {
+ damaged = 1;
+ if (!s->have_undamaged_frame) {
+ s->discard_frame = 1;
+ return AVERROR_INVALIDDATA;
+ }
+ }
+ }
+ if (damaged)
+ vp56_conceal_mb(s, mb_row, mb_col, is_alpha);
for (y=0; y<4; y++) {
s->above_block_idx[y] += 2;
}
}
+ if (!damaged)
+ s->have_undamaged_frame = 1;
+
next:
if (p->key_frame || s->golden_frame) {
av_frame_unref(s->frames[VP56_FRAME_GOLDEN]);