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/encoder/firstpass.c2
-rw-r--r--vp8/vp8_dx_iface.c20
7 files changed, 102 insertions, 1 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 9305a0556..d3972b324 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;
@@ -555,6 +563,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)
@@ -570,6 +579,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");
@@ -891,6 +904,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 adc9f8ec8..adbb1f336 100644
--- a/vp8/decoder/onyxd_if.c
+++ b/vp8/decoder/onyxd_if.c
@@ -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;
+ 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)
@@ -351,6 +368,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 dac990a26..fc8406eae 100644
--- a/vp8/decoder/threading.c
+++ b/vp8/decoder/threading.c
@@ -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.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/encoder/firstpass.c b/vp8/encoder/firstpass.c
index a78048153..1554f3d30 100644
--- a/vp8/encoder/firstpass.c
+++ b/vp8/encoder/firstpass.c
@@ -1487,7 +1487,7 @@ static void define_gf_group(VP8_COMP *cpi, FIRSTPASS_STATS *this_frame)
// Break out conditions.
if ( /* i>4 || */
// Break at cpi->max_gf_interval unless almost totally static
- (i >= cpi->max_gf_interval && (loop_decay_rate < 0.99)) ||
+ (i >= cpi->max_gf_interval && (decay_accumulator < 0.99)) ||
(
// Dont break out with a very short interval
(i > MIN_GF_INTERVAL) &&
diff --git a/vp8/vp8_dx_iface.c b/vp8/vp8_dx_iface.c
index a2ad59662..1b1cf3b94 100644
--- a/vp8/vp8_dx_iface.c
+++ b/vp8/vp8_dx_iface.c
@@ -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[] =
{
{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_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},
};