From e529a825f7e23233ec7757abc78b65b40a2c8bf2 Mon Sep 17 00:00:00 2001 From: Stefan Holmer Date: Tue, 6 Sep 2011 14:34:36 +0200 Subject: [PATCH] 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 --- vp8/decoder/decodframe.c | 17 +++++++++++++---- vp8/decoder/onyxd_if.c | 34 +++++++++++++++++++++++++--------- vp8/decoder/threading.c | 4 ++-- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index 1c11b0b50..4cd370afe 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -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; } diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c index db6528c80..357684ab9 100644 --- a/vp8/decoder/onyxd_if.c +++ b/vp8/decoder/onyxd_if.c @@ -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<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 diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c index a8bd087ff..bfc6007cc 100644 --- a/vp8/decoder/threading.c +++ b/vp8/decoder/threading.c @@ -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.