[FFmpeg-cvslog] avcodec/vp56: Implement very basic error concealment

Michael Niedermayer git at videolan.org
Sat Feb 25 14:10:30 EET 2017


ffmpeg | branch: master | Michael Niedermayer <michael at niedermayer.cc> | Sat Feb 25 12:37:32 2017 +0100| [d34bf886e963445350c4987f7a9ed77bd9c9a5c7] | committer: Michael Niedermayer

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 at niedermayer.cc>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=d34bf886e963445350c4987f7a9ed77bd9c9a5c7
---

 libavcodec/vp56.c  | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 tests/ref/fate/vp5 |  2 +-
 2 files changed, 79 insertions(+), 4 deletions(-)

diff --git a/libavcodec/vp56.c b/libavcodec/vp56.c
index d8fe994..b36c99f 100644
--- a/libavcodec/vp56.c
+++ b/libavcodec/vp56.c
@@ -261,6 +261,25 @@ static VP56mb vp56_decode_mv(VP56Context *s, int row, int col)
     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];
@@ -457,6 +476,57 @@ static int vp56_decode_mb(VP56Context *s, int row, int col, int is_alpha)
     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)
 {
     AVCodecContext *avctx = s->avctx;
@@ -593,6 +663,7 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
     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;
@@ -657,9 +728,13 @@ static int ff_vp56_decode_mbs(AVCodecContext *avctx, void *data,
         s->block_offset[5] = s->block_offset[4];
 
         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++) {
                 s->above_block_idx[y] += 2;
diff --git a/tests/ref/fate/vp5 b/tests/ref/fate/vp5
index da510fc..2469a3e 100644
--- a/tests/ref/fate/vp5
+++ b/tests/ref/fate/vp5
@@ -249,4 +249,4 @@
 0,        243,        243,        1,   233472, 0x6f530ac6
 0,        244,        244,        1,   233472, 0x94f7466c
 0,        245,        245,        1,   233472, 0xa8c1d365
-0,        246,        246,        1,   233472, 0x8843293b
+0,        246,        246,        1,   233472, 0xbf73f1b7



More information about the ffmpeg-cvslog mailing list