shithub: libvpx

Download patch

ref: e529a825f7e23233ec7757abc78b65b40a2c8bf2
parent: 35ce4eb01d2ef02e0ab930bf8327aabd95189a52
author: Stefan Holmer <holmer@google.com>
date: Tue Sep 6 10:34:36 EDT 2011

Fix necessary for input partitions iface to match the RTP profile

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

--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -191,7 +191,7 @@
     {
         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 @@
     {
         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 @@
 {
     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 @@
         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 @@
         }
     }
 
-    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;
     }
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -324,16 +324,16 @@
         /* 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 @@
             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 @@
                 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 @@
             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 @@
 #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 @@
 #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 @@
 #endif
             pbi->common.error.error_code = VPX_CODEC_ERROR;
             pbi->common.error.setjmp = 0;
+            pbi->num_partitions = 0;
             return -1;
         }
 
@@ -508,8 +526,6 @@
     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
--- a/vp8/decoder/threading.c
+++ b/vp8/decoder/threading.c
@@ -104,7 +104,7 @@
     {
         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 @@
 #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.
--