shithub: libvpx

Download patch

ref: 3d1f3fc6c9f20c9c42b51d3838a2ab10f2c362b5
parent: 939f64f68efc837a98a5c80913a4bde50b79854f
parent: 4645c89889aba53a1665934a42f082a23832f493
author: John Koleszar <jkoleszar@google.com>
date: Fri Aug 12 20:05:10 EDT 2011

Merge remote branch 'origin/master' into experimental

Change-Id: Ie6bc53eb61dc772f308abce9bf93bcc67b38f670

--- a/vp8/decoder/decodemv.c
+++ b/vp8/decoder/decodemv.c
@@ -400,7 +400,7 @@
             /* Clip "next_nearest" so that it does not extend to far out of image */
             vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
                          mb_to_top_edge, mb_to_bottom_edge);
-            break;
+            goto propagate_mv;
 
         case NEARESTMV:
             mv->as_int = nearest.as_int;
@@ -407,11 +407,11 @@
             /* Clip "next_nearest" so that it does not extend to far out of image */
             vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
                          mb_to_top_edge, mb_to_bottom_edge);
-            break;
+            goto propagate_mv;
 
         case ZEROMV:
             mv->as_int = 0;
-            break;
+            goto propagate_mv;
 
         case NEWMV:
             read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc);
@@ -428,8 +428,30 @@
                                                       mb_to_right_edge,
                                                       mb_to_top_edge,
                                                       mb_to_bottom_edge);
-            break;
 
+        propagate_mv:  /* same MV throughout */
+#if CONFIG_ERROR_CONCEALMENT
+            if(pbi->ec_enabled)
+            {
+                mi->bmi[ 0].mv.as_int =
+                mi->bmi[ 1].mv.as_int =
+                mi->bmi[ 2].mv.as_int =
+                mi->bmi[ 3].mv.as_int =
+                mi->bmi[ 4].mv.as_int =
+                mi->bmi[ 5].mv.as_int =
+                mi->bmi[ 6].mv.as_int =
+                mi->bmi[ 7].mv.as_int =
+                mi->bmi[ 8].mv.as_int =
+                mi->bmi[ 9].mv.as_int =
+                mi->bmi[10].mv.as_int =
+                mi->bmi[11].mv.as_int =
+                mi->bmi[12].mv.as_int =
+                mi->bmi[13].mv.as_int =
+                mi->bmi[14].mv.as_int =
+                mi->bmi[15].mv.as_int = mv->as_int;
+            }
+#endif
+            break;
         default:;
   #if CONFIG_DEBUG
             assert(0);
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -183,6 +183,7 @@
                               unsigned int mb_idx)
 {
     int eobtotal = 0;
+    int throw_residual = 0;
     MB_PREDICTION_MODE mode;
     int i;
 
@@ -203,7 +204,8 @@
 
     mode = xd->mode_info_context->mbmi.mode;
 
-    if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV)
+    if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV &&
+            !vp8dx_bool_error(xd->current_bc))
     {
         /* Special case:  Force the loopfilter to skip when eobtotal and
          * mb_skip_coeff are zero.
@@ -235,14 +237,21 @@
         vp8_build_inter_predictors_mb(xd);
     }
 
+    /* When we have independent partitions we can apply residual even
+     * though other partitions within the frame are corrupt.
+     */
+    throw_residual = (!pbi->independent_partitions &&
+                      pbi->frame_corrupt_residual);
+    throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
 #if CONFIG_ERROR_CONCEALMENT
-    if (pbi->ec_enabled &&
-        (mb_idx >= pbi->mvs_corrupt_from_mb ||
-        vp8dx_bool_error(xd->current_bc)))
+    if (pbi->ec_active &&
+        (mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
     {
         /* MB with corrupt residuals or corrupt mode/motion vectors.
          * Better to use the predictor as reconstruction.
          */
+        pbi->frame_corrupt_residual = 1;
         vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
         vp8_conceal_corrupt_mb(xd);
         return;
@@ -376,22 +385,28 @@
         xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
 
 #if CONFIG_ERROR_CONCEALMENT
-        if (pbi->ec_enabled &&
-            xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
-            vp8dx_bool_error(xd->current_bc))
         {
-            /* We have an intra block with corrupt coefficients, better to
-             * conceal with an inter block. Interpolate MVs from neighboring MBs
-             *
-             * Note that for the first mb with corrupt residual in a frame,
-             * we might not discover that before decoding the residual. That
-             * happens after this check, and therefore no inter concealment will
-             * be done.
-             */
-            vp8_interpolate_motion(xd,
-                                   mb_row, mb_col,
-                                   pc->mb_rows, pc->mb_cols,
-                                   pc->mode_info_stride);
+            int corrupt_residual = (!pbi->independent_partitions &&
+                                   pbi->frame_corrupt_residual) ||
+                                   vp8dx_bool_error(xd->current_bc);
+            if (pbi->ec_active &&
+                xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
+                corrupt_residual)
+            {
+                /* We have an intra block with corrupt coefficients, better to
+                 * conceal with an inter block. Interpolate MVs from neighboring
+                 * MBs.
+                 *
+                 * Note that for the first mb with corrupt residual in a frame,
+                 * we might not discover that before decoding the residual. That
+                 * happens after this check, and therefore no inter concealment
+                 * will be done.
+                 */
+                vp8_interpolate_motion(xd,
+                                       mb_row, mb_col,
+                                       pc->mb_rows, pc->mb_cols,
+                                       pc->mode_info_stride);
+            }
         }
 #endif
 
@@ -495,6 +510,15 @@
 #endif
 }
 
+
+static int read_is_valid(const unsigned char *start,
+                         size_t               len,
+                         const unsigned char *end)
+{
+    return (start + len > start && start + len <= end);
+}
+
+
 static void setup_token_decoder(VP8D_COMP *pbi,
                                 const unsigned char *cx_data)
 {
@@ -510,7 +534,7 @@
             (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
     /* Only update the multi_token_partition field if we are sure the value
      * is correct. */
-    if (!pbi->ec_enabled || !vp8dx_bool_error(&pbi->bc))
+    if (!pbi->ec_active || !vp8dx_bool_error(&pbi->bc))
         pc->multi_token_partition = multi_token_partition;
 
     num_part = 1 << pc->multi_token_partition;
@@ -529,26 +553,42 @@
     for (i = 0; i < num_part; i++)
     {
         const unsigned char *partition_size_ptr = cx_data + i * 3;
-        ptrdiff_t            partition_size;
+        ptrdiff_t            partition_size, bytes_left;
 
+        bytes_left = user_data_end - partition;
+
         /* Calculate the length of this partition. The last partition
-         * size is implicit.
+         * size is implicit. If the partition size can't be read, then
+         * either use the remaining data in the buffer (for EC mode)
+         * or throw an error.
          */
         if (i < num_part - 1)
         {
-            partition_size = read_partition_size(partition_size_ptr);
+            if (read_is_valid(partition_size_ptr, 3, user_data_end))
+                partition_size = read_partition_size(partition_size_ptr);
+            else if (pbi->ec_active)
+                partition_size = bytes_left;
+            else
+                vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                   "Truncated partition size data");
         }
         else
+            partition_size = bytes_left;
+
+        /* Validate the calculated partition length. If the buffer
+         * described by the partition can't be fully read, then restrict
+         * it to the portion that can be (for EC mode) or throw an error.
+         */
+        if (!read_is_valid(partition, partition_size, user_data_end))
         {
-            partition_size = user_data_end - partition;
+            if (pbi->ec_active)
+                partition_size = bytes_left;
+            else
+                vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+                                   "Truncated packet or corrupt partition "
+                                   "%d length", i + 1);
         }
 
-        if (!pbi->ec_enabled && (partition + partition_size > user_data_end
-            || partition + partition_size < partition))
-            vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
-                               "Truncated packet or corrupt partition "
-                               "%d length", i + 1);
-
         if (vp8dx_start_decode(bool_decoder, partition, partition_size))
             vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
                                "Failed to allocate bool decoder %d", i + 1);
@@ -634,6 +674,9 @@
             xd->subpixel_predict8x8   = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
             xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
         }
+
+        if (pbi->decoded_key_frame && pbi->ec_enabled && !pbi->ec_active)
+            pbi->ec_active = 1;
     }
 
     xd->left_context = &pc->left_context;
@@ -656,6 +699,8 @@
     int mb_row;
     int i, j, k, l;
     const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
+    int corrupt_tokens = 0;
+    int prev_independent_partitions = pbi->independent_partitions;
 
     if (pbi->input_partition)
     {
@@ -669,7 +714,7 @@
 
     if (data_end - data < 3)
     {
-        if (pbi->ec_enabled)
+        if (pbi->ec_active)
         {
             /* Declare the missing frame as an inter frame since it will
                be handled as an inter frame when we have estimated its
@@ -694,7 +739,7 @@
             (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
         data += 3;
 
-        if (!pbi->ec_enabled && (data + first_partition_length_in_bytes > data_end
+        if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
             || data + first_partition_length_in_bytes < data))
             vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
                                "Truncated packet or corrupt partition 0 length");
@@ -709,7 +754,7 @@
             /* When error concealment is enabled we should only check the sync
              * code if we have enough bits available
              */
-            if (!pbi->ec_enabled || data + 3 < data_end)
+            if (!pbi->ec_active || data + 3 < data_end)
             {
                 if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
                     vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
@@ -720,7 +765,7 @@
              * if we have enough data. Otherwise we will end up with the wrong
              * size.
              */
-            if (!pbi->ec_enabled || data + 6 < data_end)
+            if (!pbi->ec_active || data + 6 < data_end)
             {
                 pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
                 pc->horiz_scale = data[4] >> 6;
@@ -919,7 +964,7 @@
 #if CONFIG_ERROR_CONCEALMENT
         /* Assume we shouldn't refresh golden if the bit is missing */
         xd->corrupted |= vp8dx_bool_error(bc);
-        if (pbi->ec_enabled && xd->corrupted)
+        if (pbi->ec_active && xd->corrupted)
             pc->refresh_golden_frame = 0;
 #endif
 
@@ -927,7 +972,7 @@
 #if CONFIG_ERROR_CONCEALMENT
         /* Assume we shouldn't refresh altref if the bit is missing */
         xd->corrupted |= vp8dx_bool_error(bc);
-        if (pbi->ec_enabled && xd->corrupted)
+        if (pbi->ec_active && xd->corrupted)
             pc->refresh_alt_ref_frame = 0;
 #endif
 
@@ -957,7 +1002,7 @@
 #if CONFIG_ERROR_CONCEALMENT
     /* Assume we should refresh the last frame if the bit is missing */
     xd->corrupted |= vp8dx_bool_error(bc);
-    if (pbi->ec_enabled && xd->corrupted)
+    if (pbi->ec_active && xd->corrupted)
         pc->refresh_last_frame = 1;
 #endif
 
@@ -975,6 +1020,8 @@
     }
 
     {
+        pbi->independent_partitions = 1;
+
         /* read coef probability tree */
         for (i = 0; i < BLOCK_TYPES; i++)
             for (j = 0; j < COEF_BANDS; j++)
@@ -989,6 +1036,9 @@
                             *p = (vp8_prob)vp8_read_literal(bc, 8);
 
                         }
+                        if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
+                            pbi->independent_partitions = 0;
+
                     }
     }
 
@@ -1015,7 +1065,7 @@
     vp8_decode_mode_mvs(pbi);
 
 #if CONFIG_ERROR_CONCEALMENT
-    if (pbi->ec_enabled &&
+    if (pbi->ec_active &&
             pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
     {
         /* Motion vectors are missing in this frame. We will try to estimate
@@ -1029,8 +1079,12 @@
 #if CONFIG_MULTITHREAD
     if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
     {
+        int i;
+        pbi->frame_corrupt_residual = 0;
         vp8mt_decode_mb_rows(pbi, xd);
         vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]);    /*cm->frame_to_show);*/
+        for (i = 0; i < pbi->decoding_thread_count; ++i)
+            corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
     }
     else
 #endif
@@ -1037,6 +1091,7 @@
     {
         int ibc = 0;
         int num_part = 1 << pc->multi_token_partition;
+        pbi->frame_corrupt_residual = 0;
 
         /* Decode the individual macro block */
         for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
@@ -1053,6 +1108,7 @@
 
             decode_mb_row(pbi, pc, mb_row, xd);
         }
+        corrupt_tokens |= xd->corrupted;
     }
 
     stop_token_decoder(pbi);
@@ -1059,12 +1115,20 @@
 
     /* Collect information about decoder corruption. */
     /* 1. Check first boolean decoder for errors. */
-    pc->yv12_fb[pc->new_fb_idx].corrupted =
-        vp8dx_bool_error(bc);
+    pc->yv12_fb[pc->new_fb_idx].corrupted = vp8dx_bool_error(bc);
     /* 2. Check the macroblock information */
-    pc->yv12_fb[pc->new_fb_idx].corrupted |=
-        xd->corrupted;
+    pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
 
+    if (!pbi->decoded_key_frame)
+    {
+        if (pc->frame_type == KEY_FRAME &&
+            !pc->yv12_fb[pc->new_fb_idx].corrupted)
+            pbi->decoded_key_frame = 1;
+        else
+            vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
+                               "A stream must start with a complete key frame");
+    }
+
     /* vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes  \n",bc->pos+pbi->bc2.pos); */
 
     /* If this was a kf or Gf note the Q used */
@@ -1077,6 +1141,7 @@
     if (pc->refresh_entropy_probs == 0)
     {
         vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
+        pbi->independent_partitions = prev_independent_partitions;
     }
 
 #ifdef PACKET_TESTING
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -101,9 +101,21 @@
 #else
     pbi->ec_enabled = 0;
 #endif
+    /* Error concealment is activated after a key frame has been
+     * decoded without errors when error concealment is enabled.
+     */
+    pbi->ec_active = 0;
 
+    pbi->decoded_key_frame = 0;
+
     pbi->input_partition = oxcf->input_partition;
 
+    /* Independent partitions is activated when a frame updates the
+     * token probability table to have equal probabilities over the
+     * PREV_COEF context.
+     */
+    pbi->independent_partitions = 0;
+
     return (VP8D_PTR) pbi;
 }
 
@@ -346,11 +358,15 @@
             /* If error concealment is disabled we won't signal missing frames to
              * the decoder.
              */
-            if (!pbi->ec_enabled)
+            if (!pbi->ec_active)
             {
                 /* Signal that we have no frame to show. */
                 cm->show_frame = 0;
 
+                pbi->num_partitions = 0;
+                if (pbi->input_partition)
+                    pbi->common.multi_token_partition = 0;
+
                 /* Nothing more to do. */
                 return 0;
             }
@@ -378,6 +394,10 @@
             }
 #endif
             pbi->common.error.setjmp = 0;
+
+            pbi->num_partitions = 0;
+            if (pbi->input_partition)
+                pbi->common.multi_token_partition = 0;
 
            /* We do not know if the missing frame(s) was supposed to update
             * any of the reference buffers, but we act conservative and
--- a/vp8/decoder/onyxd_int.h
+++ b/vp8/decoder/onyxd_int.h
@@ -132,7 +132,11 @@
     unsigned int mvs_corrupt_from_mb;
 #endif
     int ec_enabled;
+    int ec_active;
     int input_partition;
+    int decoded_key_frame;
+    int independent_partitions;
+    int frame_corrupt_residual;
 
 } VP8D_COMP;
 
--- a/vp8/decoder/threading.c
+++ b/vp8/decoder/threading.c
@@ -93,6 +93,7 @@
 static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col)
 {
     int eobtotal = 0;
+    int throw_residual = 0;
     int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
 
     if (xd->mode_info_context->mbmi.mb_skip_coeff)
@@ -112,7 +113,7 @@
 
     eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
                   xd->mode_info_context->mbmi.mode == SPLITMV);
-    if (!eobtotal)
+    if (!eobtotal && !vp8dx_bool_error(xd->current_bc))
     {
         /* Special case:  Force the loopfilter to skip when eobtotal and
          * mb_skip_coeff are zero.
@@ -154,14 +155,22 @@
         vp8_build_inter_predictors_mb(xd);
     }
 
+    /* When we have independent partitions we can apply residual even
+     * though other partitions within the frame are corrupt.
+     */
+    throw_residual = (!pbi->independent_partitions &&
+                      pbi->frame_corrupt_residual);
+    throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
 #if CONFIG_ERROR_CONCEALMENT
-    if (pbi->ec_enabled &&
+    if (pbi->ec_active &&
         (mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
-        vp8dx_bool_error(xd->current_bc)))
+        throw_residual))
     {
         /* MB with corrupt residuals or corrupt mode/motion vectors.
          * Better to use the predictor as reconstruction.
          */
+        pbi->frame_corrupt_residual = 1;
         vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
         vp8_conceal_corrupt_mb(xd);
         return;
@@ -314,25 +323,32 @@
                         xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
 
 #if CONFIG_ERROR_CONCEALMENT
-                        if (pbi->ec_enabled &&
-                            (xd->mode_info_context->mbmi.ref_frame ==
-                                                                 INTRA_FRAME) &&
-                            vp8dx_bool_error(xd->current_bc))
                         {
-                            /* We have an intra block with corrupt coefficients,
-                             * better to conceal with an inter block.
-                             * Interpolate MVs from neighboring MBs
-                             *
-                             * Note that for the first mb with corrupt residual
-                             * in a frame, we might not discover that before
-                             * decoding the residual. That happens after this
-                             * check, and therefore no inter concealment will be
-                             * done.
-                             */
-                            vp8_interpolate_motion(xd,
-                                                   mb_row, mb_col,
-                                                   pc->mb_rows, pc->mb_cols,
-                                                   pc->mode_info_stride);
+                            int corrupt_residual =
+                                        (!pbi->independent_partitions &&
+                                        pbi->frame_corrupt_residual) ||
+                                        vp8dx_bool_error(xd->current_bc);
+                            if (pbi->ec_active &&
+                                (xd->mode_info_context->mbmi.ref_frame ==
+                                                                 INTRA_FRAME) &&
+                                corrupt_residual)
+                            {
+                                /* We have an intra block with corrupt
+                                 * coefficients, better to conceal with an inter
+                                 * block.
+                                 * Interpolate MVs from neighboring MBs
+                                 *
+                                 * Note that for the first mb with corrupt
+                                 * residual in a frame, we might not discover
+                                 * that before decoding the residual. That
+                                 * happens after this check, and therefore no
+                                 * inter concealment will be done.
+                                 */
+                                vp8_interpolate_motion(xd,
+                                                       mb_row, mb_col,
+                                                       pc->mb_rows, pc->mb_cols,
+                                                       pc->mode_info_stride);
+                            }
                         }
 #endif
 
@@ -355,9 +371,19 @@
                         xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
                         xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
 
+                        if (xd->mode_info_context->mbmi.ref_frame !=
+                                INTRA_FRAME)
+                        {
+                            /* propagate errors from reference frames */
+                            xd->corrupted |= pc->yv12_fb[ref_fb_idx].corrupted;
+                        }
+
                         vp8_build_uvmvs(xd, pc->full_pixel);
                         decode_macroblock(pbi, xd, mb_row, mb_col);
 
+                        /* check if the boolean decoder has suffered an error */
+                        xd->corrupted |= vp8dx_bool_error(xd->current_bc);
+
                         if (pbi->common.filter_level)
                         {
                             int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
@@ -803,23 +829,28 @@
                 xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
 
 #if CONFIG_ERROR_CONCEALMENT
-                if (pbi->ec_enabled &&
-                    (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
-                    vp8dx_bool_error(xd->current_bc))
                 {
-                    /* We have an intra block with corrupt coefficients, better
-                     * to conceal with an inter block. Interpolate MVs from
-                     * neighboring MBs
-                     *
-                     * Note that for the first mb with corrupt residual in a
-                     * frame, we might not discover that before decoding the
-                     * residual. That happens after this check, and therefore no
-                     * inter concealment will be done.
-                     */
-                    vp8_interpolate_motion(xd,
-                                           mb_row, mb_col,
-                                           pc->mb_rows, pc->mb_cols,
-                                           pc->mode_info_stride);
+                    int corrupt_residual = (!pbi->independent_partitions &&
+                                            pbi->frame_corrupt_residual) ||
+                                            vp8dx_bool_error(xd->current_bc);
+                    if (pbi->ec_active &&
+                        (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
+                        corrupt_residual)
+                    {
+                        /* We have an intra block with corrupt coefficients,
+                         * better to conceal with an inter block. Interpolate
+                         * MVs from neighboring MBs
+                         *
+                         * Note that for the first mb with corrupt residual in a
+                         * frame, we might not discover that before decoding the
+                         * residual. That happens after this check, and
+                         * therefore no inter concealment will be done.
+                         */
+                        vp8_interpolate_motion(xd,
+                                               mb_row, mb_col,
+                                               pc->mb_rows, pc->mb_cols,
+                                               pc->mode_info_stride);
+                    }
                 }
 #endif