From b5ee7b12d232badfd54b4d2f76f8c3fa40d67e6a Mon Sep 17 00:00:00 2001 From: Stefan Holmer Date: Fri, 18 Nov 2011 15:44:17 +0100 Subject: Decoder fixes to better support reference picture selection. Change-Id: Id3388985d754706b9fd1f079c47121e79a63efdf --- vp8/decoder/decodframe.c | 22 ++++++++++++++++++++++ vp8/decoder/error_concealment.c | 38 ++++---------------------------------- vp8/decoder/onyxd_if.c | 40 +++++++++++++++++++++++++--------------- 3 files changed, 51 insertions(+), 49 deletions(-) (limited to 'vp8') diff --git a/vp8/decoder/decodframe.c b/vp8/decoder/decodframe.c index e501b9ec7..6f2cdfabb 100644 --- a/vp8/decoder/decodframe.c +++ b/vp8/decoder/decodframe.c @@ -934,16 +934,38 @@ int vp8_decode_frame(VP8D_COMP *pbi) if (!pc->refresh_golden_frame) pc->copy_buffer_to_gf = vp8_read_literal(bc, 2); +#if CONFIG_ERROR_CONCEALMENT + /* Assume we shouldn't copy to the golden if the bit is missing */ + xd->corrupted |= vp8dx_bool_error(bc); + if (pbi->ec_active && xd->corrupted) + pc->copy_buffer_to_gf = 0; +#endif + pc->copy_buffer_to_arf = 0; if (!pc->refresh_alt_ref_frame) pc->copy_buffer_to_arf = vp8_read_literal(bc, 2); +#if CONFIG_ERROR_CONCEALMENT + /* Assume we shouldn't copy to the alt-ref if the bit is missing */ + xd->corrupted |= vp8dx_bool_error(bc); + if (pbi->ec_active && xd->corrupted) + pc->copy_buffer_to_arf = 0; +#endif + + pc->ref_frame_sign_bias[GOLDEN_FRAME] = vp8_read_bit(bc); pc->ref_frame_sign_bias[ALTREF_FRAME] = vp8_read_bit(bc); } pc->refresh_entropy_probs = vp8_read_bit(bc); +#if CONFIG_ERROR_CONCEALMENT + /* Assume we shouldn't refresh the probabilities if the bit is + * missing */ + xd->corrupted |= vp8dx_bool_error(bc); + if (pbi->ec_active && xd->corrupted) + pc->refresh_entropy_probs = 0; +#endif if (pc->refresh_entropy_probs == 0) { vpx_memcpy(&pc->lfc, &pc->fc, sizeof(pc->fc)); diff --git a/vp8/decoder/error_concealment.c b/vp8/decoder/error_concealment.c index 86fa191d3..b77d743f7 100644 --- a/vp8/decoder/error_concealment.c +++ b/vp8/decoder/error_concealment.c @@ -491,33 +491,6 @@ static void find_neighboring_blocks(MODE_INFO *mi, assert(i == 20); } -/* Calculates which reference frame type is dominating among the neighbors */ -static MV_REFERENCE_FRAME dominant_ref_frame(EC_BLOCK *neighbors) -{ - /* Default to referring to "skip" */ - MV_REFERENCE_FRAME dom_ref_frame = LAST_FRAME; - int max_ref_frame_cnt = 0; - int ref_frame_cnt[MAX_REF_FRAMES] = {0}; - int i; - /* Count neighboring reference frames */ - for (i = 0; i < NUM_NEIGHBORS; ++i) - { - if (neighbors[i].ref_frame < MAX_REF_FRAMES && - neighbors[i].ref_frame != INTRA_FRAME) - ++ref_frame_cnt[neighbors[i].ref_frame]; - } - /* Find maximum */ - for (i = 0; i < MAX_REF_FRAMES; ++i) - { - if (ref_frame_cnt[i] > max_ref_frame_cnt) - { - dom_ref_frame = i; - max_ref_frame_cnt = ref_frame_cnt[i]; - } - } - return dom_ref_frame; -} - /* Interpolates all motion vectors for a macroblock from the neighboring blocks' * motion vectors. */ @@ -591,7 +564,6 @@ void vp8_interpolate_motion(MACROBLOCKD *mb, { /* Find relevant neighboring blocks */ EC_BLOCK neighbors[NUM_NEIGHBORS]; - MV_REFERENCE_FRAME dom_ref_frame; int i; /* Initialize the array. MAX_REF_FRAMES is interpreted as "doesn't exist" */ for (i = 0; i < NUM_NEIGHBORS; ++i) @@ -604,13 +576,11 @@ void vp8_interpolate_motion(MACROBLOCKD *mb, mb_row, mb_col, mb_rows, mb_cols, mb->mode_info_stride); - /* Determine the dominant block type */ - dom_ref_frame = dominant_ref_frame(neighbors); - /* Interpolate MVs for the missing blocks - * from the dominating MVs */ - interpolate_mvs(mb, neighbors, dom_ref_frame); + /* Interpolate MVs for the missing blocks from the surrounding + * blocks which refer to the last frame. */ + interpolate_mvs(mb, neighbors, LAST_FRAME); - mb->mode_info_context->mbmi.ref_frame = dom_ref_frame; + mb->mode_info_context->mbmi.ref_frame = LAST_FRAME; mb->mode_info_context->mbmi.mode = SPLITMV; mb->mode_info_context->mbmi.uv_mode = DC_PRED; mb->mode_info_context->mbmi.partitioning = 3; diff --git a/vp8/decoder/onyxd_if.c b/vp8/decoder/onyxd_if.c index 077954948..cf525f4a9 100644 --- a/vp8/decoder/onyxd_if.c +++ b/vp8/decoder/onyxd_if.c @@ -359,28 +359,38 @@ int vp8dx_receive_compressed_data(VP8D_PTR ptr, unsigned long size, const unsign pbi->fragment_sizes[0] = 0; } - if (pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 0) + if (!pbi->ec_active && + pbi->num_fragments <= 1 && pbi->fragment_sizes[0] == 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; - /* If error concealment is disabled we won't signal missing frames * to the decoder. */ - if (!pbi->ec_active) + if (cm->fb_idx_ref_cnt[cm->lst_fb_idx] > 1) { - /* Signal that we have no frame to show. */ - cm->show_frame = 0; + /* The last reference shares buffer with another reference + * buffer. Move it to its own buffer before setting it as + * corrupt, otherwise we will make multiple buffers corrupt. + */ + const int prev_idx = cm->lst_fb_idx; + cm->fb_idx_ref_cnt[prev_idx]--; + cm->lst_fb_idx = get_free_fb(cm); + vp8_yv12_copy_frame_ptr(&cm->yv12_fb[prev_idx], + &cm->yv12_fb[cm->lst_fb_idx]); + } + /* 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; - pbi->num_fragments = 0; + /* Signal that we have no frame to show. */ + cm->show_frame = 0; - /* Nothing more to do. */ - return 0; - } + pbi->num_fragments = 0; + + /* Nothing more to do. */ + return 0; } #if HAVE_ARMV7 -- cgit v1.2.3