Refactored find_neighboring_blocks() and moved the test for corrupt stream
and intra concealment inside vp8_decode_macroblock to be able tocapture and conceal errors in the residual before reconstruction. Change-Id: Id0f0bd87945a9bb1db0c20bb5467e2ff9aae5d28
This commit is contained in:
@@ -177,9 +177,12 @@ void clamp_mvs(MACROBLOCKD *xd)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, unsigned int mb_idx)
|
void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
|
||||||
{
|
{
|
||||||
int eobtotal = 0;
|
int eobtotal = 0;
|
||||||
|
int corrupt_partition;
|
||||||
|
int mb_row = ((-xd->mb_to_top_edge)/16)>>3;
|
||||||
|
int mb_col = ((-xd->mb_to_left_edge)/16)>>3;
|
||||||
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)
|
||||||
@@ -191,6 +194,24 @@ void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, unsigned int mb_idx)
|
|||||||
eobtotal = vp8_decode_mb_tokens(pbi, xd);
|
eobtotal = vp8_decode_mb_tokens(pbi, xd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check if the boolean decoder has suffered an error */
|
||||||
|
corrupt_partition = vp8dx_bool_error(xd->current_bc);
|
||||||
|
xd->corrupted |= corrupt_partition;
|
||||||
|
|
||||||
|
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
|
||||||
|
corrupt_partition)
|
||||||
|
{
|
||||||
|
/* We have an intra block with corrupt coefficients,
|
||||||
|
* better to conceal with an inter block. Interpolate MVs
|
||||||
|
* from neighboring MBs.
|
||||||
|
*/
|
||||||
|
vp8_interpolate_mv(xd->mode_info_context,
|
||||||
|
mb_row, mb_col,
|
||||||
|
pbi->common.mb_rows, pbi->common.mb_cols,
|
||||||
|
pbi->common.mode_info_stride);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Perform temporary clamping of the MV to be used for prediction */
|
/* Perform temporary clamping of the MV to be used for prediction */
|
||||||
if (do_clamp)
|
if (do_clamp)
|
||||||
{
|
{
|
||||||
@@ -228,7 +249,8 @@ void vp8_decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd, unsigned int mb_idx)
|
|||||||
|
|
||||||
/* TODO(holmer): change when we have MB level error tracking */
|
/* TODO(holmer): change when we have MB level error tracking */
|
||||||
if (pbi->ec_enabled && xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME
|
if (pbi->ec_enabled && xd->mode_info_context->mbmi.ref_frame != INTRA_FRAME
|
||||||
&& (xd->corrupted || mb_idx >= pbi->mvs_corrupt_from_mb))
|
&& (xd->corrupted ||
|
||||||
|
mb_row*pbi->common.mb_cols + mb_col >= pbi->mvs_corrupt_from_mb))
|
||||||
{
|
{
|
||||||
vp8_conceal_corrupt_block(xd);
|
vp8_conceal_corrupt_block(xd);
|
||||||
return;
|
return;
|
||||||
@@ -342,7 +364,6 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
|
|||||||
int dst_fb_idx = pc->new_fb_idx;
|
int dst_fb_idx = pc->new_fb_idx;
|
||||||
int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
|
int recon_y_stride = pc->yv12_fb[ref_fb_idx].y_stride;
|
||||||
int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
|
int recon_uv_stride = pc->yv12_fb[ref_fb_idx].uv_stride;
|
||||||
int corrupt_partition = 0;
|
|
||||||
|
|
||||||
vpx_memset(&pc->left_context, 0, sizeof(pc->left_context));
|
vpx_memset(&pc->left_context, 0, sizeof(pc->left_context));
|
||||||
recon_yoffset = mb_row * recon_y_stride * 16;
|
recon_yoffset = mb_row * recon_y_stride * 16;
|
||||||
@@ -357,19 +378,6 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
|
|||||||
|
|
||||||
for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
|
for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
|
||||||
{
|
{
|
||||||
if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
|
|
||||||
corrupt_partition)
|
|
||||||
{
|
|
||||||
/* We have an intra block with corrupt coefficients,
|
|
||||||
* better to conceal with an inter block. Interpolate MVs
|
|
||||||
* from neighboring MBs.
|
|
||||||
*/
|
|
||||||
vp8_interpolate_mv(xd->mode_info_context,
|
|
||||||
mb_row, mb_col,
|
|
||||||
pc->mb_rows, pc->mb_cols,
|
|
||||||
pc->mode_info_stride);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xd->mode_info_context->mbmi.mode == SPLITMV || xd->mode_info_context->mbmi.mode == B_PRED)
|
if (xd->mode_info_context->mbmi.mode == SPLITMV || xd->mode_info_context->mbmi.mode == B_PRED)
|
||||||
{
|
{
|
||||||
for (i = 0; i < 16; i++)
|
for (i = 0; i < 16; i++)
|
||||||
@@ -417,11 +425,10 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
|
|||||||
else
|
else
|
||||||
pbi->debugoutput =0;
|
pbi->debugoutput =0;
|
||||||
*/
|
*/
|
||||||
vp8_decode_macroblock(pbi, xd, mb_row * pc->mb_cols + mb_col);
|
vp8_decode_macroblock(pbi, xd);
|
||||||
|
|
||||||
/* check if the boolean decoder has suffered an error */
|
/* check if the boolean decoder has suffered an error */
|
||||||
corrupt_partition = vp8dx_bool_error(xd->current_bc);
|
xd->corrupted |= vp8dx_bool_error(xd->current_bc);
|
||||||
xd->corrupted |= corrupt_partition;
|
|
||||||
|
|
||||||
recon_yoffset += 16;
|
recon_yoffset += 16;
|
||||||
recon_uvoffset += 8;
|
recon_uvoffset += 8;
|
||||||
|
@@ -396,103 +396,67 @@ void vp8_estimate_missing_mvs_ex(MB_OVERLAP *overlaps,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void assign_neighbor(EC_BLOCK *neighbor, MODE_INFO *mi, int block_idx)
|
||||||
|
{
|
||||||
|
assert(mi->mbmi.ref_frame < MAX_REF_FRAMES);
|
||||||
|
neighbor->ref_frame = mi->mbmi.ref_frame;
|
||||||
|
neighbor->mv = mi->bmi[block_idx].mv.as_mv;
|
||||||
|
}
|
||||||
|
|
||||||
void vp8_find_neighboring_blocks(MODE_INFO *mi,
|
void vp8_find_neighboring_blocks(MODE_INFO *mi,
|
||||||
EC_BLOCK *neighbors,
|
EC_BLOCK *neighbors,
|
||||||
int mb_row, int mb_col,
|
int mb_row, int mb_col,
|
||||||
int mb_rows, int mb_cols,
|
int mb_rows, int mb_cols,
|
||||||
int mi_stride)
|
int mi_stride)
|
||||||
{
|
{
|
||||||
/* TODO(holmer): Refactor this code */
|
|
||||||
MODE_INFO *neighbor;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int j;
|
int j;
|
||||||
if (mb_row > 0)
|
if (mb_row > 0)
|
||||||
{
|
|
||||||
if (mb_col > 0)
|
|
||||||
{
|
{
|
||||||
/* upper left */
|
/* upper left */
|
||||||
neighbor = mi - mi_stride - 1;
|
if (mb_col > 0)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi - mi_stride - 1, 15);
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i].mv = neighbor->bmi[15].mv.as_mv;
|
|
||||||
}
|
|
||||||
++i;
|
++i;
|
||||||
/* above */
|
/* above */
|
||||||
neighbor = mi - mi_stride;
|
for (j = 12; j < 16; ++j, ++i)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi - mi_stride, j);
|
||||||
for (j = 12; j < 16; ++j)
|
|
||||||
{
|
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i++].mv = neighbor->bmi[j].mv.as_mv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i += 5;
|
i += 5;
|
||||||
if (mb_col < mb_cols - 1)
|
if (mb_col < mb_cols - 1)
|
||||||
{
|
|
||||||
if (mb_row > 0)
|
|
||||||
{
|
{
|
||||||
/* upper right */
|
/* upper right */
|
||||||
neighbor = mi - mi_stride + 1;
|
if (mb_row > 0)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi - mi_stride + 1, 12);
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i].mv = neighbor->bmi[12].mv.as_mv;
|
|
||||||
}
|
|
||||||
++i;
|
++i;
|
||||||
/* right */
|
/* right */
|
||||||
neighbor = mi + 1;
|
for (j = 0; j <= 12; j += 4, ++i)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi + 1, j);
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
for (j = 0; j <= 12; j += 4)
|
|
||||||
{
|
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i++].mv = neighbor->bmi[j].mv.as_mv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i += 5;
|
i += 5;
|
||||||
if (mb_row < mb_rows - 1)
|
if (mb_row < mb_rows - 1)
|
||||||
{
|
|
||||||
if (mb_col < mb_cols - 1)
|
|
||||||
{
|
{
|
||||||
/* lower right */
|
/* lower right */
|
||||||
neighbor = mi + mi_stride + 1;
|
if (mb_col < mb_cols - 1)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi + mi_stride + 1, 0);
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i].mv = neighbor->bmi[0].mv.as_mv;
|
|
||||||
}
|
|
||||||
++i;
|
++i;
|
||||||
/* below */
|
/* below */
|
||||||
neighbor = mi + mi_stride;
|
for (j = 0; j < 4; ++j, ++i)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi + mi_stride, j);
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
for (j = 0; j < 4; ++j)
|
|
||||||
{
|
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i++].mv = neighbor->bmi[j].mv.as_mv;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
i += 5;
|
i += 5;
|
||||||
if (mb_col > 0)
|
if (mb_col > 0)
|
||||||
{
|
|
||||||
if (mb_row < mb_rows - 1)
|
|
||||||
{
|
{
|
||||||
/* lower left */
|
/* lower left */
|
||||||
neighbor = mi + mi_stride - 1;
|
if (mb_row < mb_rows - 1)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
assign_neighbor(&neighbors[i], mi + mi_stride - 1, 4);
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
neighbors[i].mv = neighbor->bmi[4].mv.as_mv;
|
|
||||||
}
|
|
||||||
++i;
|
++i;
|
||||||
/* left */
|
/* left */
|
||||||
neighbor = mi - 1;
|
for (j = 3; j < 16; j += 4, ++i)
|
||||||
assert(neighbor->mbmi.ref_frame < MAX_REF_FRAMES);
|
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
|
||||||
for (j = 3; j < 16; j += 4)
|
|
||||||
{
|
{
|
||||||
neighbors[i].ref_frame = neighbor->mbmi.ref_frame;
|
assign_neighbor(&neighbors[i], mi - 1, j);
|
||||||
neighbors[i++].mv = neighbor->bmi[j].mv.as_mv;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -609,11 +573,6 @@ void vp8_interpolate_mv(MODE_INFO *mi,
|
|||||||
mi->mbmi.mb_skip_coeff = 1;
|
mi->mbmi.mb_skip_coeff = 1;
|
||||||
/* TODO(holmer): should this be enabled, when? */
|
/* TODO(holmer): should this be enabled, when? */
|
||||||
mi->mbmi.need_to_clamp_mvs = 1;
|
mi->mbmi.need_to_clamp_mvs = 1;
|
||||||
|
|
||||||
/* Improved algorithm:
|
|
||||||
* Use the same block type as neighboring blocks
|
|
||||||
* Interpolate from blocks with same type
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void vp8_conceal_corrupt_block(MACROBLOCKD *xd)
|
void vp8_conceal_corrupt_block(MACROBLOCKD *xd)
|
||||||
|
Reference in New Issue
Block a user