summaryrefslogtreecommitdiff
path: root/vp8
diff options
context:
space:
mode:
Diffstat (limited to 'vp8')
-rw-r--r--vp8/common/blockd.h2
-rw-r--r--vp8/decoder/dboolhuff.h25
-rw-r--r--vp8/decoder/decodframe.c21
-rw-r--r--vp8/decoder/onyxd_if.c24
-rw-r--r--vp8/decoder/threading.c9
-rw-r--r--vp8/vp8_dx_iface.c20
6 files changed, 101 insertions, 0 deletions
diff --git a/vp8/common/blockd.h b/vp8/common/blockd.h
index a38f0b72b..5a8991e65 100644
--- a/vp8/common/blockd.h
+++ b/vp8/common/blockd.h
@@ -282,6 +282,8 @@ typedef struct
void *current_bc;
+ int corrupted;
+
#if CONFIG_RUNTIME_CPU_DETECT
struct VP8_COMMON_RTCD *rtcd;
#endif
diff --git a/vp8/decoder/dboolhuff.h b/vp8/decoder/dboolhuff.h
index c851aa7e5..d14f4dceb 100644
--- a/vp8/decoder/dboolhuff.h
+++ b/vp8/decoder/dboolhuff.h
@@ -206,4 +206,29 @@ static int vp8_decode_value(BOOL_DECODER *br, int bits)
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
diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c
index 4702faeed..2ce1b86b9 100644
--- a/vp8/decoder/decodframe.c
+++ b/vp8/decoder/decodframe.c
@@ -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.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);
/*
@@ -391,6 +397,8 @@ void vp8_decode_mb_row(VP8D_COMP *pbi,
*/
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;
@@ -556,6 +564,7 @@ static void init_frame(VP8D_COMP *pbi)
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)
@@ -571,6 +580,10 @@ 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");
@@ -892,6 +905,14 @@ int vp8_decode_frame(VP8D_COMP *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); */
/* If this was a kf or Gf note the Q used */
diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c
index aa2709f5b..d32b8cd65 100644
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -334,6 +334,23 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
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)
@@ -356,6 +373,13 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign
}
#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;
diff --git a/vp8/decoder/threading.c b/vp8/decoder/threading.c
index fea4e1cc1..2e10c1059 100644
--- a/vp8/decoder/threading.c
+++ b/vp8/decoder/threading.c
@@ -893,9 +893,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.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 */
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index cf32d1f38..7d4d7f65b 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -708,6 +708,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[] =
{
{VP8_SET_REFERENCE, vp8_set_reference},
@@ -718,6 +737,7 @@ vpx_codec_ctrl_fn_map_t vp8_ctf_maps[] =
{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},
};