Decoder fixes to better support reference picture selection.
authorStefan Holmer <holmer@google.com>
Fri, 18 Nov 2011 14:44:17 +0000 (15:44 +0100)
committerStefan Holmer <holmer@google.com>
Mon, 21 Nov 2011 09:25:21 +0000 (10:25 +0100)
Change-Id: Id3388985d754706b9fd1f079c47121e79a63efdf

vp8/decoder/decodframe.c
vp8/decoder/error_concealment.c
vp8/decoder/onyxd_if.c

index e501b9e..6f2cdfa 100644 (file)
@@ -934,16 +934,38 @@ int vp8_decode_frame(VP8D_COMP *pbi)
         if (!pc->refresh_golden_frame)
             pc->copy_buffer_to_gf = vp8_read_literal(bc, 2);
 
+#if CONFIG_ERROR_CONCEALMENT
+        /* Assume we shouldn't copy to the golden if the bit is missing */
+        xd->corrupted |= vp8dx_bool_error(bc);
+        if (pbi->ec_active && xd->corrupted)
+            pc->copy_buffer_to_gf = 0;
+#endif
+
         pc->copy_buffer_to_arf = 0;
 
         if (!pc->refresh_alt_ref_frame)
             pc->copy_buffer_to_arf = vp8_read_literal(bc, 2);
 
+#if CONFIG_ERROR_CONCEALMENT
+        /* Assume we shouldn't copy to the alt-ref if the bit is missing */
+        xd->corrupted |= vp8dx_bool_error(bc);
+        if (pbi->ec_active && xd->corrupted)
+            pc->copy_buffer_to_arf = 0;
+#endif
+
+
         pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp8_read_bit(bc);
         pc->ref_frame_sign_bias[ALTREF_FRAME] = vp8_read_bit(bc);
     }
 
     pc->refresh_entropy_probs = vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+    /* Assume we shouldn't refresh the probabilities if the bit is
+     * missing */
+    xd->corrupted |= vp8dx_bool_error(bc);
+    if (pbi->ec_active && xd->corrupted)
+        pc->refresh_entropy_probs = 0;
+#endif
     if (pc->refresh_entropy_probs == 0)
     {
         vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc));
index 86fa191..b77d743 100644 (file)
@@ -491,33 +491,6 @@ static void find_neighboring_blocks(MODE_INFO *mi,
     assert(i == 20);
 }
 
-/* Calculates which reference frame type is dominating among the neighbors */
-static MV_REFERENCE_FRAME dominant_ref_frame(EC_BLOCK *neighbors)
-{
-    /* Default to referring to "skip" */
-    MV_REFERENCE_FRAME dom_ref_frame = LAST_FRAME;
-    int max_ref_frame_cnt = 0;
-    int ref_frame_cnt[MAX_REF_FRAMES] = {0};
-    int i;
-    /* Count neighboring reference frames */
-    for (i = 0; i < NUM_NEIGHBORS; ++i)
-    {
-        if (neighbors[i].ref_frame < MAX_REF_FRAMES &&
-            neighbors[i].ref_frame != INTRA_FRAME)
-            ++ref_frame_cnt[neighbors[i].ref_frame];
-    }
-    /* Find maximum */
-    for (i = 0; i < MAX_REF_FRAMES; ++i)
-    {
-        if (ref_frame_cnt[i] > max_ref_frame_cnt)
-        {
-            dom_ref_frame = i;
-            max_ref_frame_cnt = ref_frame_cnt[i];
-        }
-    }
-    return dom_ref_frame;
-}
-
 /* Interpolates all motion vectors for a macroblock from the neighboring blocks'
  * motion vectors.
  */
@@ -591,7 +564,6 @@ void vp8_interpolate_motion(MACROBLOCKD *mb,
 {
     /* Find relevant neighboring blocks */
     EC_BLOCK neighbors[NUM_NEIGHBORS];
-    MV_REFERENCE_FRAME dom_ref_frame;
     int i;
     /* Initialize the array. MAX_REF_FRAMES is interpreted as "doesn't exist" */
     for (i = 0; i < NUM_NEIGHBORS; ++i)
@@ -604,13 +576,11 @@ void vp8_interpolate_motion(MACROBLOCKD *mb,
                                 mb_row, mb_col,
                                 mb_rows, mb_cols,
                                 mb->mode_info_stride);
-    /* Determine the dominant block type */
-    dom_ref_frame = dominant_ref_frame(neighbors);
-    /* Interpolate MVs for the missing blocks
-     * from the dominating MVs */
-    interpolate_mvs(mb, neighbors, dom_ref_frame);
+    /* Interpolate MVs for the missing blocks from the surrounding
+     * blocks which refer to the last frame. */
+    interpolate_mvs(mb, neighbors, LAST_FRAME);
 
-    mb->mode_info_context->mbmi.ref_frame = dom_ref_frame;
+    mb->mode_info_context->mbmi.ref_frame = LAST_FRAME;
     mb->mode_info_context->mbmi.mode = SPLITMV;
     mb->mode_info_context->mbmi.uv_mode = DC_PRED;
     mb->mode_info_context->mbmi.partitioning = 3;
index 0779549..cf525f4 100644 (file)
@@ -359,28 +359,38 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
         pbi->fragment_sizes[0] = 0;
     }
 
-    if (pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 0)
+    if (!pbi->ec_active &&
+        pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 0)
     {
-       /* This is used to signal that we are missing frames.
-        * We do not know if the missing frame(s) was supposed to update
-        * any of the reference buffers, but we act conservative and
-        * mark only the last buffer as corrupted.
-        */
-        cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
-
         /* If error concealment is disabled we won't signal missing frames
          * to the decoder.
          */
-        if (!pbi->ec_active)
+        if (cm->fb_idx_ref_cnt[cm->lst_fb_idx] > 1)
         {
-            /* Signal that we have no frame to show. */
-            cm->show_frame = 0;
+            /* The last reference shares buffer with another reference
+             * buffer. Move it to its own buffer before setting it as
+             * corrupt, otherwise we will make multiple buffers corrupt.
+             */
+            const int prev_idx = cm->lst_fb_idx;
+            cm->fb_idx_ref_cnt[prev_idx]--;
+            cm->lst_fb_idx = get_free_fb(cm);
+            vp8_yv12_copy_frame_ptr(&cm->yv12_fb[prev_idx],
+                                    &cm->yv12_fb[cm->lst_fb_idx]);
+        }
+        /* This is used to signal that we are missing frames.
+         * We do not know if the missing frame(s) was supposed to update
+         * any of the reference buffers, but we act conservative and
+         * mark only the last buffer as corrupted.
+         */
+        cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
 
-            pbi->num_fragments = 0;
+        /* Signal that we have no frame to show. */
+        cm->show_frame = 0;
 
-            /* Nothing more to do. */
-            return 0;
-        }
+        pbi->num_fragments = 0;
+
+        /* Nothing more to do. */
+        return 0;
     }
 
 #if HAVE_ARMV7