Merge remote branch 'origin/master' into experimental
Change-Id: Ie6bc53eb61dc772f308abce9bf93bcc67b38f670
This commit is contained in:
@@ -400,18 +400,18 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
|
|||||||
/* Clip "next_nearest" so that it does not extend to far out of image */
|
/* Clip "next_nearest" so that it does not extend to far out of image */
|
||||||
vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
|
vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
|
||||||
mb_to_top_edge, mb_to_bottom_edge);
|
mb_to_top_edge, mb_to_bottom_edge);
|
||||||
break;
|
goto propagate_mv;
|
||||||
|
|
||||||
case NEARESTMV:
|
case NEARESTMV:
|
||||||
mv->as_int = nearest.as_int;
|
mv->as_int = nearest.as_int;
|
||||||
/* Clip "next_nearest" so that it does not extend to far out of image */
|
/* Clip "next_nearest" so that it does not extend to far out of image */
|
||||||
vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
|
vp8_clamp_mv(mv, mb_to_left_edge, mb_to_right_edge,
|
||||||
mb_to_top_edge, mb_to_bottom_edge);
|
mb_to_top_edge, mb_to_bottom_edge);
|
||||||
break;
|
goto propagate_mv;
|
||||||
|
|
||||||
case ZEROMV:
|
case ZEROMV:
|
||||||
mv->as_int = 0;
|
mv->as_int = 0;
|
||||||
break;
|
goto propagate_mv;
|
||||||
|
|
||||||
case NEWMV:
|
case NEWMV:
|
||||||
read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc);
|
read_mv(bc, &mv->as_mv, (const MV_CONTEXT *) mvc);
|
||||||
@@ -428,8 +428,30 @@ static void read_mb_modes_mv(VP8D_COMP *pbi, MODE_INFO *mi, MB_MODE_INFO *mbmi,
|
|||||||
mb_to_right_edge,
|
mb_to_right_edge,
|
||||||
mb_to_top_edge,
|
mb_to_top_edge,
|
||||||
mb_to_bottom_edge);
|
mb_to_bottom_edge);
|
||||||
break;
|
|
||||||
|
|
||||||
|
propagate_mv: /* same MV throughout */
|
||||||
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
|
if(pbi->ec_enabled)
|
||||||
|
{
|
||||||
|
mi->bmi[ 0].mv.as_int =
|
||||||
|
mi->bmi[ 1].mv.as_int =
|
||||||
|
mi->bmi[ 2].mv.as_int =
|
||||||
|
mi->bmi[ 3].mv.as_int =
|
||||||
|
mi->bmi[ 4].mv.as_int =
|
||||||
|
mi->bmi[ 5].mv.as_int =
|
||||||
|
mi->bmi[ 6].mv.as_int =
|
||||||
|
mi->bmi[ 7].mv.as_int =
|
||||||
|
mi->bmi[ 8].mv.as_int =
|
||||||
|
mi->bmi[ 9].mv.as_int =
|
||||||
|
mi->bmi[10].mv.as_int =
|
||||||
|
mi->bmi[11].mv.as_int =
|
||||||
|
mi->bmi[12].mv.as_int =
|
||||||
|
mi->bmi[13].mv.as_int =
|
||||||
|
mi->bmi[14].mv.as_int =
|
||||||
|
mi->bmi[15].mv.as_int = mv->as_int;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
default:;
|
default:;
|
||||||
#if CONFIG_DEBUG
|
#if CONFIG_DEBUG
|
||||||
assert(0);
|
assert(0);
|
||||||
|
@@ -183,6 +183,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
|
|||||||
unsigned int mb_idx)
|
unsigned int mb_idx)
|
||||||
{
|
{
|
||||||
int eobtotal = 0;
|
int eobtotal = 0;
|
||||||
|
int throw_residual = 0;
|
||||||
MB_PREDICTION_MODE mode;
|
MB_PREDICTION_MODE mode;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@@ -203,7 +204,8 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
|
|||||||
|
|
||||||
mode = xd->mode_info_context->mbmi.mode;
|
mode = xd->mode_info_context->mbmi.mode;
|
||||||
|
|
||||||
if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV)
|
if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV &&
|
||||||
|
!vp8dx_bool_error(xd->current_bc))
|
||||||
{
|
{
|
||||||
/* Special case: Force the loopfilter to skip when eobtotal and
|
/* Special case: Force the loopfilter to skip when eobtotal and
|
||||||
* mb_skip_coeff are zero.
|
* mb_skip_coeff are zero.
|
||||||
@@ -235,14 +237,21 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
|
|||||||
vp8_build_inter_predictors_mb(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.
|
||||||
|
*/
|
||||||
|
throw_residual = (!pbi->independent_partitions &&
|
||||||
|
pbi->frame_corrupt_residual);
|
||||||
|
throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
|
||||||
|
|
||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
if (pbi->ec_enabled &&
|
if (pbi->ec_active &&
|
||||||
(mb_idx >= pbi->mvs_corrupt_from_mb ||
|
(mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
|
||||||
vp8dx_bool_error(xd->current_bc)))
|
|
||||||
{
|
{
|
||||||
/* MB with corrupt residuals or corrupt mode/motion vectors.
|
/* MB with corrupt residuals or corrupt mode/motion vectors.
|
||||||
* Better to use the predictor as reconstruction.
|
* Better to use the predictor as reconstruction.
|
||||||
*/
|
*/
|
||||||
|
pbi->frame_corrupt_residual = 1;
|
||||||
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
|
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
|
||||||
vp8_conceal_corrupt_mb(xd);
|
vp8_conceal_corrupt_mb(xd);
|
||||||
return;
|
return;
|
||||||
@@ -376,22 +385,28 @@ decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
|
|||||||
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
|
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
|
||||||
|
|
||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
if (pbi->ec_enabled &&
|
|
||||||
xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
|
|
||||||
vp8dx_bool_error(xd->current_bc))
|
|
||||||
{
|
{
|
||||||
/* We have an intra block with corrupt coefficients, better to
|
int corrupt_residual = (!pbi->independent_partitions &&
|
||||||
* conceal with an inter block. Interpolate MVs from neighboring MBs
|
pbi->frame_corrupt_residual) ||
|
||||||
*
|
vp8dx_bool_error(xd->current_bc);
|
||||||
* Note that for the first mb with corrupt residual in a frame,
|
if (pbi->ec_active &&
|
||||||
* we might not discover that before decoding the residual. That
|
xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
|
||||||
* happens after this check, and therefore no inter concealment will
|
corrupt_residual)
|
||||||
* be done.
|
{
|
||||||
*/
|
/* We have an intra block with corrupt coefficients, better to
|
||||||
vp8_interpolate_motion(xd,
|
* conceal with an inter block. Interpolate MVs from neighboring
|
||||||
mb_row, mb_col,
|
* MBs.
|
||||||
pc->mb_rows, pc->mb_cols,
|
*
|
||||||
pc->mode_info_stride);
|
* Note that for the first mb with corrupt residual in a frame,
|
||||||
|
* we might not discover that before decoding the residual. That
|
||||||
|
* happens after this check, and therefore no inter concealment
|
||||||
|
* will be done.
|
||||||
|
*/
|
||||||
|
vp8_interpolate_motion(xd,
|
||||||
|
mb_row, mb_col,
|
||||||
|
pc->mb_rows, pc->mb_cols,
|
||||||
|
pc->mode_info_stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -495,6 +510,15 @@ static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int read_is_valid(const unsigned char *start,
|
||||||
|
size_t len,
|
||||||
|
const unsigned char *end)
|
||||||
|
{
|
||||||
|
return (start + len > start && start + len <= end);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setup_token_decoder(VP8D_COMP *pbi,
|
static void setup_token_decoder(VP8D_COMP *pbi,
|
||||||
const unsigned char *cx_data)
|
const unsigned char *cx_data)
|
||||||
{
|
{
|
||||||
@@ -510,7 +534,7 @@ static void setup_token_decoder(VP8D_COMP *pbi,
|
|||||||
(TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
|
(TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
|
||||||
/* Only update the multi_token_partition field if we are sure the value
|
/* Only update the multi_token_partition field if we are sure the value
|
||||||
* is correct. */
|
* is correct. */
|
||||||
if (!pbi->ec_enabled || !vp8dx_bool_error(&pbi->bc))
|
if (!pbi->ec_active || !vp8dx_bool_error(&pbi->bc))
|
||||||
pc->multi_token_partition = multi_token_partition;
|
pc->multi_token_partition = multi_token_partition;
|
||||||
|
|
||||||
num_part = 1 << pc->multi_token_partition;
|
num_part = 1 << pc->multi_token_partition;
|
||||||
@@ -529,25 +553,41 @@ static void setup_token_decoder(VP8D_COMP *pbi,
|
|||||||
for (i = 0; i < num_part; i++)
|
for (i = 0; i < num_part; i++)
|
||||||
{
|
{
|
||||||
const unsigned char *partition_size_ptr = cx_data + i * 3;
|
const unsigned char *partition_size_ptr = cx_data + i * 3;
|
||||||
ptrdiff_t partition_size;
|
ptrdiff_t partition_size, bytes_left;
|
||||||
|
|
||||||
|
bytes_left = user_data_end - partition;
|
||||||
|
|
||||||
/* Calculate the length of this partition. The last partition
|
/* Calculate the length of this partition. The last partition
|
||||||
* size is implicit.
|
* 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)
|
if (i < num_part - 1)
|
||||||
{
|
{
|
||||||
partition_size = read_partition_size(partition_size_ptr);
|
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");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
partition_size = bytes_left;
|
||||||
partition_size = user_data_end - partition;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!pbi->ec_enabled && (partition + partition_size > user_data_end
|
/* Validate the calculated partition length. If the buffer
|
||||||
|| partition + partition_size < partition))
|
* described by the partition can't be fully read, then restrict
|
||||||
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
* it to the portion that can be (for EC mode) or throw an error.
|
||||||
"Truncated packet or corrupt partition "
|
*/
|
||||||
"%d length", i + 1);
|
if (!read_is_valid(partition, partition_size, user_data_end))
|
||||||
|
{
|
||||||
|
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 (vp8dx_start_decode(bool_decoder, partition, partition_size))
|
if (vp8dx_start_decode(bool_decoder, partition, partition_size))
|
||||||
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
|
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
|
||||||
@@ -634,6 +674,9 @@ static void init_frame(VP8D_COMP *pbi)
|
|||||||
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
|
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
|
||||||
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
|
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pbi->decoded_key_frame && pbi->ec_enabled && !pbi->ec_active)
|
||||||
|
pbi->ec_active = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
xd->left_context = &pc->left_context;
|
xd->left_context = &pc->left_context;
|
||||||
@@ -656,6 +699,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
int mb_row;
|
int mb_row;
|
||||||
int i, j, k, l;
|
int i, j, k, l;
|
||||||
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
|
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
|
||||||
|
int corrupt_tokens = 0;
|
||||||
|
int prev_independent_partitions = pbi->independent_partitions;
|
||||||
|
|
||||||
if (pbi->input_partition)
|
if (pbi->input_partition)
|
||||||
{
|
{
|
||||||
@@ -669,7 +714,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
|
|
||||||
if (data_end - data < 3)
|
if (data_end - data < 3)
|
||||||
{
|
{
|
||||||
if (pbi->ec_enabled)
|
if (pbi->ec_active)
|
||||||
{
|
{
|
||||||
/* Declare the missing frame as an inter frame since it will
|
/* Declare the missing frame as an inter frame since it will
|
||||||
be handled as an inter frame when we have estimated its
|
be handled as an inter frame when we have estimated its
|
||||||
@@ -694,7 +739,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
(data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
|
(data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
|
||||||
data += 3;
|
data += 3;
|
||||||
|
|
||||||
if (!pbi->ec_enabled && (data + first_partition_length_in_bytes > data_end
|
if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
|
||||||
|| data + first_partition_length_in_bytes < data))
|
|| data + first_partition_length_in_bytes < data))
|
||||||
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
||||||
"Truncated packet or corrupt partition 0 length");
|
"Truncated packet or corrupt partition 0 length");
|
||||||
@@ -709,7 +754,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
/* When error concealment is enabled we should only check the sync
|
/* When error concealment is enabled we should only check the sync
|
||||||
* code if we have enough bits available
|
* code if we have enough bits available
|
||||||
*/
|
*/
|
||||||
if (!pbi->ec_enabled || data + 3 < data_end)
|
if (!pbi->ec_active || data + 3 < data_end)
|
||||||
{
|
{
|
||||||
if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
|
if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
|
||||||
vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
|
vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
|
||||||
@@ -720,7 +765,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
* if we have enough data. Otherwise we will end up with the wrong
|
* if we have enough data. Otherwise we will end up with the wrong
|
||||||
* size.
|
* size.
|
||||||
*/
|
*/
|
||||||
if (!pbi->ec_enabled || data + 6 < data_end)
|
if (!pbi->ec_active || data + 6 < data_end)
|
||||||
{
|
{
|
||||||
pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
|
pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
|
||||||
pc->horiz_scale = data[4] >> 6;
|
pc->horiz_scale = data[4] >> 6;
|
||||||
@@ -919,7 +964,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
/* Assume we shouldn't refresh golden if the bit is missing */
|
/* Assume we shouldn't refresh golden if the bit is missing */
|
||||||
xd->corrupted |= vp8dx_bool_error(bc);
|
xd->corrupted |= vp8dx_bool_error(bc);
|
||||||
if (pbi->ec_enabled && xd->corrupted)
|
if (pbi->ec_active && xd->corrupted)
|
||||||
pc->refresh_golden_frame = 0;
|
pc->refresh_golden_frame = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -927,7 +972,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
/* Assume we shouldn't refresh altref if the bit is missing */
|
/* Assume we shouldn't refresh altref if the bit is missing */
|
||||||
xd->corrupted |= vp8dx_bool_error(bc);
|
xd->corrupted |= vp8dx_bool_error(bc);
|
||||||
if (pbi->ec_enabled && xd->corrupted)
|
if (pbi->ec_active && xd->corrupted)
|
||||||
pc->refresh_alt_ref_frame = 0;
|
pc->refresh_alt_ref_frame = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -957,7 +1002,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
/* Assume we should refresh the last frame if the bit is missing */
|
/* Assume we should refresh the last frame if the bit is missing */
|
||||||
xd->corrupted |= vp8dx_bool_error(bc);
|
xd->corrupted |= vp8dx_bool_error(bc);
|
||||||
if (pbi->ec_enabled && xd->corrupted)
|
if (pbi->ec_active && xd->corrupted)
|
||||||
pc->refresh_last_frame = 1;
|
pc->refresh_last_frame = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -975,6 +1020,8 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
pbi->independent_partitions = 1;
|
||||||
|
|
||||||
/* read coef probability tree */
|
/* read coef probability tree */
|
||||||
for (i = 0; i < BLOCK_TYPES; i++)
|
for (i = 0; i < BLOCK_TYPES; i++)
|
||||||
for (j = 0; j < COEF_BANDS; j++)
|
for (j = 0; j < COEF_BANDS; j++)
|
||||||
@@ -989,6 +1036,9 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
*p = (vp8_prob)vp8_read_literal(bc, 8);
|
*p = (vp8_prob)vp8_read_literal(bc, 8);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
|
||||||
|
pbi->independent_partitions = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1015,7 +1065,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
vp8_decode_mode_mvs(pbi);
|
vp8_decode_mode_mvs(pbi);
|
||||||
|
|
||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
if (pbi->ec_enabled &&
|
if (pbi->ec_active &&
|
||||||
pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
|
pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
|
||||||
{
|
{
|
||||||
/* Motion vectors are missing in this frame. We will try to estimate
|
/* Motion vectors are missing in this frame. We will try to estimate
|
||||||
@@ -1029,14 +1079,19 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
#if CONFIG_MULTITHREAD
|
#if CONFIG_MULTITHREAD
|
||||||
if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
|
if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
pbi->frame_corrupt_residual = 0;
|
||||||
vp8mt_decode_mb_rows(pbi, xd);
|
vp8mt_decode_mb_rows(pbi, xd);
|
||||||
vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]); /*cm->frame_to_show);*/
|
vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]); /*cm->frame_to_show);*/
|
||||||
|
for (i = 0; i < pbi->decoding_thread_count; ++i)
|
||||||
|
corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
int ibc = 0;
|
int ibc = 0;
|
||||||
int num_part = 1 << pc->multi_token_partition;
|
int num_part = 1 << pc->multi_token_partition;
|
||||||
|
pbi->frame_corrupt_residual = 0;
|
||||||
|
|
||||||
/* Decode the individual macro block */
|
/* Decode the individual macro block */
|
||||||
for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
|
for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
|
||||||
@@ -1053,17 +1108,26 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
|
|
||||||
decode_mb_row(pbi, pc, mb_row, xd);
|
decode_mb_row(pbi, pc, mb_row, xd);
|
||||||
}
|
}
|
||||||
|
corrupt_tokens |= xd->corrupted;
|
||||||
}
|
}
|
||||||
|
|
||||||
stop_token_decoder(pbi);
|
stop_token_decoder(pbi);
|
||||||
|
|
||||||
/* Collect information about decoder corruption. */
|
/* Collect information about decoder corruption. */
|
||||||
/* 1. Check first boolean decoder for errors. */
|
/* 1. Check first boolean decoder for errors. */
|
||||||
pc->yv12_fb[pc->new_fb_idx].corrupted =
|
pc->yv12_fb[pc->new_fb_idx].corrupted = vp8dx_bool_error(bc);
|
||||||
vp8dx_bool_error(bc);
|
|
||||||
/* 2. Check the macroblock information */
|
/* 2. Check the macroblock information */
|
||||||
pc->yv12_fb[pc->new_fb_idx].corrupted |=
|
pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
|
||||||
xd->corrupted;
|
|
||||||
|
if (!pbi->decoded_key_frame)
|
||||||
|
{
|
||||||
|
if (pc->frame_type == KEY_FRAME &&
|
||||||
|
!pc->yv12_fb[pc->new_fb_idx].corrupted)
|
||||||
|
pbi->decoded_key_frame = 1;
|
||||||
|
else
|
||||||
|
vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
|
||||||
|
"A stream must start with a complete key frame");
|
||||||
|
}
|
||||||
|
|
||||||
/* vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes \n",bc->pos+pbi->bc2.pos); */
|
/* vpx_log("Decoder: Frame Decoded, Size Roughly:%d bytes \n",bc->pos+pbi->bc2.pos); */
|
||||||
|
|
||||||
@@ -1077,6 +1141,7 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
if (pc->refresh_entropy_probs == 0)
|
if (pc->refresh_entropy_probs == 0)
|
||||||
{
|
{
|
||||||
vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
|
vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
|
||||||
|
pbi->independent_partitions = prev_independent_partitions;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PACKET_TESTING
|
#ifdef PACKET_TESTING
|
||||||
|
@@ -101,9 +101,21 @@ VP8D_PTR vp8dx_create_decompressor(VP8D_CONFIG *oxcf)
|
|||||||
#else
|
#else
|
||||||
pbi->ec_enabled = 0;
|
pbi->ec_enabled = 0;
|
||||||
#endif
|
#endif
|
||||||
|
/* Error concealment is activated after a key frame has been
|
||||||
|
* decoded without errors when error concealment is enabled.
|
||||||
|
*/
|
||||||
|
pbi->ec_active = 0;
|
||||||
|
|
||||||
|
pbi->decoded_key_frame = 0;
|
||||||
|
|
||||||
pbi->input_partition = oxcf->input_partition;
|
pbi->input_partition = oxcf->input_partition;
|
||||||
|
|
||||||
|
/* Independent partitions is activated when a frame updates the
|
||||||
|
* token probability table to have equal probabilities over the
|
||||||
|
* PREV_COEF context.
|
||||||
|
*/
|
||||||
|
pbi->independent_partitions = 0;
|
||||||
|
|
||||||
return (VP8D_PTR) pbi;
|
return (VP8D_PTR) pbi;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,11 +358,15 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
|
|||||||
/* If error concealment is disabled we won't signal missing frames to
|
/* If error concealment is disabled we won't signal missing frames to
|
||||||
* the decoder.
|
* the decoder.
|
||||||
*/
|
*/
|
||||||
if (!pbi->ec_enabled)
|
if (!pbi->ec_active)
|
||||||
{
|
{
|
||||||
/* Signal that we have no frame to show. */
|
/* Signal that we have no frame to show. */
|
||||||
cm->show_frame = 0;
|
cm->show_frame = 0;
|
||||||
|
|
||||||
|
pbi->num_partitions = 0;
|
||||||
|
if (pbi->input_partition)
|
||||||
|
pbi->common.multi_token_partition = 0;
|
||||||
|
|
||||||
/* Nothing more to do. */
|
/* Nothing more to do. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -379,6 +395,10 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
|
|||||||
#endif
|
#endif
|
||||||
pbi->common.error.setjmp = 0;
|
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
|
/* We do not know if the missing frame(s) was supposed to update
|
||||||
* any of the reference buffers, but we act conservative and
|
* any of the reference buffers, but we act conservative and
|
||||||
* mark only the last buffer as corrupted.
|
* mark only the last buffer as corrupted.
|
||||||
|
@@ -132,7 +132,11 @@ typedef struct VP8Decompressor
|
|||||||
unsigned int mvs_corrupt_from_mb;
|
unsigned int mvs_corrupt_from_mb;
|
||||||
#endif
|
#endif
|
||||||
int ec_enabled;
|
int ec_enabled;
|
||||||
|
int ec_active;
|
||||||
int input_partition;
|
int input_partition;
|
||||||
|
int decoded_key_frame;
|
||||||
|
int independent_partitions;
|
||||||
|
int frame_corrupt_residual;
|
||||||
|
|
||||||
} VP8D_COMP;
|
} VP8D_COMP;
|
||||||
|
|
||||||
|
@@ -93,6 +93,7 @@ static void setup_decoding_thread_data(VP8D_COMP *pbi, MACROBLOCKD *xd, MB_ROW_D
|
|||||||
static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col)
|
static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int mb_col)
|
||||||
{
|
{
|
||||||
int eobtotal = 0;
|
int eobtotal = 0;
|
||||||
|
int throw_residual = 0;
|
||||||
int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
|
int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
|
||||||
|
|
||||||
if (xd->mode_info_context->mbmi.mb_skip_coeff)
|
if (xd->mode_info_context->mbmi.mb_skip_coeff)
|
||||||
@@ -112,7 +113,7 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int m
|
|||||||
|
|
||||||
eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
|
eobtotal |= (xd->mode_info_context->mbmi.mode == B_PRED ||
|
||||||
xd->mode_info_context->mbmi.mode == SPLITMV);
|
xd->mode_info_context->mbmi.mode == SPLITMV);
|
||||||
if (!eobtotal)
|
if (!eobtotal && !vp8dx_bool_error(xd->current_bc))
|
||||||
{
|
{
|
||||||
/* Special case: Force the loopfilter to skip when eobtotal and
|
/* Special case: Force the loopfilter to skip when eobtotal and
|
||||||
* mb_skip_coeff are zero.
|
* mb_skip_coeff are zero.
|
||||||
@@ -154,14 +155,22 @@ static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, int mb_row, int m
|
|||||||
vp8_build_inter_predictors_mb(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.
|
||||||
|
*/
|
||||||
|
throw_residual = (!pbi->independent_partitions &&
|
||||||
|
pbi->frame_corrupt_residual);
|
||||||
|
throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
|
||||||
|
|
||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
if (pbi->ec_enabled &&
|
if (pbi->ec_active &&
|
||||||
(mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
|
(mb_row * pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb ||
|
||||||
vp8dx_bool_error(xd->current_bc)))
|
throw_residual))
|
||||||
{
|
{
|
||||||
/* MB with corrupt residuals or corrupt mode/motion vectors.
|
/* MB with corrupt residuals or corrupt mode/motion vectors.
|
||||||
* Better to use the predictor as reconstruction.
|
* Better to use the predictor as reconstruction.
|
||||||
*/
|
*/
|
||||||
|
pbi->frame_corrupt_residual = 1;
|
||||||
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
|
vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
|
||||||
vp8_conceal_corrupt_mb(xd);
|
vp8_conceal_corrupt_mb(xd);
|
||||||
return;
|
return;
|
||||||
@@ -314,25 +323,32 @@ static THREAD_FUNCTION thread_decoding_proc(void *p_data)
|
|||||||
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
|
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
|
||||||
|
|
||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
if (pbi->ec_enabled &&
|
|
||||||
(xd->mode_info_context->mbmi.ref_frame ==
|
|
||||||
INTRA_FRAME) &&
|
|
||||||
vp8dx_bool_error(xd->current_bc))
|
|
||||||
{
|
{
|
||||||
/* We have an intra block with corrupt coefficients,
|
int corrupt_residual =
|
||||||
* better to conceal with an inter block.
|
(!pbi->independent_partitions &&
|
||||||
* Interpolate MVs from neighboring MBs
|
pbi->frame_corrupt_residual) ||
|
||||||
*
|
vp8dx_bool_error(xd->current_bc);
|
||||||
* Note that for the first mb with corrupt residual
|
if (pbi->ec_active &&
|
||||||
* in a frame, we might not discover that before
|
(xd->mode_info_context->mbmi.ref_frame ==
|
||||||
* decoding the residual. That happens after this
|
INTRA_FRAME) &&
|
||||||
* check, and therefore no inter concealment will be
|
corrupt_residual)
|
||||||
* done.
|
{
|
||||||
*/
|
/* We have an intra block with corrupt
|
||||||
vp8_interpolate_motion(xd,
|
* coefficients, better to conceal with an inter
|
||||||
mb_row, mb_col,
|
* block.
|
||||||
pc->mb_rows, pc->mb_cols,
|
* Interpolate MVs from neighboring MBs
|
||||||
pc->mode_info_stride);
|
*
|
||||||
|
* Note that for the first mb with corrupt
|
||||||
|
* residual in a frame, we might not discover
|
||||||
|
* that before decoding the residual. That
|
||||||
|
* happens after this check, and therefore no
|
||||||
|
* inter concealment will be done.
|
||||||
|
*/
|
||||||
|
vp8_interpolate_motion(xd,
|
||||||
|
mb_row, mb_col,
|
||||||
|
pc->mb_rows, pc->mb_cols,
|
||||||
|
pc->mode_info_stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -355,9 +371,19 @@ static THREAD_FUNCTION thread_decoding_proc(void *p_data)
|
|||||||
xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
|
xd->pre.u_buffer = pc->yv12_fb[ref_fb_idx].u_buffer + recon_uvoffset;
|
||||||
xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
|
xd->pre.v_buffer = pc->yv12_fb[ref_fb_idx].v_buffer + recon_uvoffset;
|
||||||
|
|
||||||
|
if (xd->mode_info_context->mbmi.ref_frame !=
|
||||||
|
INTRA_FRAME)
|
||||||
|
{
|
||||||
|
/* propagate errors from reference frames */
|
||||||
|
xd->corrupted |= pc->yv12_fb[ref_fb_idx].corrupted;
|
||||||
|
}
|
||||||
|
|
||||||
vp8_build_uvmvs(xd, pc->full_pixel);
|
vp8_build_uvmvs(xd, pc->full_pixel);
|
||||||
decode_macroblock(pbi, xd, mb_row, mb_col);
|
decode_macroblock(pbi, xd, mb_row, mb_col);
|
||||||
|
|
||||||
|
/* check if the boolean decoder has suffered an error */
|
||||||
|
xd->corrupted |= vp8dx_bool_error(xd->current_bc);
|
||||||
|
|
||||||
if (pbi->common.filter_level)
|
if (pbi->common.filter_level)
|
||||||
{
|
{
|
||||||
int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
|
int skip_lf = (xd->mode_info_context->mbmi.mode != B_PRED &&
|
||||||
@@ -803,23 +829,28 @@ void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
|
|||||||
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
|
xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
|
||||||
|
|
||||||
#if CONFIG_ERROR_CONCEALMENT
|
#if CONFIG_ERROR_CONCEALMENT
|
||||||
if (pbi->ec_enabled &&
|
|
||||||
(xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
|
|
||||||
vp8dx_bool_error(xd->current_bc))
|
|
||||||
{
|
{
|
||||||
/* We have an intra block with corrupt coefficients, better
|
int corrupt_residual = (!pbi->independent_partitions &&
|
||||||
* to conceal with an inter block. Interpolate MVs from
|
pbi->frame_corrupt_residual) ||
|
||||||
* neighboring MBs
|
vp8dx_bool_error(xd->current_bc);
|
||||||
*
|
if (pbi->ec_active &&
|
||||||
* Note that for the first mb with corrupt residual in a
|
(xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) &&
|
||||||
* frame, we might not discover that before decoding the
|
corrupt_residual)
|
||||||
* residual. That happens after this check, and therefore no
|
{
|
||||||
* inter concealment will be done.
|
/* We have an intra block with corrupt coefficients,
|
||||||
*/
|
* better to conceal with an inter block. Interpolate
|
||||||
vp8_interpolate_motion(xd,
|
* MVs from neighboring MBs
|
||||||
mb_row, mb_col,
|
*
|
||||||
pc->mb_rows, pc->mb_cols,
|
* Note that for the first mb with corrupt residual in a
|
||||||
pc->mode_info_stride);
|
* frame, we might not discover that before decoding the
|
||||||
|
* residual. That happens after this check, and
|
||||||
|
* therefore no inter concealment will be done.
|
||||||
|
*/
|
||||||
|
vp8_interpolate_motion(xd,
|
||||||
|
mb_row, mb_col,
|
||||||
|
pc->mb_rows, pc->mb_cols,
|
||||||
|
pc->mode_info_stride);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user