[NORMATIVE] Use the primary reference frame as prev_frame Previously LAST_FRAME was used. BUG=aomedia:1589 Change-Id: I5358e81406afeda4b56de41e55c9c1ab104ec6c4
diff --git a/av1/common/onyxc_int.h b/av1/common/onyxc_int.h index bec31a5..9951334 100644 --- a/av1/common/onyxc_int.h +++ b/av1/common/onyxc_int.h
@@ -653,6 +653,15 @@ return cm->frame_type == KEY_FRAME || cm->intra_only; } +static INLINE RefCntBuffer *get_prev_frame(const AV1_COMMON *const cm) { + if (cm->primary_ref_frame == PRIMARY_REF_NONE || + cm->frame_refs[cm->primary_ref_frame].idx == INVALID_IDX) { + return NULL; + } else { + return &cm->buffer_pool + ->frame_bufs[cm->frame_refs[cm->primary_ref_frame].idx]; + } +} // Returns 1 if this frame might use mvs from some previous frame. This // function doesn't consider whether prev_frame is actually suitable (see // frame_can_use_prev_frame_mvs for that)
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c index a115413..78ff4e3 100644 --- a/av1/decoder/decodeframe.c +++ b/av1/decoder/decodeframe.c
@@ -2522,8 +2522,9 @@ static void read_global_motion(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) { for (int frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) { const WarpedMotionParams *ref_params = - cm->error_resilient_mode ? &default_warp_params - : &cm->prev_frame->global_motion[frame]; + (cm->error_resilient_mode || cm->prev_frame == NULL) + ? &default_warp_params + : &cm->prev_frame->global_motion[frame]; int good_params = read_global_motion_params( &cm->global_motion[frame], ref_params, rb, cm->allow_high_precision_mv); if (!good_params) { @@ -2837,6 +2838,10 @@ } #endif + if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) { + cm->primary_ref_frame = aom_rb_read_literal(rb, PRIMARY_REF_BITS); + } + if (cm->frame_type == KEY_FRAME) { #if !CONFIG_EXPLICIT_ORDER_HINT wrap_around_current_video_frame(pbi); @@ -3019,17 +3024,25 @@ #endif cm->interp_filter = read_frame_interp_filter(rb); cm->switchable_motion_mode = aom_rb_read_bit(rb); + } + + cm->prev_frame = get_prev_frame(cm); + if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) { + if (cm->primary_ref_frame != PRIMARY_REF_NONE && + cm->frame_refs[cm->primary_ref_frame].idx < 0) { + aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME, + "Reference frame containing this frame's initial " + "frame context is unavailable."); + } + } + + if (!cm->intra_only && pbi->need_resync != 1) { if (frame_might_use_prev_frame_mvs(cm) && cm->seq_params.enable_order_hint) cm->use_ref_frame_mvs = aom_rb_read_bit(rb); else cm->use_ref_frame_mvs = 0; - cm->prev_frame = - cm->frame_refs[LAST_FRAME - LAST_FRAME].idx != INVALID_IDX - ? &cm->buffer_pool - ->frame_bufs[cm->frame_refs[LAST_FRAME - LAST_FRAME].idx] - : NULL; for (int i = 0; i < INTER_REFS_PER_FRAME; ++i) { RefBuffer *const ref_buf = &cm->frame_refs[i]; av1_setup_scale_factors_for_frame( @@ -3083,15 +3096,6 @@ } else { cm->refresh_frame_context = REFRESH_FRAME_CONTEXT_DISABLED; } - if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) { - cm->primary_ref_frame = aom_rb_read_literal(rb, PRIMARY_REF_BITS); - if (cm->primary_ref_frame != PRIMARY_REF_NONE && - cm->frame_refs[cm->primary_ref_frame].idx < 0) { - aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME, - "Reference frame containing this frame's initial " - "frame context is unavailable."); - } - } // Generate next_ref_frame_map. lock_buffer_pool(pool);
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c index abc5643..2838da7 100644 --- a/av1/decoder/decoder.c +++ b/av1/decoder/decoder.c
@@ -379,9 +379,6 @@ if (!cm->show_existing_frame) { cm->last_show_frame = cm->show_frame; - // NOTE: It is not supposed to ref to any frame not used as reference - if (cm->is_reference_frame) cm->prev_frame = cm->cur_frame; - if (cm->seg.enabled) { #if CONFIG_SEGMENT_PRED_LAST if (cm->prev_frame && (cm->mi_rows == cm->prev_frame->mi_rows) &&
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c index c5b513f..70b20ff 100644 --- a/av1/encoder/bitstream.c +++ b/av1/encoder/bitstream.c
@@ -2928,8 +2928,9 @@ int frame; for (frame = LAST_FRAME; frame <= ALTREF_FRAME; ++frame) { const WarpedMotionParams *ref_params = - cm->error_resilient_mode ? &default_warp_params - : &cm->prev_frame->global_motion[frame]; + (cm->error_resilient_mode || cm->prev_frame == NULL) + ? &default_warp_params + : &cm->prev_frame->global_motion[frame]; write_global_motion_params(&cm->global_motion[frame], ref_params, wb, cm->allow_high_precision_mv); // TODO(sarahparker, debargha): The logic in the commented out code below @@ -3086,6 +3087,10 @@ } #endif + if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) { + aom_wb_write_literal(wb, cm->primary_ref_frame, PRIMARY_REF_BITS); + } + if (cm->frame_type == KEY_FRAME) { write_frame_size(cm, frame_size_override_flag, wb); assert(av1_superres_unscaled(cm) || @@ -3243,9 +3248,7 @@ aom_wb_write_bit( wb, cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_DISABLED); } - if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) { - aom_wb_write_literal(wb, cm->primary_ref_frame, PRIMARY_REF_BITS); - } + #if CONFIG_TILE_INFO_FIRST write_tile_info(cm, saved_wb, wb); #endif // CONFIG_TILE_INFO_FIRST
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c index 8348f28..f09343c 100644 --- a/av1/encoder/encodeframe.c +++ b/av1/encoder/encodeframe.c
@@ -304,7 +304,8 @@ if (seg->enabled && !cpi->vaq_refresh) { const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; - mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col); + mbmi->segment_id = + map ? get_segment_id(cm, map, bsize, mi_row, mi_col) : 0; } av1_init_plane_quantizers(cpi, x, mbmi->segment_id); } @@ -459,7 +460,8 @@ if (cpi->oxcf.aq_mode == COMPLEXITY_AQ) { const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; - mbmi->segment_id = get_segment_id(cm, map, bsize, mi_row, mi_col); + mbmi->segment_id = + map ? get_segment_id(cm, map, bsize, mi_row, mi_col) : 0; reset_tx_size(x, mbmi, cm->tx_mode); } // Else for cyclic refresh mode update the segment map, set the segment id @@ -3505,7 +3507,8 @@ const uint8_t *const map = seg->update_map ? cpi->segmentation_map : cm->last_frame_seg_map; int segment_id = - get_segment_id(cm, map, cm->seq_params.sb_size, mi_row, mi_col); + map ? get_segment_id(cm, map, cm->seq_params.sb_size, mi_row, mi_col) + : 0; seg_skip = segfeature_active(seg, segment_id, SEG_LVL_SKIP); } #if CONFIG_AMVR @@ -4084,7 +4087,6 @@ MACROBLOCKD *const xd = &x->e_mbd; RD_COUNTS *const rdc = &cpi->td.rd_counts; int i; - const int last_fb_buf_idx = get_ref_frame_buf_idx(cpi, LAST_FRAME); x->min_partition_size = AOMMIN(x->min_partition_size, cm->seq_params.sb_size); x->max_partition_size = AOMMIN(x->max_partition_size, cm->seq_params.sb_size); @@ -4197,6 +4199,62 @@ } #endif + for (i = 0; i < MAX_SEGMENTS; ++i) { + const int qindex = cm->seg.enabled + ? av1_get_qindex(&cm->seg, i, cm->base_qindex) + : cm->base_qindex; + xd->lossless[i] = qindex == 0 && cm->y_dc_delta_q == 0 && + cm->u_dc_delta_q == 0 && cm->u_ac_delta_q == 0 && + cm->v_dc_delta_q == 0 && cm->v_ac_delta_q == 0; + if (xd->lossless[i]) cpi->has_lossless_segment = 1; + xd->qindex[i] = qindex; + if (xd->lossless[i]) { + cpi->optimize_seg_arr[i] = 0; + } else { + cpi->optimize_seg_arr[i] = cpi->optimize_speed_feature; + } + } + cm->all_lossless = all_lossless(cm, xd); + + cm->tx_mode = select_tx_mode(cpi); + + // Fix delta q resolution for the moment + cm->delta_q_res = DEFAULT_DELTA_Q_RES; +// Set delta_q_present_flag before it is used for the first time +#if CONFIG_EXT_DELTA_Q + cm->delta_lf_res = DEFAULT_DELTA_LF_RES; + cm->delta_q_present_flag = cpi->oxcf.deltaq_mode != NO_DELTA_Q; + cm->delta_lf_present_flag = cpi->oxcf.deltaq_mode == DELTA_Q_LF; + cm->delta_lf_multi = DEFAULT_DELTA_LF_MULTI; + // update delta_q_present_flag and delta_lf_present_flag based on base_qindex + cm->delta_q_present_flag &= cm->base_qindex > 0; + cm->delta_lf_present_flag &= cm->base_qindex > 0; +#else + cm->delta_q_present_flag = + cpi->oxcf.aq_mode == DELTA_AQ && cm->base_qindex > 0; +#endif // CONFIG_EXT_DELTA_Q + + av1_frame_init_quantizer(cpi); + + av1_initialize_rd_consts(cpi); + av1_initialize_me_consts(cpi, x, cm->base_qindex); + init_encode_frame_mb_context(cpi); + +#if CONFIG_SEGMENT_PRED_LAST + if (cm->prev_frame) + cm->last_frame_seg_map = cm->prev_frame->seg_map; + else + cm->last_frame_seg_map = NULL; + cm->current_frame_seg_map = cm->cur_frame->seg_map; +#endif + + // Special case: set prev_mi to NULL when the previous mode info + // context cannot be used. + cm->prev_mi = cm->use_ref_frame_mvs ? cm->prev_mip : NULL; + + x->txb_split_count = 0; + av1_zero(x->blk_skip_drl); + av1_zero(rdc->global_motion_used); av1_zero(cpi->gmparams_cost); if (cpi->common.frame_type == INTER_FRAME && cpi->source && @@ -4217,8 +4275,9 @@ int pframe; cm->global_motion[frame] = default_warp_params; const WarpedMotionParams *ref_params = - cm->error_resilient_mode ? &default_warp_params - : &cm->prev_frame->global_motion[frame]; + (cm->error_resilient_mode || cm->prev_frame == NULL) + ? &default_warp_params + : &cm->prev_frame->global_motion[frame]; // check for duplicate buffer for (pframe = LAST_FRAME; pframe < frame; ++pframe) { if (ref_buf[frame] == ref_buf[pframe]) break; @@ -4315,62 +4374,6 @@ memcpy(cm->cur_frame->global_motion, cm->global_motion, TOTAL_REFS_PER_FRAME * sizeof(WarpedMotionParams)); - for (i = 0; i < MAX_SEGMENTS; ++i) { - const int qindex = cm->seg.enabled - ? av1_get_qindex(&cm->seg, i, cm->base_qindex) - : cm->base_qindex; - xd->lossless[i] = qindex == 0 && cm->y_dc_delta_q == 0 && - cm->u_dc_delta_q == 0 && cm->u_ac_delta_q == 0 && - cm->v_dc_delta_q == 0 && cm->v_ac_delta_q == 0; - if (xd->lossless[i]) cpi->has_lossless_segment = 1; - xd->qindex[i] = qindex; - if (xd->lossless[i]) { - cpi->optimize_seg_arr[i] = 0; - } else { - cpi->optimize_seg_arr[i] = cpi->optimize_speed_feature; - } - } - cm->all_lossless = all_lossless(cm, xd); - - cm->tx_mode = select_tx_mode(cpi); - - // Fix delta q resolution for the moment - cm->delta_q_res = DEFAULT_DELTA_Q_RES; -// Set delta_q_present_flag before it is used for the first time -#if CONFIG_EXT_DELTA_Q - cm->delta_lf_res = DEFAULT_DELTA_LF_RES; - cm->delta_q_present_flag = cpi->oxcf.deltaq_mode != NO_DELTA_Q; - cm->delta_lf_present_flag = cpi->oxcf.deltaq_mode == DELTA_Q_LF; - cm->delta_lf_multi = DEFAULT_DELTA_LF_MULTI; - // update delta_q_present_flag and delta_lf_present_flag based on base_qindex - cm->delta_q_present_flag &= cm->base_qindex > 0; - cm->delta_lf_present_flag &= cm->base_qindex > 0; -#else - cm->delta_q_present_flag = - cpi->oxcf.aq_mode == DELTA_AQ && cm->base_qindex > 0; -#endif // CONFIG_EXT_DELTA_Q - - av1_frame_init_quantizer(cpi); - - av1_initialize_rd_consts(cpi); - av1_initialize_me_consts(cpi, x, cm->base_qindex); - init_encode_frame_mb_context(cpi); - - cm->prev_frame = last_fb_buf_idx != INVALID_IDX - ? &cm->buffer_pool->frame_bufs[last_fb_buf_idx] - : NULL; -#if CONFIG_SEGMENT_PRED_LAST - if (cm->prev_frame) cm->last_frame_seg_map = cm->prev_frame->seg_map; - cm->current_frame_seg_map = cm->cur_frame->seg_map; -#endif - - // Special case: set prev_mi to NULL when the previous mode info - // context cannot be used. - cm->prev_mi = cm->use_ref_frame_mvs ? cm->prev_mip : NULL; - - x->txb_split_count = 0; - av1_zero(x->blk_skip_drl); - av1_setup_motion_field(cm); cpi->all_one_sided_refs = @@ -4744,12 +4747,16 @@ mi_row, mi_col); } - // If there is at least one lossless segment, force the skip for intra block - // to be 0, in order to avoid the segment_id to be changed by in - // write_segment_id(). + // If there is at least one lossless segment, force the skip for intra + // block to be 0, in order to avoid the segment_id to be changed by in + // write_segment_id(). +#if CONFIG_SPATIAL_SEGMENTATION if (!cpi->common.seg.preskip_segid && cpi->common.seg.update_map && cpi->has_lossless_segment) mbmi->skip = 0; +#else + if (cpi->common.seg.update_map && cpi->has_lossless_segment) mbmi->skip = 0; +#endif xd->cfl.store_y = 0; if (av1_allow_palette(cm->allow_screen_content_tools, bsize)) {
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 49ab33c..d637219 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -302,10 +302,6 @@ // other inter-frames the encoder currently uses only two contexts; // context 1 for ALTREF frames and context 0 for the others. -#if CONFIG_SEGMENT_PRED_LAST - if (cm->prev_frame) cm->last_frame_seg_map = cm->prev_frame->seg_map; - cm->current_frame_seg_map = cm->cur_frame->seg_map; -#endif cm->primary_ref_frame = PRIMARY_REF_NONE; if (frame_is_intra_only(cm) || cm->error_resilient_mode) { av1_setup_past_independence(cm); @@ -361,7 +357,16 @@ av1_zero(cpi->interp_filter_selected[0]); } + cm->prev_frame = get_prev_frame(cm); cpi->vaq_refresh = 0; + +#if CONFIG_SEGMENT_PRED_LAST + if (cm->prev_frame) + cm->last_frame_seg_map = cm->prev_frame->seg_map; + else + cm->last_frame_seg_map = NULL; + cm->current_frame_seg_map = cm->cur_frame->seg_map; +#endif } static void enc_setup_mi(AV1_COMMON *cm) { @@ -560,8 +565,10 @@ av1_set_default_ref_deltas(last_ref_deltas); av1_set_default_mode_deltas(last_mode_deltas); } else { + assert(cm->buffer_pool->frame_bufs[buf_idx].ref_deltas != NULL); memcpy(last_ref_deltas, cm->buffer_pool->frame_bufs[buf_idx].ref_deltas, TOTAL_REFS_PER_FRAME); + assert(cm->buffer_pool->frame_bufs[buf_idx].mode_deltas != NULL); memcpy(last_mode_deltas, cm->buffer_pool->frame_bufs[buf_idx].mode_deltas, MAX_MODE_LF_DELTAS); } @@ -4386,10 +4393,11 @@ apply_active_map(cpi); #if CONFIG_SEGMENT_PRED_LAST if (cm->seg.enabled) { - if (cm->seg.update_data) + if (cm->seg.update_data) { segfeatures_copy(&cm->cur_frame->seg, &cm->seg); - else if (cm->prev_frame) + } else if (cm->prev_frame) { segfeatures_copy(&cm->seg, &cm->prev_frame->seg); + } } #endif @@ -4494,10 +4502,11 @@ } #if CONFIG_SEGMENT_PRED_LAST if (cm->seg.enabled) { - if (cm->seg.update_data) + if (cm->seg.update_data) { segfeatures_copy(&cm->cur_frame->seg, &cm->seg); - else if (cm->prev_frame) + } else if (cm->prev_frame) { segfeatures_copy(&cm->seg, &cm->prev_frame->seg); + } } #endif @@ -5211,7 +5220,7 @@ if (cm->seg.enabled) { if (cm->seg.update_map) { update_reference_segmentation_map(cpi); - } else { + } else if (cm->last_frame_seg_map) { memcpy(cm->current_frame_seg_map, cm->last_frame_seg_map, cm->mi_cols * cm->mi_rows * sizeof(uint8_t)); } @@ -5283,7 +5292,6 @@ // NOTE: Shall not refer to any frame not used as reference. if (cm->is_reference_frame) { - cm->prev_frame = cm->cur_frame; // keep track of the last coded dimensions cm->last_width = cm->width; cm->last_height = cm->height;
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index 9ebf0e2..c7b6dfb 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -4460,7 +4460,6 @@ ref_best_rd = AOMMIN(rd, ref_best_rd); if (rd < best_rd) { - best_rd = rd; *rd_stats = this_rd_stats; best_tx = mbmi->tx_size; memcpy(best_blk_skip, x->blk_skip[0], sizeof(best_blk_skip[0]) * n4);
diff --git a/av1/encoder/segmentation.c b/av1/encoder/segmentation.c index e90fb07..d77bcb5 100644 --- a/av1/encoder/segmentation.c +++ b/av1/encoder/segmentation.c
@@ -70,7 +70,9 @@ const BLOCK_SIZE bsize = xd->mi[0]->mbmi.sb_type; // Test to see if the segment id matches the predicted value. const int pred_segment_id = - get_segment_id(cm, cm->last_frame_seg_map, bsize, mi_row, mi_col); + cm->last_frame_seg_map + ? get_segment_id(cm, cm->last_frame_seg_map, bsize, mi_row, mi_col) + : 0; const int pred_flag = pred_segment_id == segment_id; const int pred_context = av1_get_pred_context_seg_id(xd);