Add inter_mode_search_order_independent_skip() Move search order independent skip rules into this function. Change-Id: I5d415b81ae343915633232eebc83077966374274
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c index f9608b5..5f1c77c 100644 --- a/av1/encoder/rdopt.c +++ b/av1/encoder/rdopt.c
@@ -8299,6 +8299,15 @@ int above_stride, const uint8_t *left, int left_stride); +static const int ref_frame_flag_list[REF_FRAMES] = { 0, + AOM_LAST_FLAG, + AOM_LAST2_FLAG, + AOM_LAST3_FLAG, + AOM_GOLD_FLAG, + AOM_BWD_FLAG, + AOM_ALT2_FLAG, + AOM_ALT_FLAG }; + static void estimate_skip_mode_rdcost( const AV1_COMP *const cpi, TileDataEnc *tile_data, MACROBLOCK *const x, BLOCK_SIZE bsize, int mi_row, int mi_col, @@ -8311,14 +8320,6 @@ MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext; int *mode_map = tile_data->mode_map[bsize]; - static const int flag_list[REF_FRAMES] = { 0, - AOM_LAST_FLAG, - AOM_LAST2_FLAG, - AOM_LAST3_FLAG, - AOM_GOLD_FLAG, - AOM_BWD_FLAG, - AOM_ALT2_FLAG, - AOM_ALT_FLAG }; int i; for (int midx = 0; midx < MAX_MODES; ++midx) { @@ -8335,8 +8336,9 @@ const PREDICTION_MODE this_mode = av1_mode_order[mode_index].mode; - if (!(cpi->ref_frame_flags & flag_list[ref_frame])) continue; - if (comp_pred && !(cpi->ref_frame_flags & flag_list[second_ref_frame])) + if (!(cpi->ref_frame_flags & ref_frame_flag_list[ref_frame])) continue; + if (comp_pred && + !(cpi->ref_frame_flags & ref_frame_flag_list[second_ref_frame])) continue; // Check whether current refs/mode align with skip_mode if (!(ref_frame == (LAST_FRAME + cm->ref_frame_idx_0) && @@ -8536,15 +8538,6 @@ const struct segmentation *const seg = &cm->seg; const SPEED_FEATURES *const sf = &cpi->sf; unsigned char segment_id = mbmi->segment_id; - static const int flag_list[REF_FRAMES] = { 0, - AOM_LAST_FLAG, - AOM_LAST2_FLAG, - AOM_LAST3_FLAG, - AOM_GOLD_FLAG, - AOM_BWD_FLAG, - AOM_ALT2_FLAG, - AOM_ALT_FLAG }; - int dst_width1[MAX_MB_PLANE] = { MAX_SB_SIZE, MAX_SB_SIZE, MAX_SB_SIZE }; int dst_width2[MAX_MB_PLANE] = { MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1, MAX_SB_SIZE >> 1 }; @@ -8586,7 +8579,7 @@ x->pred_mv_sad[ref_frame] = INT_MAX; x->mbmi_ext->mode_context[ref_frame] = 0; x->mbmi_ext->compound_mode_context[ref_frame] = 0; - if (cpi->ref_frame_flags & flag_list[ref_frame]) { + if (cpi->ref_frame_flags & ref_frame_flag_list[ref_frame]) { assert(get_ref_frame_buffer(cpi, ref_frame) != NULL); setup_buffer_inter(cpi, x, ref_frame, bsize, mi_row, mi_col, frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb); @@ -8637,7 +8630,7 @@ for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) min_pred_mv_sad = AOMMIN(min_pred_mv_sad, x->pred_mv_sad[ref_frame]); for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) { - if (!(cpi->ref_frame_flags & flag_list[ref_frame])) { + if (!(cpi->ref_frame_flags & ref_frame_flag_list[ref_frame])) { // Skip checking missing references in both single and compound reference // modes. Note that a mode will be skipped iff both reference frames // are masked out. @@ -8693,7 +8686,7 @@ if (cpi->rc.is_src_frame_alt_ref) { if (sf->alt_ref_search_fp) { - assert(cpi->ref_frame_flags & flag_list[ALTREF_FRAME]); + assert(cpi->ref_frame_flags & ref_frame_flag_list[ALTREF_FRAME]); mode_skip_mask[ALTREF_FRAME] = 0; ref_frame_skip_mask[0] = ~(1 << ALTREF_FRAME); ref_frame_skip_mask[1] = SECOND_REF_FRAME_MASK; @@ -8834,6 +8827,97 @@ search_state->modelled_rd[i][ref_frame] = INT64_MAX; } +static int inter_mode_search_order_independent_skip(const AV1_COMP *cpi, + const MACROBLOCK *x, + BLOCK_SIZE bsize, + int mode_index) { + const SPEED_FEATURES *const sf = &cpi->sf; + const AV1_COMMON *const cm = &cpi->common; + const struct segmentation *const seg = &cm->seg; + const MACROBLOCKD *const xd = &x->e_mbd; + const MB_MODE_INFO *const mbmi = xd->mi[0]; + const unsigned char segment_id = mbmi->segment_id; + const MV_REFERENCE_FRAME *ref_frame = av1_mode_order[mode_index].ref_frame; + const PREDICTION_MODE this_mode = av1_mode_order[mode_index].mode; + + if (ref_frame[0] > INTRA_FRAME && ref_frame[1] == INTRA_FRAME) { + // Mode must by compatible + if (!is_interintra_allowed_mode(this_mode)) return 1; + if (!is_interintra_allowed_bsize(bsize)) return 1; + } + + // This is only used in motion vector unit test. + if (cpi->oxcf.motion_vector_unit_test && ref_frame[0] == INTRA_FRAME) + return 1; + + if (ref_frame[0] == INTRA_FRAME) { + if (this_mode != DC_PRED) { + // Disable intra modes other than DC_PRED for blocks with low variance + // Threshold for intra skipping based on source variance + // TODO(debargha): Specialize the threshold for super block sizes + const unsigned int skip_intra_var_thresh = 64; + if ((sf->mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) && + x->source_variance < skip_intra_var_thresh) + return 1; + } + } else { + if (!is_comp_ref_allowed(bsize) && ref_frame[1] > INTRA_FRAME) return 1; + } + + const int comp_pred = ref_frame[1] > INTRA_FRAME; + if (comp_pred) { + if (!cpi->allow_comp_inter_inter) return 1; + + // Skip compound inter modes if ARF is not available. + if (!(cpi->ref_frame_flags & ref_frame_flag_list[ref_frame[1]])) return 1; + + // Do not allow compound prediction if the segment level reference frame + // feature is in use as in this case there can only be one reference. + if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) return 1; + } + + if (sf->selective_ref_frame) { + if (sf->selective_ref_frame == 2 || x->cb_partition_scan) { + if (ref_frame[0] == ALTREF2_FRAME || ref_frame[1] == ALTREF2_FRAME) + if (get_relative_dist( + cm, cm->cur_frame->ref_frame_offset[ALTREF2_FRAME - LAST_FRAME], + cm->frame_offset) < 0) + return 1; + if (ref_frame[0] == BWDREF_FRAME || ref_frame[1] == BWDREF_FRAME) + if (get_relative_dist( + cm, cm->cur_frame->ref_frame_offset[BWDREF_FRAME - LAST_FRAME], + cm->frame_offset) < 0) + return 1; + } + if (ref_frame[0] == LAST3_FRAME || ref_frame[1] == LAST3_FRAME) + if (get_relative_dist( + cm, cm->cur_frame->ref_frame_offset[LAST3_FRAME - LAST_FRAME], + cm->cur_frame->ref_frame_offset[GOLDEN_FRAME - LAST_FRAME]) <= 0) + return 1; + if (ref_frame[0] == LAST2_FRAME || ref_frame[1] == LAST2_FRAME) + if (get_relative_dist( + cm, cm->cur_frame->ref_frame_offset[LAST2_FRAME - LAST_FRAME], + cm->cur_frame->ref_frame_offset[GOLDEN_FRAME - LAST_FRAME]) <= 0) + return 1; + } + + // One-sided compound is used only when all reference frames are one-sided. + if (sf->selective_ref_frame && comp_pred && !cpi->all_one_sided_refs) { + unsigned int ref_offsets[2]; + for (int i = 0; i < 2; ++i) { + const int buf_idx = cm->frame_refs[ref_frame[i] - LAST_FRAME].idx; + assert(buf_idx >= 0); + ref_offsets[i] = cm->buffer_pool->frame_bufs[buf_idx].cur_frame_offset; + } + if ((get_relative_dist(cm, ref_offsets[0], cm->frame_offset) <= 0 && + get_relative_dist(cm, ref_offsets[1], cm->frame_offset) <= 0) || + (get_relative_dist(cm, ref_offsets[0], cm->frame_offset) > 0 && + get_relative_dist(cm, ref_offsets[1], cm->frame_offset) > 0)) + return 1; + } + return 0; +} + void av1_rd_pick_inter_mode_sb(const AV1_COMP *cpi, TileDataEnc *tile_data, MACROBLOCK *x, int mi_row, int mi_col, RD_STATS *rd_cost, BLOCK_SIZE bsize, @@ -8853,14 +8937,6 @@ unsigned char segment_id = mbmi->segment_id; int i, k; struct buf_2d yv12_mb[REF_FRAMES][MAX_MB_PLANE]; - static const int flag_list[REF_FRAMES] = { 0, - AOM_LAST_FLAG, - AOM_LAST2_FLAG, - AOM_LAST3_FLAG, - AOM_GOLD_FLAG, - AOM_BWD_FLAG, - AOM_ALT2_FLAG, - AOM_ALT_FLAG }; const int skip_ctx = av1_get_skip_context(xd); const int rate_skip0 = x->skip_cost[skip_ctx][0]; const int rate_skip1 = x->skip_cost[skip_ctx][1]; @@ -8896,7 +8972,10 @@ ref_costs_single, ref_costs_comp, yv12_mb); for (int midx = 0; midx < MAX_MODES; ++midx) { - int mode_index; + int mode_index = mode_map[midx]; + if (inter_mode_search_order_independent_skip(cpi, x, bsize, mode_index)) + continue; + int64_t this_rd = INT64_MAX; int disable_skip = 0; int compmode_cost = 0; @@ -8907,7 +8986,6 @@ int64_t total_sse = INT64_MAX; uint8_t ref_frame_type; - mode_index = mode_map[midx]; x->skip_mode_index_candidate = mode_index; this_mode = av1_mode_order[mode_index].mode; ref_frame = av1_mode_order[mode_index].ref_frame[0]; @@ -8931,12 +9009,6 @@ } } - if (ref_frame > INTRA_FRAME && second_ref_frame == INTRA_FRAME) { - // Mode must by compatible - if (!is_interintra_allowed_mode(this_mode)) continue; - if (!is_interintra_allowed_bsize(bsize)) continue; - } - if (is_inter_compound_mode(this_mode)) { search_state.frame_mv[this_mode][ref_frame].as_int = search_state.frame_mv[compound_ref0_mode(this_mode)][ref_frame] @@ -8956,20 +9028,8 @@ if (search_state.best_rd < search_state.mode_threshold[mode_index]) continue; - // This is only used in motion vector unit test. - if (cpi->oxcf.motion_vector_unit_test && ref_frame == INTRA_FRAME) continue; - const int comp_pred = second_ref_frame > INTRA_FRAME; if (comp_pred) { - if (!cpi->allow_comp_inter_inter) continue; - - // Skip compound inter modes if ARF is not available. - if (!(cpi->ref_frame_flags & flag_list[second_ref_frame])) continue; - - // Do not allow compound prediction if the segment level reference frame - // feature is in use as in this case there can only be one reference. - if (segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME)) continue; - if ((sf->mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) && search_state.best_mode_index >= 0 && search_state.best_mbmode.ref_frame[0] == INTRA_FRAME) @@ -8983,13 +9043,6 @@ continue; if (this_mode != DC_PRED) { - // Disable intra modes other than DC_PRED for blocks with low variance - // Threshold for intra skipping based on source variance - // TODO(debargha): Specialize the threshold for super block sizes - const unsigned int skip_intra_var_thresh = 64; - if ((sf->mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) && - x->source_variance < skip_intra_var_thresh) - continue; // Only search the oblique modes if the best so far is // one of the neighboring directional modes if ((sf->mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) && @@ -9039,54 +9092,6 @@ mbmi->interintra_mode = (INTERINTRA_MODE)(II_DC_PRED - 1); - if (sf->selective_ref_frame) { - if (sf->selective_ref_frame == 2 || x->cb_partition_scan) { - if (mbmi->ref_frame[0] == ALTREF2_FRAME || - mbmi->ref_frame[1] == ALTREF2_FRAME) - if (get_relative_dist( - cm, - cm->cur_frame->ref_frame_offset[ALTREF2_FRAME - LAST_FRAME], - cm->frame_offset) < 0) - continue; - if (mbmi->ref_frame[0] == BWDREF_FRAME || - mbmi->ref_frame[1] == BWDREF_FRAME) - if (get_relative_dist( - cm, - cm->cur_frame->ref_frame_offset[BWDREF_FRAME - LAST_FRAME], - cm->frame_offset) < 0) - continue; - } - if (mbmi->ref_frame[0] == LAST3_FRAME || - mbmi->ref_frame[1] == LAST3_FRAME) - if (get_relative_dist( - cm, cm->cur_frame->ref_frame_offset[LAST3_FRAME - LAST_FRAME], - cm->cur_frame->ref_frame_offset[GOLDEN_FRAME - LAST_FRAME]) <= - 0) - continue; - if (mbmi->ref_frame[0] == LAST2_FRAME || - mbmi->ref_frame[1] == LAST2_FRAME) - if (get_relative_dist( - cm, cm->cur_frame->ref_frame_offset[LAST2_FRAME - LAST_FRAME], - cm->cur_frame->ref_frame_offset[GOLDEN_FRAME - LAST_FRAME]) <= - 0) - continue; - } - - // One-sided compound is used only when all reference frames are one-sided. - if (sf->selective_ref_frame && comp_pred && !cpi->all_one_sided_refs) { - unsigned int ref_offsets[2]; - for (i = 0; i < 2; ++i) { - const int buf_idx = cm->frame_refs[mbmi->ref_frame[i] - LAST_FRAME].idx; - assert(buf_idx >= 0); - ref_offsets[i] = cm->buffer_pool->frame_bufs[buf_idx].cur_frame_offset; - } - if ((get_relative_dist(cm, ref_offsets[0], cm->frame_offset) <= 0 && - get_relative_dist(cm, ref_offsets[1], cm->frame_offset) <= 0) || - (get_relative_dist(cm, ref_offsets[0], cm->frame_offset) > 0 && - get_relative_dist(cm, ref_offsets[1], cm->frame_offset) > 0)) - continue; - } - if (ref_frame == INTRA_FRAME) { RD_STATS rd_stats_y; TX_SIZE uv_tx; @@ -9231,9 +9236,6 @@ } else { int_mv backup_ref_mv[2]; - if (!is_comp_ref_allowed(bsize) && mbmi->ref_frame[1] > INTRA_FRAME) - continue; - backup_ref_mv[0] = mbmi_ext->ref_mvs[ref_frame][0]; if (comp_pred) backup_ref_mv[1] = mbmi_ext->ref_mvs[second_ref_frame][0]; mbmi->angle_delta[PLANE_TYPE_Y] = 0;