summaryrefslogtreecommitdiff
path: root/vp8/decoder/decodframe.c
diff options
context:
space:
mode:
Diffstat (limited to 'vp8/decoder/decodframe.c')
-rw-r--r--vp8/decoder/decodframe.c239
1 files changed, 118 insertions, 121 deletions
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
index c3263082a..f44c7d31a 100644
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -416,144 +416,153 @@ static unsigned int read_partition_size(const unsigned char *cx_size)
return size;
}
-static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
+static int read_is_valid(const unsigned char *start,
+ size_t len,
+ const unsigned char *end)
{
- vp8_reader *bool_decoder = &pbi->bc2;
- int part_idx = 1;
- int num_token_partitions;
+ return (start + len > start && start + len <= end);
+}
- 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)
+static unsigned int read_available_partition_size(
+ VP8D_COMP *pbi,
+ const unsigned char *token_part_sizes,
+ const unsigned char *fragment_start,
+ const unsigned char *first_fragment_end,
+ const unsigned char *fragment_end,
+ int i,
+ int num_part)
+{
+ VP8_COMMON* pc = &pbi->common;
+ const unsigned char *partition_size_ptr = token_part_sizes + i * 3;
+ unsigned int partition_size;
+ ptrdiff_t bytes_left = fragment_end - fragment_start;
+ /* Calculate the length of this partition. The last partition
+ * 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)
{
- CHECK_MEM_ERROR(pbi->mbc, vpx_malloc((pbi->num_partitions - 1) *
- sizeof(vp8_reader)));
- bool_decoder = pbi->mbc;
+ if (read_is_valid(partition_size_ptr, 3, first_fragment_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;
- for (; part_idx < pbi->num_partitions; ++part_idx)
+ /* 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(fragment_start, partition_size, fragment_end))
{
- if (vp8dx_start_decode(bool_decoder,
- pbi->partitions[part_idx],
- pbi->partition_sizes[part_idx]))
- vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
- "Failed to allocate bool decoder %d",
- part_idx);
-
- bool_decoder++;
+ 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 CONFIG_MULTITHREAD
- /* Clamp number of decoder threads */
- if (pbi->decoding_thread_count > pbi->num_partitions - 1)
- pbi->decoding_thread_count = pbi->num_partitions - 1;
-#endif
-}
-
-
-static int read_is_valid(const unsigned char *start,
- size_t len,
- const unsigned char *end)
-{
- return (start + len > start && start + len <= end);
+ return partition_size;
}
static void setup_token_decoder(VP8D_COMP *pbi,
- const unsigned char *cx_data)
+ const unsigned char* token_part_sizes)
{
- int num_part;
- int i;
- VP8_COMMON *pc = &pbi->common;
- const unsigned char *user_data_end = pbi->Source + pbi->source_sz;
- vp8_reader *bool_decoder;
- const unsigned char *partition;
+ vp8_reader *bool_decoder = &pbi->bc2;
+ int fragment_idx, partition_idx;
+ int num_token_partitions;
+ const unsigned char *first_fragment_end = pbi->fragments[0] +
+ pbi->fragment_sizes[0];
- /* Parse number of token partitions to use */
- const TOKEN_PARTITION multi_token_partition =
+ TOKEN_PARTITION multi_token_partition =
(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_active || !vp8dx_bool_error(&pbi->bc))
- pc->multi_token_partition = multi_token_partition;
-
- num_part = 1 << pc->multi_token_partition;
-
- /* Set up pointers to the first partition */
- partition = cx_data;
- bool_decoder = &pbi->bc2;
-
- if (num_part > 1)
+ 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)
{
- CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_part * sizeof(vp8_reader)));
+ CHECK_MEM_ERROR(pbi->mbc, vpx_malloc(num_token_partitions *
+ sizeof(vp8_reader)));
bool_decoder = pbi->mbc;
- partition += 3 * (num_part - 1);
}
- for (i = 0; i < num_part; i++)
+ /* Check for partitions within the fragments and unpack the fragments
+ * so that each fragment pointer points to its corresponding partition. */
+ for (fragment_idx = 0; fragment_idx < pbi->num_fragments; ++fragment_idx)
{
- const unsigned char *partition_size_ptr = cx_data + i * 3;
- ptrdiff_t partition_size, bytes_left;
-
- bytes_left = user_data_end - partition;
-
- /* Calculate the length of this partition. The last partition
- * 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)
+ unsigned int fragment_size = pbi->fragment_sizes[fragment_idx];
+ const unsigned char *fragment_end = pbi->fragments[fragment_idx] +
+ fragment_size;
+ /* Special case for handling the first partition since we have already
+ * read its size. */
+ if (fragment_idx == 0)
{
- 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");
+ /* Size of first partition + token partition sizes element */
+ ptrdiff_t ext_first_part_size = token_part_sizes -
+ pbi->fragments[0] + 3 * (num_token_partitions - 1);
+ fragment_size -= ext_first_part_size;
+ if (fragment_size > 0)
+ {
+ pbi->fragment_sizes[0] = ext_first_part_size;
+ /* The fragment contains an additional partition. Move to
+ * next. */
+ fragment_idx++;
+ pbi->fragments[fragment_idx] = pbi->fragments[0] +
+ pbi->fragment_sizes[0];
+ }
}
- 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))
+ /* Split the chunk into partitions read from the bitstream */
+ while (fragment_size > 0)
{
- 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);
+ ptrdiff_t partition_size = read_available_partition_size(
+ pbi,
+ token_part_sizes,
+ pbi->fragments[fragment_idx],
+ first_fragment_end,
+ fragment_end,
+ fragment_idx - 1,
+ num_token_partitions);
+ pbi->fragment_sizes[fragment_idx] = partition_size;
+ fragment_size -= partition_size;
+ assert(fragment_idx <= num_token_partitions);
+ if (fragment_size > 0)
+ {
+ /* The fragment contains an additional partition.
+ * Move to next. */
+ fragment_idx++;
+ pbi->fragments[fragment_idx] =
+ pbi->fragments[fragment_idx - 1] + partition_size;
+ }
}
+ }
+
+ pbi->num_fragments = num_token_partitions + 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);
+ for (partition_idx = 1; partition_idx < pbi->num_fragments; ++partition_idx)
+ {
+ if (vp8dx_start_decode(bool_decoder,
+ pbi->fragments[partition_idx],
+ pbi->fragment_sizes[partition_idx]))
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate bool decoder %d",
+ partition_idx);
- /* Advance to the next partition */
- partition += partition_size;
bool_decoder++;
}
#if CONFIG_MULTITHREAD
/* Clamp number of decoder threads */
- if (pbi->decoding_thread_count > num_part - 1)
- pbi->decoding_thread_count = num_part - 1;
+ if (pbi->decoding_thread_count > num_token_partitions - 1)
+ pbi->decoding_thread_count = num_token_partitions - 1;
#endif
}
-
static void stop_token_decoder(VP8D_COMP *pbi)
{
VP8_COMMON *pc = &pbi->common;
@@ -645,8 +654,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
vp8_reader *const bc = & pbi->bc;
VP8_COMMON *const pc = & pbi->common;
MACROBLOCKD *const xd = & pbi->mb;
- const unsigned char *data = (const unsigned char *)pbi->Source;
- const unsigned char *data_end = data + pbi->source_sz;
+ const unsigned char *data = pbi->fragments[0];
+ const unsigned char *data_end = data + pbi->fragment_sizes[0];
ptrdiff_t first_partition_length_in_bytes;
int mb_row;
@@ -655,12 +664,6 @@ int vp8_decode_frame(VP8D_COMP *pbi)
int corrupt_tokens = 0;
int prev_independent_partitions = pbi->independent_partitions;
- if (pbi->input_partition)
- {
- data = pbi->partitions[0];
- data_end = data + pbi->partition_sizes[0];
- }
-
/* start with no corruption of current frame */
xd->corrupted = 0;
pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
@@ -877,14 +880,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
}
}
- if (pbi->input_partition)
- {
- setup_token_decoder_partition_input(pbi);
- }
- else
- {
- setup_token_decoder(pbi, data + first_partition_length_in_bytes);
- }
+ setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+
xd->current_bc = &pbi->bc2;
/* Read the default quantizers. */