Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(15)

Unified Diff: source/libvpx/vp8/decoder/decodframe.c

Issue 7671004: Update libvpx snapshot to v0.9.7-p1 (Cayuga). (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/libvpx/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « source/libvpx/vp8/decoder/decodemv.c ('k') | source/libvpx/vp8/decoder/detokenize.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: source/libvpx/vp8/decoder/decodframe.c
===================================================================
--- source/libvpx/vp8/decoder/decodframe.c (revision 96967)
+++ source/libvpx/vp8/decoder/decodframe.c (working copy)
@@ -27,6 +27,9 @@
#include "decodemv.h"
#include "vp8/common/extend.h"
+#if CONFIG_ERROR_CONCEALMENT
+#include "error_concealment.h"
+#endif
#include "vpx_mem/vpx_mem.h"
#include "vp8/common/idct.h"
#include "dequantize.h"
@@ -111,16 +114,17 @@
*/
static void skip_recon_mb(VP8D_COMP *pbi, MACROBLOCKD *xd)
{
- if (xd->frame_type == KEY_FRAME || xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+ if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
{
-
- vp8_build_intra_predictors_mbuv_s(xd);
+ RECON_INVOKE(&pbi->common.rtcd.recon, build_intra_predictors_mbuv_s)(xd);
RECON_INVOKE(&pbi->common.rtcd.recon,
build_intra_predictors_mby_s)(xd);
}
else
{
- vp8_build_inter_predictors_mb_s(xd);
+ vp8_build_inter16x16_predictors_mb(xd, xd->dst.y_buffer,
+ xd->dst.u_buffer, xd->dst.v_buffer,
+ xd->dst.y_stride, xd->dst.uv_stride);
}
}
@@ -175,10 +179,13 @@
}
-static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd)
+static void decode_macroblock(VP8D_COMP *pbi, MACROBLOCKD *xd,
+ unsigned int mb_idx)
{
int eobtotal = 0;
- int i, do_clamp = xd->mode_info_context->mbmi.need_to_clamp_mvs;
+ int throw_residual = 0;
+ MB_PREDICTION_MODE mode;
+ int i;
if (xd->mode_info_context->mbmi.mb_skip_coeff)
{
@@ -190,16 +197,21 @@
}
/* Perform temporary clamping of the MV to be used for prediction */
- if (do_clamp)
+ if (xd->mode_info_context->mbmi.need_to_clamp_mvs)
{
clamp_mvs(xd);
}
- xd->mode_info_context->mbmi.dc_diff = 1;
+ mode = xd->mode_info_context->mbmi.mode;
- if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV && eobtotal == 0)
+ if (eobtotal == 0 && mode != B_PRED && mode != SPLITMV &&
+ !vp8dx_bool_error(xd->current_bc))
{
- xd->mode_info_context->mbmi.dc_diff = 0;
+ /* Special case: Force the loopfilter to skip when eobtotal and
+ * mb_skip_coeff are zero.
+ * */
+ xd->mode_info_context->mbmi.mb_skip_coeff = 1;
+
skip_recon_mb(pbi, xd);
return;
}
@@ -208,11 +220,11 @@
mb_init_dequantizer(pbi, xd);
/* do prediction */
- if (xd->frame_type == KEY_FRAME || xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
+ if (xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME)
{
- vp8_build_intra_predictors_mbuv(xd);
+ RECON_INVOKE(&pbi->common.rtcd.recon, build_intra_predictors_mbuv)(xd);
- if (xd->mode_info_context->mbmi.mode != B_PRED)
+ if (mode != B_PRED)
{
RECON_INVOKE(&pbi->common.rtcd.recon,
build_intra_predictors_mby)(xd);
@@ -225,10 +237,63 @@
vp8_build_inter_predictors_mb(xd);
}
+ /* When we have independent partitions we can apply residual even
+ * though other partitions within the frame are corrupt.
+ */
+ throw_residual = (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual);
+ throw_residual = (throw_residual || vp8dx_bool_error(xd->current_bc));
+
+#if CONFIG_ERROR_CONCEALMENT
+ if (pbi->ec_active &&
+ (mb_idx >= pbi->mvs_corrupt_from_mb || throw_residual))
+ {
+ /* MB with corrupt residuals or corrupt mode/motion vectors.
+ * Better to use the predictor as reconstruction.
+ */
+ pbi->frame_corrupt_residual = 1;
+ vpx_memset(xd->qcoeff, 0, sizeof(xd->qcoeff));
+ vp8_conceal_corrupt_mb(xd);
+ return;
+ }
+#endif
+
/* dequantization and idct */
- if (xd->mode_info_context->mbmi.mode != B_PRED && xd->mode_info_context->mbmi.mode != SPLITMV)
+ if (mode == B_PRED)
{
+ for (i = 0; i < 16; i++)
+ {
+ BLOCKD *b = &xd->block[i];
+ RECON_INVOKE(RTCD_VTABLE(recon), intra4x4_predict)
+ (b, b->bmi.as_mode, b->predictor);
+
+ if (xd->eobs[i] > 1)
+ {
+ DEQUANT_INVOKE(&pbi->dequant, idct_add)
+ (b->qcoeff, b->dequant, b->predictor,
+ *(b->base_dst) + b->dst, 16, b->dst_stride);
+ }
+ else
+ {
+ IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar_add)
+ (b->qcoeff[0] * b->dequant[0], b->predictor,
+ *(b->base_dst) + b->dst, 16, b->dst_stride);
+ ((int *)b->qcoeff)[0] = 0;
+ }
+ }
+
+ }
+ else if (mode == SPLITMV)
+ {
+ DEQUANT_INVOKE (&pbi->dequant, idct_add_y_block)
+ (xd->qcoeff, xd->block[0].dequant,
+ xd->predictor, xd->dst.y_buffer,
+ xd->dst.y_stride, xd->eobs);
+ }
+ else
+ {
BLOCKD *b = &xd->block[24];
+
DEQUANT_INVOKE(&pbi->dequant, block)(b);
/* do 2nd order transform on the dc block */
@@ -255,38 +320,7 @@
xd->predictor, xd->dst.y_buffer,
xd->dst.y_stride, xd->eobs, xd->block[24].diff);
}
- else if ((xd->frame_type == KEY_FRAME || xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME) && xd->mode_info_context->mbmi.mode == B_PRED)
- {
- for (i = 0; i < 16; i++)
- {
- BLOCKD *b = &xd->block[i];
- vp8_predict_intra4x4(b, b->bmi.mode, b->predictor);
-
- if (xd->eobs[i] > 1)
- {
- DEQUANT_INVOKE(&pbi->dequant, idct_add)
- (b->qcoeff, b->dequant, b->predictor,
- *(b->base_dst) + b->dst, 16, b->dst_stride);
- }
- else
- {
- IDCT_INVOKE(RTCD_VTABLE(idct), idct1_scalar_add)
- (b->qcoeff[0] * b->dequant[0], b->predictor,
- *(b->base_dst) + b->dst, 16, b->dst_stride);
- ((int *)b->qcoeff)[0] = 0;
- }
- }
-
- }
- else
- {
- DEQUANT_INVOKE (&pbi->dequant, idct_add_y_block)
- (xd->qcoeff, xd->block[0].dequant,
- xd->predictor, xd->dst.y_buffer,
- xd->dst.y_stride, xd->eobs);
- }
-
DEQUANT_INVOKE (&pbi->dequant, idct_add_uv_block)
(xd->qcoeff+16*16, xd->block[16].dequant,
xd->predictor+16*16, xd->dst.u_buffer, xd->dst.v_buffer,
@@ -323,8 +357,6 @@
static void
decode_mb_row(VP8D_COMP *pbi, VP8_COMMON *pc, int mb_row, MACROBLOCKD *xd)
{
-
- int i;
int recon_yoffset, recon_uvoffset;
int mb_col;
int ref_fb_idx = pc->lst_fb_idx;
@@ -345,21 +377,40 @@
for (mb_col = 0; mb_col < pc->mb_cols; mb_col++)
{
+ /* Distance of Mb to the various image edges.
+ * These are specified to 8th pel as they are always compared to values
+ * that are in 1/8th pel units
+ */
+ xd->mb_to_left_edge = -((mb_col * 16) << 3);
+ xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
- if (xd->mode_info_context->mbmi.mode == SPLITMV || xd->mode_info_context->mbmi.mode == B_PRED)
+#if CONFIG_ERROR_CONCEALMENT
{
- for (i = 0; i < 16; i++)
+ int corrupt_residual = (!pbi->independent_partitions &&
+ pbi->frame_corrupt_residual) ||
+ vp8dx_bool_error(xd->current_bc);
+ if (pbi->ec_active &&
+ xd->mode_info_context->mbmi.ref_frame == INTRA_FRAME &&
+ corrupt_residual)
{
- BLOCKD *d = &xd->block[i];
- vpx_memcpy(&d->bmi, &xd->mode_info_context->bmi[i], sizeof(B_MODE_INFO));
+ /* We have an intra block with corrupt coefficients, better to
+ * conceal with an inter block. Interpolate MVs from neighboring
+ * MBs.
+ *
+ * Note that for the first mb with corrupt residual in a frame,
+ * we might not discover that before decoding the residual. That
+ * happens after this check, and therefore no inter concealment
+ * will be done.
+ */
+ vp8_interpolate_motion(xd,
+ mb_row, mb_col,
+ pc->mb_rows, pc->mb_cols,
+ pc->mode_info_stride);
}
}
+#endif
- /* Distance of Mb to the various image edges.
- * These are specified to 8th pel as they are always compared to values that are in 1/8th pel units
- */
- xd->mb_to_left_edge = -((mb_col * 16) << 3);
- xd->mb_to_right_edge = ((pc->mb_cols - 1 - mb_col) * 16) << 3;
+ update_blockd_bmi(xd);
xd->dst.y_buffer = pc->yv12_fb[dst_fb_idx].y_buffer + recon_yoffset;
xd->dst.u_buffer = pc->yv12_fb[dst_fb_idx].u_buffer + recon_uvoffset;
@@ -393,7 +444,7 @@
else
pbi->debugoutput =0;
*/
- decode_macroblock(pbi, xd);
+ decode_macroblock(pbi, xd, mb_row * pc->mb_cols + mb_col);
/* check if the boolean decoder has suffered an error */
xd->corrupted |= vp8dx_bool_error(xd->current_bc);
@@ -424,7 +475,50 @@
return size;
}
+static void setup_token_decoder_partition_input(VP8D_COMP *pbi)
+{
+ vp8_reader *bool_decoder = &pbi->bc2;
+ int part_idx = 1;
+ TOKEN_PARTITION multi_token_partition =
+ (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+ assert(vp8dx_bool_error(&pbi->bc) ||
+ multi_token_partition == pbi->common.multi_token_partition);
+ if (pbi->num_partitions > 2)
+ {
+ CHECK_MEM_ERROR(pbi->mbc, vpx_malloc((pbi->num_partitions - 1) *
+ sizeof(vp8_reader)));
+ bool_decoder = pbi->mbc;
+ }
+
+ for (; part_idx < pbi->num_partitions; ++part_idx)
+ {
+ if (vp8dx_start_decode(bool_decoder,
+ pbi->partitions[part_idx],
+ pbi->partition_sizes[part_idx]))
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate bool decoder %d",
+ part_idx);
+
+ bool_decoder++;
+ }
+
+#if CONFIG_MULTITHREAD
+ /* Clamp number of decoder threads */
+ if (pbi->decoding_thread_count > pbi->num_partitions - 1)
+ pbi->decoding_thread_count = pbi->num_partitions - 1;
+#endif
+}
+
+
+static int read_is_valid(const unsigned char *start,
+ size_t len,
+ const unsigned char *end)
+{
+ return (start + len > start && start + len <= end);
+}
+
+
static void setup_token_decoder(VP8D_COMP *pbi,
const unsigned char *cx_data)
{
@@ -436,7 +530,13 @@
const unsigned char *partition;
/* Parse number of token partitions to use */
- pc->multi_token_partition = (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+ const TOKEN_PARTITION multi_token_partition =
+ (TOKEN_PARTITION)vp8_read_literal(&pbi->bc, 2);
+ /* Only update the multi_token_partition field if we are sure the value
+ * is correct. */
+ if (!pbi->ec_active || !vp8dx_bool_error(&pbi->bc))
+ pc->multi_token_partition = multi_token_partition;
+
num_part = 1 << pc->multi_token_partition;
/* Set up pointers to the first partition */
@@ -453,26 +553,42 @@
for (i = 0; i < num_part; i++)
{
const unsigned char *partition_size_ptr = cx_data + i * 3;
- ptrdiff_t partition_size;
+ ptrdiff_t partition_size, bytes_left;
+ bytes_left = user_data_end - partition;
+
/* Calculate the length of this partition. The last partition
- * size is implicit.
+ * size is implicit. If the partition size can't be read, then
+ * either use the remaining data in the buffer (for EC mode)
+ * or throw an error.
*/
if (i < num_part - 1)
{
- partition_size = read_partition_size(partition_size_ptr);
+ if (read_is_valid(partition_size_ptr, 3, user_data_end))
+ partition_size = read_partition_size(partition_size_ptr);
+ else if (pbi->ec_active)
+ partition_size = bytes_left;
+ else
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated partition size data");
}
else
+ partition_size = bytes_left;
+
+ /* Validate the calculated partition length. If the buffer
+ * described by the partition can't be fully read, then restrict
+ * it to the portion that can be (for EC mode) or throw an error.
+ */
+ if (!read_is_valid(partition, partition_size, user_data_end))
{
- partition_size = user_data_end - partition;
+ if (pbi->ec_active)
+ partition_size = bytes_left;
+ else
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet or corrupt partition "
+ "%d length", i + 1);
}
- if (partition + partition_size > user_data_end
- || partition + partition_size < partition)
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated packet or corrupt partition "
- "%d length", i + 1);
-
if (vp8dx_start_decode(bool_decoder, partition, partition_size))
vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate bool decoder %d", i + 1);
@@ -495,7 +611,10 @@
VP8_COMMON *pc = &pbi->common;
if (pc->multi_token_partition != ONE_PARTITION)
+ {
vpx_free(pbi->mbc);
+ pbi->mbc = NULL;
+ }
}
static void init_frame(VP8D_COMP *pbi)
@@ -555,6 +674,9 @@
xd->subpixel_predict8x8 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear8x8);
xd->subpixel_predict16x16 = SUBPIX_INVOKE(RTCD_VTABLE(subpix), bilinear16x16);
}
+
+ if (pbi->decoded_key_frame && pbi->ec_enabled && !pbi->ec_active)
+ pbi->ec_active = 1;
}
xd->left_context = &pc->left_context;
@@ -571,75 +693,125 @@
VP8_COMMON *const pc = & pbi->common;
MACROBLOCKD *const xd = & pbi->mb;
const unsigned char *data = (const unsigned char *)pbi->Source;
- const unsigned char *const data_end = data + pbi->source_sz;
+ const unsigned char *data_end = data + pbi->source_sz;
ptrdiff_t first_partition_length_in_bytes;
int mb_row;
int i, j, k, l;
const int *const mb_feature_data_bits = vp8_mb_feature_data_bits;
+ int corrupt_tokens = 0;
+ int prev_independent_partitions = pbi->independent_partitions;
+ if (pbi->input_partition)
+ {
+ data = pbi->partitions[0];
+ data_end = data + pbi->partition_sizes[0];
+ }
+
/* 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");
- pc->frame_type = (FRAME_TYPE)(data[0] & 1);
- pc->version = (data[0] >> 1) & 7;
- pc->show_frame = (data[0] >> 4) & 1;
- first_partition_length_in_bytes =
- (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
- data += 3;
-
- if (data + first_partition_length_in_bytes > data_end
- || data + first_partition_length_in_bytes < data)
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Truncated packet or corrupt partition 0 length");
- vp8_setup_version(pc);
-
- if (pc->frame_type == KEY_FRAME)
{
- const int Width = pc->Width;
- const int Height = pc->Height;
+ if (pbi->ec_active)
+ {
+ /* Declare the missing frame as an inter frame since it will
+ be handled as an inter frame when we have estimated its
+ motion vectors. */
+ pc->frame_type = INTER_FRAME;
+ pc->version = 0;
+ pc->show_frame = 1;
+ first_partition_length_in_bytes = 0;
+ }
+ else
+ {
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet");
+ }
+ }
+ else
+ {
+ pc->frame_type = (FRAME_TYPE)(data[0] & 1);
+ pc->version = (data[0] >> 1) & 7;
+ pc->show_frame = (data[0] >> 4) & 1;
+ first_partition_length_in_bytes =
+ (data[0] | (data[1] << 8) | (data[2] << 16)) >> 5;
+ data += 3;
- /* vet via sync code */
- if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
- vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
- "Invalid frame sync code");
+ if (!pbi->ec_active && (data + first_partition_length_in_bytes > data_end
+ || data + first_partition_length_in_bytes < data))
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Truncated packet or corrupt partition 0 length");
+ vp8_setup_version(pc);
- pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
- pc->horiz_scale = data[4] >> 6;
- pc->Height = (data[5] | (data[6] << 8)) & 0x3fff;
- pc->vert_scale = data[6] >> 6;
- data += 7;
-
- if (Width != pc->Width || Height != pc->Height)
+ if (pc->frame_type == KEY_FRAME)
{
- int prev_mb_rows = pc->mb_rows;
+ const int Width = pc->Width;
+ const int Height = pc->Height;
- if (pc->Width <= 0)
+ /* vet via sync code */
+ /* When error concealment is enabled we should only check the sync
+ * code if we have enough bits available
+ */
+ if (!pbi->ec_active || data + 3 < data_end)
{
- pc->Width = Width;
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Invalid frame width");
+ if (data[0] != 0x9d || data[1] != 0x01 || data[2] != 0x2a)
+ vpx_internal_error(&pc->error, VPX_CODEC_UNSUP_BITSTREAM,
+ "Invalid frame sync code");
}
- if (pc->Height <= 0)
+ /* If error concealment is enabled we should only parse the new size
+ * if we have enough data. Otherwise we will end up with the wrong
+ * size.
+ */
+ if (!pbi->ec_active || data + 6 < data_end)
{
- pc->Height = Height;
- vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
- "Invalid frame height");
+ pc->Width = (data[3] | (data[4] << 8)) & 0x3fff;
+ pc->horiz_scale = data[4] >> 6;
+ pc->Height = (data[5] | (data[6] << 8)) & 0x3fff;
+ pc->vert_scale = data[6] >> 6;
}
+ data += 7;
- if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
- vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
- "Failed to allocate frame buffers");
+ if (Width != pc->Width || Height != pc->Height)
+ {
+ int prev_mb_rows = pc->mb_rows;
+ if (pc->Width <= 0)
+ {
+ pc->Width = Width;
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Invalid frame width");
+ }
+
+ if (pc->Height <= 0)
+ {
+ pc->Height = Height;
+ vpx_internal_error(&pc->error, VPX_CODEC_CORRUPT_FRAME,
+ "Invalid frame height");
+ }
+
+ if (vp8_alloc_frame_buffers(pc, pc->Width, pc->Height))
+ vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate frame buffers");
+
+#if CONFIG_ERROR_CONCEALMENT
+ pbi->overlaps = NULL;
+ if (pbi->ec_enabled)
+ {
+ if (vp8_alloc_overlap_lists(pbi))
+ vpx_internal_error(&pc->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate overlap lists "
+ "for error concealment");
+ }
+#endif
+
#if CONFIG_MULTITHREAD
- if (pbi->b_multithreaded_rd)
- vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows);
+ if (pbi->b_multithreaded_rd)
+ vp8mt_alloc_temp_buffers(pbi, pc->Width, prev_mb_rows);
#endif
+ }
}
}
@@ -751,7 +923,14 @@
}
}
- setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+ if (pbi->input_partition)
+ {
+ setup_token_decoder_partition_input(pbi);
+ }
+ else
+ {
+ setup_token_decoder(pbi, data + first_partition_length_in_bytes);
+ }
xd->current_bc = &pbi->bc2;
/* Read the default quantizers. */
@@ -782,7 +961,20 @@
{
/* Should the GF or ARF be updated from the current frame */
pc->refresh_golden_frame = vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+ /* Assume we shouldn't refresh golden if the bit is missing */
+ xd->corrupted |= vp8dx_bool_error(bc);
+ if (pbi->ec_active && xd->corrupted)
+ pc->refresh_golden_frame = 0;
+#endif
+
pc->refresh_alt_ref_frame = vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+ /* Assume we shouldn't refresh altref if the bit is missing */
+ xd->corrupted |= vp8dx_bool_error(bc);
+ if (pbi->ec_active && xd->corrupted)
+ pc->refresh_alt_ref_frame = 0;
+#endif
/* Buffer to buffer copy flags. */
pc->copy_buffer_to_gf = 0;
@@ -807,6 +999,13 @@
pc->refresh_last_frame = pc->frame_type == KEY_FRAME || vp8_read_bit(bc);
+#if CONFIG_ERROR_CONCEALMENT
+ /* Assume we should refresh the last frame if the bit is missing */
+ xd->corrupted |= vp8dx_bool_error(bc);
+ if (pbi->ec_active && xd->corrupted)
+ pc->refresh_last_frame = 1;
+#endif
+
if (0)
{
FILE *z = fopen("decodestats.stt", "a");
@@ -820,14 +1019,14 @@
fclose(z);
}
+ {
+ pbi->independent_partitions = 1;
- {
/* read coef probability tree */
-
for (i = 0; i < BLOCK_TYPES; i++)
for (j = 0; j < COEF_BANDS; j++)
for (k = 0; k < PREV_COEF_CONTEXTS; k++)
- for (l = 0; l < MAX_ENTROPY_TOKENS - 1; l++)
+ for (l = 0; l < ENTROPY_NODES; l++)
{
vp8_prob *const p = pc->fc.coef_probs [i][j][k] + l;
@@ -837,6 +1036,9 @@
*p = (vp8_prob)vp8_read_literal(bc, 8);
}
+ if (k > 0 && *p != pc->fc.coef_probs[i][j][k-1][l])
+ pbi->independent_partitions = 0;
+
}
}
@@ -862,29 +1064,34 @@
vp8_decode_mode_mvs(pbi);
+#if CONFIG_ERROR_CONCEALMENT
+ if (pbi->ec_active &&
+ pbi->mvs_corrupt_from_mb < (unsigned int)pc->mb_cols * pc->mb_rows)
+ {
+ /* Motion vectors are missing in this frame. We will try to estimate
+ * them and then continue decoding the frame as usual */
+ vp8_estimate_missing_mvs(pbi);
+ }
+#endif
+
vpx_memset(pc->above_context, 0, sizeof(ENTROPY_CONTEXT_PLANES) * pc->mb_cols);
- vpx_memcpy(&xd->block[0].bmi, &xd->mode_info_context->bmi[0], sizeof(B_MODE_INFO));
-
#if CONFIG_MULTITHREAD
if (pbi->b_multithreaded_rd && pc->multi_token_partition != ONE_PARTITION)
{
+ int i;
+ pbi->frame_corrupt_residual = 0;
vp8mt_decode_mb_rows(pbi, xd);
- if(pbi->common.filter_level)
- {
- /*vp8_mt_loop_filter_frame(pbi);*/ /*cm, &pbi->mb, cm->filter_level);*/
-
- pc->last_frame_type = pc->frame_type;
- pc->last_filter_type = pc->filter_type;
- pc->last_sharpness_level = pc->sharpness_level;
- }
vp8_yv12_extend_frame_borders_ptr(&pc->yv12_fb[pc->new_fb_idx]); /*cm->frame_to_show);*/
+ for (i = 0; i < pbi->decoding_thread_count; ++i)
+ corrupt_tokens |= pbi->mb_row_di[i].mbd.corrupted;
}
else
#endif
{
int ibc = 0;
int num_part = 1 << pc->multi_token_partition;
+ pbi->frame_corrupt_residual = 0;
/* Decode the individual macro block */
for (mb_row = 0; mb_row < pc->mb_rows; mb_row++)
@@ -901,19 +1108,27 @@
decode_mb_row(pbi, pc, mb_row, xd);
}
+ corrupt_tokens |= xd->corrupted;
}
-
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);
+ 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;
+ pc->yv12_fb[pc->new_fb_idx].corrupted |= corrupt_tokens;
+ if (!pbi->decoded_key_frame)
+ {
+ if (pc->frame_type == KEY_FRAME &&
+ !pc->yv12_fb[pc->new_fb_idx].corrupted)
+ pbi->decoded_key_frame = 1;
+ else
+ vpx_internal_error(&pbi->common.error, VPX_CODEC_CORRUPT_FRAME,
+ "A stream must start with a complete key frame");
+ }
+
/* 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 */
@@ -926,6 +1141,7 @@
if (pc->refresh_entropy_probs == 0)
{
vpx_memcpy(&pc->fc, &pc->lfc, sizeof(pc->fc));
+ pbi->independent_partitions = prev_independent_partitions;
}
#ifdef PACKET_TESTING
« no previous file with comments | « source/libvpx/vp8/decoder/decodemv.c ('k') | source/libvpx/vp8/decoder/detokenize.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698