Browse Source

avcodec/vp56: Implement very basic error concealment

This should fix the fate failure due to a truncated last frame.
Alternatively the frame could be dropped.

Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
tags/n3.3
Michael Niedermayer 8 years ago
parent
commit
d34bf886e9
2 changed files with 79 additions and 4 deletions
  1. +78
    -3
      libavcodec/vp56.c
  2. +1
    -1
      tests/ref/fate/vp5

+ 78
- 3
libavcodec/vp56.c View File

@@ -261,6 +261,25 @@ static VP56mb vp56_decode_mv(VP56Context *s, int row, int col)
return s->mb_type; 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) static void vp56_add_predictors_dc(VP56Context *s, VP56Frame ref_frame)
{ {
int idx = s->idct_scantable[0]; int idx = s->idct_scantable[0];
@@ -457,6 +476,57 @@ static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
return 0; return 0;
} }


static int vp56_conceal_mb(VP56Context *s, int row, int col, int is_alpha)
{
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_conceal_mv(s, row, col);
ref_frame = ff_vp56_reference_frame[mb_type];

frame_current = s->frames[VP56_FRAME_CURRENT];
frame_ref = s->frames[ref_frame];
if (mb_type != VP56_MB_INTRA && !frame_ref->data[0])
return 0;

ab = 6*is_alpha;
b_max = 6 - 2*is_alpha;

switch (mb_type) {
case VP56_MB_INTRA:
for (b=0; b<b_max; b++) {
plane = ff_vp56_b2p[b+ab];
s->vp3dsp.idct_put(frame_current->data[plane] + s->block_offset[b],
s->stride[plane], s->block_coeff[b]);
}
break;

case VP56_MB_INTER_NOVEC_PF:
case VP56_MB_INTER_NOVEC_GF:
for (b=0; b<b_max; b++) {
plane = ff_vp56_b2p[b+ab];
off = s->block_offset[b];
s->hdsp.put_pixels_tab[1][0](frame_current->data[plane] + off,
frame_ref->data[plane] + off,
s->stride[plane], 8);
s->vp3dsp.idct_add(frame_current->data[plane] + off,
s->stride[plane], s->block_coeff[b]);
}
break;
}

if (is_alpha) {
s->block_coeff[4][0] = 0;
s->block_coeff[5][0] = 0;
}
return 0;
}

static int vp56_size_changed(VP56Context *s) static int vp56_size_changed(VP56Context *s)
{ {
AVCodecContext *avctx = s->avctx; AVCodecContext *avctx = s->avctx;
@@ -593,6 +663,7 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
int block, y, uv; int block, y, uv;
ptrdiff_t stride_y, stride_uv; ptrdiff_t stride_y, stride_uv;
int res; int res;
int damaged = 0;


if (p->key_frame) { if (p->key_frame) {
p->pict_type = AV_PICTURE_TYPE_I; p->pict_type = AV_PICTURE_TYPE_I;
@@ -657,9 +728,13 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
s->block_offset[5] = s->block_offset[4]; s->block_offset[5] = s->block_offset[4];


for (mb_col=0; mb_col<s->mb_width; mb_col++) { for (mb_col=0; mb_col<s->mb_width; mb_col++) {
int ret = vp56_decode_mb(s, mb_row, mb_col, is_alpha);
if (ret < 0)
return ret;
if (!damaged) {
int ret = vp56_decode_mb(s, mb_row, mb_col, is_alpha);
if (ret < 0)
damaged = 1;
}
if (damaged)
vp56_conceal_mb(s, mb_row, mb_col, is_alpha);


for (y=0; y<4; y++) { for (y=0; y<4; y++) {
s->above_block_idx[y] += 2; s->above_block_idx[y] += 2;


+ 1
- 1
tests/ref/fate/vp5 View File

@@ -249,4 +249,4 @@
0, 243, 243, 1, 233472, 0x6f530ac6 0, 243, 243, 1, 233472, 0x6f530ac6
0, 244, 244, 1, 233472, 0x94f7466c 0, 244, 244, 1, 233472, 0x94f7466c
0, 245, 245, 1, 233472, 0xa8c1d365 0, 245, 245, 1, 233472, 0xa8c1d365
0, 246, 246, 1, 233472, 0x8843293b
0, 246, 246, 1, 233472, 0xbf73f1b7

Loading…
Cancel
Save