void *current_bc;
+ int corrupted;
+
#if CONFIG_RUNTIME_CPU_DETECT
struct VP8_COMMON_RTCD *rtcd;
#endif
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
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;
+ 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_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_uvoffset += 8;
xd->frame_type = pc->frame_type;
xd->mode_info_context->mbmi.mode = DC_PRED;
xd->mode_info_stride = pc->mode_info_stride;
+ xd->corrupted = 0; /* init without corruption */
}
int vp8_decode_frame(VP8D_COMP *pbi)
int i, j, k, l;
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)
vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
"Truncated packet");
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); */
/* If this was a kf or Gf note the Q used */
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 CONFIG_RUNTIME_CPU_DETECT
if (cm->rtcd.flags & HAS_NEON)
}
#endif
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)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
return -1;
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;
+ 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);
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)
{
/* Save decoded MB last row data for next-row decoding */
}
+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[] =
{
{VP8_SET_REFERENCE, vp8_set_reference},
{VP8_SET_DBG_COLOR_B_MODES, 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_FRAME_CORRUPTED, vp8_get_frame_corrupted},
{ -1, NULL},
};
{
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;
else if (!ctx->iface || !ctx->priv)
res = VPX_CODEC_ERROR;
VP8_DECODER_CTRL_ID_START = 256,
VP8D_GET_LAST_REF_UPDATES, /**< control function to get info on which reference frames were updated
by the last decode */
+ VP8D_GET_FRAME_CORRUPTED, /**< check if the indicated frame is corrupted */
VP8_DECODER_CTRL_ID_MAX
} ;
VPX_CTRL_USE_TYPE(VP8D_GET_LAST_REF_UPDATES, int *)
+VPX_CTRL_USE_TYPE(VP8D_GET_FRAME_CORRUPTED, int *)
/*! @} - end defgroup vp8_decoder */
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->corrupted = 0; /* assume not currupted by errors */
}
else
{
int border;
int frame_size;
YUV_TYPE clrtype;
+
+ int corrupted;
} YV12_BUFFER_CONFIG;
int vp8_yv12_alloc_frame_buffer(YV12_BUFFER_CONFIG *ybf, int width, int height, int border);