diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index cbbcd20f5..0f4b47463 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -215,7 +215,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)) { #if CONFIG_T8X8 @@ -292,7 +292,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. */ @@ -641,9 +640,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) @@ -911,12 +917,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) @@ -989,7 +997,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 d901faf11..6c8840304 100644 --- a/vp8/decoder/onyxd_if.c +++ b/vp8/decoder/onyxd_if.c @@ -380,16 +380,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; @@ -401,6 +401,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) { @@ -420,8 +439,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; @@ -452,8 +469,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 @@ -483,6 +498,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; @@ -503,6 +519,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 @@ -520,6 +537,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; } @@ -567,8 +585,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 a1a165fd2..68df61821 100644 --- a/vp8/decoder/threading.c +++ b/vp8/decoder/threading.c @@ -112,7 +112,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); } @@ -177,7 +177,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.