]> granicus.if.org Git - libvpx/commitdiff
Fix necessary for input partitions iface to match the RTP profile
authorStefan Holmer <holmer@google.com>
Tue, 6 Sep 2011 12:34:36 +0000 (14:34 +0200)
committerStefan Holmer <holmer@google.com>
Mon, 19 Sep 2011 13:00:21 +0000 (15:00 +0200)
These changes fixes a glitch between the RTP profile and the input
partitions interface. Since there's no way for the user to know the
actual number of partitions, the decoder have to read the
multi_token_paritition bits also when input partitions mode is
enabled.

Included are also a couple of fixes for issues with independent
partitions and uninitialized memory reads.

Change-Id: I6f93b15287d291169ed681898ed3fbcc5dc81837

vp8/decoder/decodframe.c
vp8/decoder/onyxd_if.c
vp8/decoder/threading.c

index 1c11b0b50f23ca102536b597421363c05e6a69c3..4cd370afedbfb49119539ecd16779a41a6bdc765 100644 (file)
@@ -191,7 +191,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
     {
         vp8_reset_mb_tokens_context(xd);
     }
-    else
+    else if (!vp8dx_bool_error(xd->current_bc))
     {
         eobtotal = vp8_decode_mb_tokens(pbi, xd);
     }
@@ -236,7 +236,6 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
     {
         vp8_build_inter_predictors_mb(xd);
     }
-
     /* When we have independent partitions we can apply residual even
      * though other partitions within the frame are corrupt.
      */
@@ -471,9 +470,16 @@ static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
 {
     vp8_reader *bool_decoder = &pbi->bc2;
     int part_idx = 1;
+    int num_token_partitions;
 
     TOKEN_PARTITION multi_token_partition =
             (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+    if (!vp8dx_bool_error(&pbi->bc))
+        pbi->common.multi_token_partition = multi_token_partition;
+    num_token_partitions = 1 << pbi->common.multi_token_partition;
+    if (num_token_partitions + 1 > pbi->num_partitions)
+        vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
+                           "Partitions missing");
     assert(vp8dx_bool_error(&pbi->bc) ||
            multi_token_partition == pbi->common.multi_token_partition);
     if (pbi->num_partitions > 2)
@@ -734,12 +740,14 @@ int vp8_decode_frame(VP8D_COMP *pbi)
         pc->show_frame = (data[0] >> 4) & 1;
         first_partition_length_in_bytes =
             (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
-        data += 3;
 
         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");
+
+        data += 3;
+
         vp8_setup_version(pc);
 
         if (pc->frame_type == KEY_FRAME)
@@ -812,7 +820,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
         }
     }
 
-    if (pc->Width == 0 || pc->Height == 0)
+    if ((!pbi->decoded_key_frame && pc->frame_type != KEY_FRAME) ||
+        pc->Width == 0 || pc->Height == 0)
     {
         return -1;
     }
index db6528c80d58f5044ec0c6fa751e6544acc038c6..357684ab9d365a0dc5e9d42411d7322538b393ae 100644 (file)
@@ -324,16 +324,16 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
         /* Store a pointer to this partition and return. We haven't
          * received the complete frame yet, so we will wait with decoding.
          */
+        assert(pbi->num_partitions < MAX_PARTITIONS);
         pbi->partitions[pbi->num_partitions] = source;
         pbi->partition_sizes[pbi->num_partitions] = size;
         pbi->source_sz += size;
         pbi->num_partitions++;
-        if (pbi->num_partitions > (1<<pbi->common.multi_token_partition) + 1)
-            pbi->common.multi_token_partition++;
-        if (pbi->common.multi_token_partition > EIGHT_PARTITION)
+        if (pbi->num_partitions > (1 << EIGHT_PARTITION) + 1)
         {
             pbi->common.error.error_code = VPX_CODEC_UNSUP_BITSTREAM;
             pbi->common.error.setjmp = 0;
+            pbi->num_partitions = 0;
             return -1;
         }
         return 0;
@@ -345,6 +345,25 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
             pbi->Source = source;
             pbi->source_sz = size;
         }
+        else
+        {
+            assert(pbi->common.multi_token_partition <= EIGHT_PARTITION);
+            if (pbi->num_partitions == 0)
+            {
+                pbi->num_partitions = 1;
+                pbi->partitions[0] = NULL;
+                pbi->partition_sizes[0] = 0;
+            }
+            while (pbi->num_partitions < (1 << pbi->common.multi_token_partition) + 1)
+            {
+                // Reset all missing partitions
+                pbi->partitions[pbi->num_partitions] =
+                    pbi->partitions[pbi->num_partitions - 1] +
+                    pbi->partition_sizes[pbi->num_partitions - 1];
+                pbi->partition_sizes[pbi->num_partitions] = 0;
+                pbi->num_partitions++;
+            }
+        }
 
         if (pbi->source_sz == 0)
         {
@@ -364,8 +383,6 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
                 cm->show_frame = 0;
 
                 pbi->num_partitions = 0;
-                if (pbi->input_partition)
-                    pbi->common.multi_token_partition = 0;
 
                 /* Nothing more to do. */
                 return 0;
@@ -396,8 +413,6 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
             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
@@ -427,6 +442,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
 #endif
         pbi->common.error.error_code = VPX_CODEC_ERROR;
         pbi->common.error.setjmp = 0;
+        pbi->num_partitions = 0;
         if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
           cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
         return retcode;
@@ -447,6 +463,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
 #endif
             pbi->common.error.error_code = VPX_CODEC_ERROR;
             pbi->common.error.setjmp = 0;
+            pbi->num_partitions = 0;
             return -1;
         }
     } else
@@ -464,6 +481,7 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
 #endif
             pbi->common.error.error_code = VPX_CODEC_ERROR;
             pbi->common.error.setjmp = 0;
+            pbi->num_partitions = 0;
             return -1;
         }
 
@@ -508,8 +526,6 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
     pbi->ready_for_new_data = 0;
     pbi->last_time_stamp = time_stamp;
     pbi->num_partitions = 0;
-    if (pbi->input_partition)
-        pbi->common.multi_token_partition = 0;
     pbi->source_sz = 0;
 
 #if 0
index a8bd087ff25d3a200979455e42feba55a090c093..bfc6007cc5a6f6a4996e83c7507afc4946e2088f 100644 (file)
@@ -104,7 +104,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int m
     {
         vp8_reset_mb_tokens_context(xd);
     }
-    else
+    else if (!vp8dx_bool_error(xd->current_bc))
     {
         eobtotal = vp8_decode_mb_tokens(pbi, xd);
     }
@@ -169,7 +169,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int m
 #if CONFIG_ERROR_CONCEALMENT
     if (pbi->ec_active &&
         (mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
-        throw_residual))
+         throw_residual))
     {
         /* MB with corrupt residuals or corrupt mode/motion vectors.
          * Better to use the predictor as reconstruction.