Merge "Implement error tracking in the decoder"
This commit is contained in:
commit
2f0331c90c
@ -282,6 +282,8 @@ typedef struct
|
|||||||
|
|
||||||
void *current_bc;
|
void *current_bc;
|
||||||
|
|
||||||
|
int corrupted;
|
||||||
|
|
||||||
#if CONFIG_RUNTIME_CPU_DETECT
|
#if CONFIG_RUNTIME_CPU_DETECT
|
||||||
struct VP8_COMMON_RTCD *rtcd;
|
struct VP8_COMMON_RTCD *rtcd;
|
||||||
#endif
|
#endif
|
||||||
|
@ -206,4 +206,29 @@ static int vp8_decode_value(BOOL_DECODER *br, int bits)
|
|||||||
|
|
||||||
return z;
|
return z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vp8dx_bool_error(BOOL_DECODER *br)
|
||||||
|
{
|
||||||
|
/* Check if we have reached the end of the buffer.
|
||||||
|
*
|
||||||
|
* Variable 'count' stores the number of bits in the 'value' buffer,
|
||||||
|
* minus 8. So if count == 8, there are 16 bits available to be read.
|
||||||
|
* Normally, count is filled with 8 and one byte is filled into the
|
||||||
|
* value buffer. When we reach the end of the buffer, count is instead
|
||||||
|
* filled with VP8_LOTS_OF_BITS, 8 of which represent the last 8 real
|
||||||
|
* bits from the bitstream. So the last bit in the bitstream will be
|
||||||
|
* represented by count == VP8_LOTS_OF_BITS - 16.
|
||||||
|
*/
|
||||||
|
if ((br->count > VP8_BD_VALUE_SIZE)
|
||||||
|
&& (br->count <= VP8_LOTS_OF_BITS - 16))
|
||||||
|
{
|
||||||
|
/* We have tried to decode bits after the end of
|
||||||
|
* stream was encountered.
|
||||||
|
*/
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* No error. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -381,6 +381,12 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
|
|||||||
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);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -391,6 +397,8 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
|
|||||||
*/
|
*/
|
||||||
vp8_decode_macroblock(pbi, xd);
|
vp8_decode_macroblock(pbi, xd);
|
||||||
|
|
||||||
|
/* check if the boolean decoder has suffered an error */
|
||||||
|
xd->corrupted |= vp8dx_bool_error(xd->current_bc);
|
||||||
|
|
||||||
recon_yoffset += 16;
|
recon_yoffset += 16;
|
||||||
recon_uvoffset += 8;
|
recon_uvoffset += 8;
|
||||||
@ -555,6 +563,7 @@ static void init_frame(VP8D_COMP *pbi)
|
|||||||
xd->frame_type = pc->frame_type;
|
xd->frame_type = pc->frame_type;
|
||||||
xd->mode_info_context->mbmi.mode = DC_PRED;
|
xd->mode_info_context->mbmi.mode = DC_PRED;
|
||||||
xd->mode_info_stride = pc->mode_info_stride;
|
xd->mode_info_stride = pc->mode_info_stride;
|
||||||
|
xd->corrupted = 0; /* init without corruption */
|
||||||
}
|
}
|
||||||
|
|
||||||
int vp8_decode_frame(VP8D_COMP *pbi)
|
int vp8_decode_frame(VP8D_COMP *pbi)
|
||||||
@ -570,6 +579,10 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
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;
|
||||||
|
|
||||||
|
/* start with no corruption of current frame */
|
||||||
|
xd->corrupted = 0;
|
||||||
|
pc->yv12_fb[pc->new_fb_idx].corrupted = 0;
|
||||||
|
|
||||||
if (data_end - data < 3)
|
if (data_end - data < 3)
|
||||||
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
|
||||||
"Truncated packet");
|
"Truncated packet");
|
||||||
@ -891,6 +904,14 @@ int vp8_decode_frame(VP8D_COMP *pbi)
|
|||||||
|
|
||||||
stop_token_decoder(pbi);
|
stop_token_decoder(pbi);
|
||||||
|
|
||||||
|
/* Collect information about decoder corruption. */
|
||||||
|
/* 1. Check first boolean decoder for errors. */
|
||||||
|
pc->yv12_fb[pc->new_fb_idx].corrupted =
|
||||||
|
vp8dx_bool_error(bc);
|
||||||
|
/* 2. Check the macroblock information */
|
||||||
|
pc->yv12_fb[pc->new_fb_idx].corrupted |=
|
||||||
|
xd->corrupted;
|
||||||
|
|
||||||
/* 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); */
|
||||||
|
|
||||||
/* If this was a kf or Gf note the Q used */
|
/* If this was a kf or Gf note the Q used */
|
||||||
|
@ -329,6 +329,23 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
|
|||||||
|
|
||||||
pbi->common.error.error_code = VPX_CODEC_OK;
|
pbi->common.error.error_code = VPX_CODEC_OK;
|
||||||
|
|
||||||
|
if (size == 0)
|
||||||
|
{
|
||||||
|
/* This is used to signal that we are missing frames.
|
||||||
|
* We do not know if the missing frame(s) was supposed to update
|
||||||
|
* any of the reference buffers, but we act conservative and
|
||||||
|
* mark only the last buffer as corrupted.
|
||||||
|
*/
|
||||||
|
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
||||||
|
|
||||||
|
/* Signal that we have no frame to show. */
|
||||||
|
cm->show_frame = 0;
|
||||||
|
|
||||||
|
/* Nothing more to do. */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if HAVE_ARMV7
|
#if HAVE_ARMV7
|
||||||
#if CONFIG_RUNTIME_CPU_DETECT
|
#if CONFIG_RUNTIME_CPU_DETECT
|
||||||
if (cm->rtcd.flags & HAS_NEON)
|
if (cm->rtcd.flags & HAS_NEON)
|
||||||
@ -351,6 +368,13 @@ 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;
|
||||||
|
|
||||||
|
/* We do not know if the missing frame(s) was supposed to update
|
||||||
|
* any of the reference buffers, but we act conservative and
|
||||||
|
* mark only the last buffer as corrupted.
|
||||||
|
*/
|
||||||
|
cm->yv12_fb[cm->lst_fb_idx].corrupted = 1;
|
||||||
|
|
||||||
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
|
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
|
||||||
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
|
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -890,9 +890,18 @@ void vp8mt_decode_mb_rows( VP8D_COMP *pbi, MACROBLOCKD *xd)
|
|||||||
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);
|
||||||
vp8mt_decode_macroblock(pbi, xd, mb_row, mb_col);
|
vp8mt_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)
|
||||||
{
|
{
|
||||||
/* Save decoded MB last row data for next-row decoding */
|
/* Save decoded MB last row data for next-row decoding */
|
||||||
|
@ -709,6 +709,25 @@ static vpx_codec_err_t vp8_get_last_ref_updates(vpx_codec_alg_priv_t *ctx,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static vpx_codec_err_t vp8_get_frame_corrupted(vpx_codec_alg_priv_t *ctx,
|
||||||
|
int ctrl_id,
|
||||||
|
va_list args)
|
||||||
|
{
|
||||||
|
|
||||||
|
int *corrupted = va_arg(args, int *);
|
||||||
|
|
||||||
|
if (corrupted)
|
||||||
|
{
|
||||||
|
VP8D_COMP *pbi = (VP8D_COMP *)ctx->pbi;
|
||||||
|
*corrupted = pbi->common.frame_to_show->corrupted;
|
||||||
|
|
||||||
|
return VPX_CODEC_OK;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return VPX_CODEC_INVALID_PARAM;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
|
vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
|
||||||
{
|
{
|
||||||
{VP8_SET_REFERENCE, vp8_set_reference},
|
{VP8_SET_REFERENCE, vp8_set_reference},
|
||||||
@ -719,6 +738,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
|
|||||||
{VP8_SET_DBG_COLOR_B_MODES, vp8_set_dbg_options},
|
{VP8_SET_DBG_COLOR_B_MODES, vp8_set_dbg_options},
|
||||||
{VP8_SET_DBG_DISPLAY_MV, vp8_set_dbg_options},
|
{VP8_SET_DBG_DISPLAY_MV, vp8_set_dbg_options},
|
||||||
{VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates},
|
{VP8D_GET_LAST_REF_UPDATES, vp8_get_last_ref_updates},
|
||||||
|
{VP8D_GET_FRAME_CORRUPTED, vp8_get_frame_corrupted},
|
||||||
{ -1, NULL},
|
{ -1, NULL},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -118,7 +118,9 @@ vpx_codec_err_t vpx_codec_decode(vpx_codec_ctx_t *ctx,
|
|||||||
{
|
{
|
||||||
vpx_codec_err_t res;
|
vpx_codec_err_t res;
|
||||||
|
|
||||||
if (!ctx || !data || !data_sz)
|
/* Sanity checks */
|
||||||
|
/* NULL data ptr allowed if data_sz is 0 too */
|
||||||
|
if (!ctx || (!data && data_sz))
|
||||||
res = VPX_CODEC_INVALID_PARAM;
|
res = VPX_CODEC_INVALID_PARAM;
|
||||||
else if (!ctx->iface || !ctx->priv)
|
else if (!ctx->iface || !ctx->priv)
|
||||||
res = VPX_CODEC_ERROR;
|
res = VPX_CODEC_ERROR;
|
||||||
|
@ -45,6 +45,7 @@ enum vp8d_dec_control_id
|
|||||||
VP8_DECODER_CTRL_ID_START = 256,
|
VP8_DECODER_CTRL_ID_START = 256,
|
||||||
VP8D_GET_LAST_REF_UPDATES, /**< control function to get info on which reference frames were updated
|
VP8D_GET_LAST_REF_UPDATES, /**< control function to get info on which reference frames were updated
|
||||||
by the last decode */
|
by the last decode */
|
||||||
|
VP8D_GET_FRAME_CORRUPTED, /**< check if the indicated frame is corrupted */
|
||||||
VP8_DECODER_CTRL_ID_MAX
|
VP8_DECODER_CTRL_ID_MAX
|
||||||
} ;
|
} ;
|
||||||
|
|
||||||
@ -58,6 +59,7 @@ enum vp8d_dec_control_id
|
|||||||
|
|
||||||
|
|
||||||
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *)
|
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *)
|
||||||
|
VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *)
|
||||||
|
|
||||||
|
|
||||||
/*! @} - end defgroup vp8_decoder */
|
/*! @} - end defgroup vp8_decoder */
|
||||||
|
@ -81,6 +81,8 @@ vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int
|
|||||||
|
|
||||||
ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2 * ybf->uv_stride) + border / 2;
|
ybf->u_buffer = ybf->buffer_alloc + yplane_size + (border / 2 * ybf->uv_stride) + border / 2;
|
||||||
ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2 * ybf->uv_stride) + border / 2;
|
ybf->v_buffer = ybf->buffer_alloc + yplane_size + uvplane_size + (border / 2 * ybf->uv_stride) + border / 2;
|
||||||
|
|
||||||
|
ybf->corrupted = 0; /* assume not currupted by errors */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -57,6 +57,8 @@ extern "C"
|
|||||||
int border;
|
int border;
|
||||||
int frame_size;
|
int frame_size;
|
||||||
YUV_TYPE clrtype;
|
YUV_TYPE clrtype;
|
||||||
|
|
||||||
|
int corrupted;
|
||||||
} YV12_BUFFER_CONFIG;
|
} YV12_BUFFER_CONFIG;
|
||||||
|
|
||||||
int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border);
|
int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user