Move inter speed features to separate function
No change in performance. A followup for features that occur after
handle_inter_mode is coming.
BUG=aomedia:2615
Change-Id: Ia7275d919e44c7ef8680d94c8d2040c663101562
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index aa1948f..bc6af31 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -4184,8 +4184,106 @@
}
}
-// Indicates number of winner simple translation modes to be used
-static unsigned int num_winner_motion_modes[3] = { 0, 10, 3 };
+// Arguments for speed feature pruning of inter mode search
+typedef struct {
+ int *skip_motion_mode;
+ mode_skip_mask_t *mode_skip_mask;
+ InterModeSearchState *search_state;
+ int skip_ref_frame_mask;
+ int reach_first_comp_mode;
+ int mode_thresh_mul_fact;
+ int *intra_mode_idx_ls;
+ int *intra_mode_num;
+ int prune_cpd_using_sr_stats_ready;
+} InterModeSFArgs;
+
+static int skip_inter_mode(AV1_COMP *cpi, MACROBLOCK *x, const BLOCK_SIZE bsize,
+ int64_t *ref_frame_rd, int midx,
+ InterModeSFArgs *args) {
+ const SPEED_FEATURES *const sf = &cpi->sf;
+ MACROBLOCKD *const xd = &x->e_mbd;
+ MB_MODE_INFO *const mbmi = xd->mi[0];
+ // Get the actual prediction mode we are trying in this iteration
+ const THR_MODES mode_enum = av1_default_mode_order[midx];
+ const MODE_DEFINITION *mode_def = &av1_mode_defs[mode_enum];
+ const PREDICTION_MODE this_mode = mode_def->mode;
+ const MV_REFERENCE_FRAME *ref_frames = mode_def->ref_frame;
+ const MV_REFERENCE_FRAME ref_frame = ref_frames[0];
+ const MV_REFERENCE_FRAME second_ref_frame = ref_frames[1];
+ const int comp_pred = second_ref_frame > INTRA_FRAME;
+ const int last_single_ref_mode_idx =
+ find_last_single_ref_mode_idx(av1_default_mode_order);
+
+ // After we done with single reference modes, find the 2nd best RD
+ // for a reference frame. Only search compound modes that have a reference
+ // frame at least as good as the 2nd best.
+ if (sf->inter_sf.prune_compound_using_single_ref &&
+ midx == last_single_ref_mode_idx + 1) {
+ find_top_ref(ref_frame_rd);
+ args->prune_cpd_using_sr_stats_ready = 1;
+ }
+
+ // Check if this mode should be skipped because it is incompatible with the
+ // current frame
+ if (inter_mode_compatible_skip(cpi, x, bsize, this_mode, ref_frames))
+ return 1;
+ const int ret = inter_mode_search_order_independent_skip(
+ cpi, x, args->mode_skip_mask, args->search_state,
+ args->skip_ref_frame_mask, this_mode, mode_def->ref_frame);
+ if (ret == 1) return 1;
+ *(args->skip_motion_mode) = (ret == 2);
+
+ // We've reached the first compound prediction mode, get stats from the
+ // single reference predictors to help with pruning
+ if (sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred &&
+ args->reach_first_comp_mode == 0) {
+ analyze_single_states(cpi, args->search_state);
+ args->reach_first_comp_mode = 1;
+ }
+
+ // Prune aggressively when best mode is skippable.
+ int mul_fact = args->search_state->best_mode_skippable
+ ? args->mode_thresh_mul_fact
+ : (1 << MODE_THRESH_QBITS);
+ int64_t mode_threshold =
+ (args->search_state->mode_threshold[mode_enum] * mul_fact) >>
+ MODE_THRESH_QBITS;
+
+ if (args->search_state->best_rd < mode_threshold) return 1;
+
+ // Skip this compound mode based on the RD results from the single prediction
+ // modes
+ if (sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred) {
+ if (compound_skip_by_single_states(cpi, args->search_state, this_mode,
+ ref_frame, second_ref_frame, x))
+ return 1;
+ }
+
+ // Speed features to prune out INTRA frames
+ if (ref_frame == INTRA_FRAME) {
+ if ((!cpi->oxcf.enable_smooth_intra || sf->intra_sf.disable_smooth_intra) &&
+ (mbmi->mode == SMOOTH_PRED || mbmi->mode == SMOOTH_H_PRED ||
+ mbmi->mode == SMOOTH_V_PRED))
+ return 1;
+ if (!cpi->oxcf.enable_paeth_intra && mbmi->mode == PAETH_PRED) return 1;
+ if (sf->inter_sf.adaptive_mode_search > 1)
+ if ((x->source_variance << num_pels_log2_lookup[bsize]) >
+ args->search_state->best_pred_sse)
+ return 1;
+
+ // Intra modes will be handled in another loop later.
+ assert(*args->intra_mode_num < INTRA_MODES);
+ args->intra_mode_idx_ls[(*args->intra_mode_num)++] = mode_enum;
+ return 1;
+ }
+
+ if (sf->inter_sf.prune_compound_using_single_ref &&
+ args->prune_cpd_using_sr_stats_ready && comp_pred &&
+ !in_single_ref_cutoff(ref_frame_rd, ref_frame, second_ref_frame)) {
+ return 1;
+ }
+ return 0;
+}
static void record_best_compound(REFERENCE_MODE reference_mode,
RD_STATS *rd_stats, int comp_pred, int rdmult,
@@ -4221,6 +4319,9 @@
hybrid_rd;
}
+// Indicates number of winner simple translation modes to be used
+static const unsigned int num_winner_motion_modes[3] = { 0, 10, 3 };
+
void av1_rd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
MACROBLOCK *x, RD_STATS *rd_cost,
const BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx,
@@ -4317,7 +4418,6 @@
int intra_mode_num = 0;
int intra_mode_idx_ls[INTRA_MODES];
- int reach_first_comp_mode = 0;
// Temporary buffers used by handle_inter_mode().
uint8_t *const tmp_buf = get_buf_by_bd(xd, x->tmp_obmc_bufs[0]);
@@ -4389,10 +4489,6 @@
}
}
- const int last_single_ref_mode_idx =
- find_last_single_ref_mode_idx(av1_default_mode_order);
- int prune_cpd_using_sr_stats_ready = 0;
-
// Initialize best mode stats for winner mode processing
av1_zero(x->winner_mode_stats);
x->winner_mode_count = 0;
@@ -4407,6 +4503,17 @@
mode_thresh_mul_fact = mode_threshold_mul_factor[x->qindex];
}
+ // Initialize arguments for mode loop speed features
+ InterModeSFArgs sf_args = { &args.skip_motion_mode,
+ &mode_skip_mask,
+ &search_state,
+ skip_ref_frame_mask,
+ 0,
+ mode_thresh_mul_fact,
+ intra_mode_idx_ls,
+ &intra_mode_num,
+ 0 };
+
// Here midx is just an iterator index that should not be used by itself
// except to keep track of the number of modes searched. It should be used
// with av1_default_mode_order to get the enum that defines the mode, which
@@ -4425,80 +4532,13 @@
ref_frame > INTRA_FRAME && second_ref_frame == NONE_FRAME;
const int comp_pred = second_ref_frame > INTRA_FRAME;
- // After we done with single reference modes, find the 2nd best RD
- // for a reference frame. Only search compound modes that have a reference
- // frame at least as good as the 2nd best.
- if (sf->inter_sf.prune_compound_using_single_ref &&
- midx == last_single_ref_mode_idx + 1) {
- find_top_ref(ref_frame_rd);
- prune_cpd_using_sr_stats_ready = 1;
- }
-
- if (inter_mode_compatible_skip(cpi, x, bsize, this_mode, ref_frames))
- continue;
- const int ret = inter_mode_search_order_independent_skip(
- cpi, x, &mode_skip_mask, &search_state, skip_ref_frame_mask, this_mode,
- mode_def->ref_frame);
- if (ret == 1) continue;
- args.skip_motion_mode = (ret == 2);
-
- if (sf->inter_sf.prune_compound_using_single_ref &&
- prune_cpd_using_sr_stats_ready && comp_pred &&
- !in_single_ref_cutoff(ref_frame_rd, ref_frame, second_ref_frame)) {
- continue;
- }
-
- // Reach the first compound prediction mode
- if (sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred &&
- reach_first_comp_mode == 0) {
- analyze_single_states(cpi, &search_state);
- reach_first_comp_mode = 1;
- }
-
init_mbmi(mbmi, this_mode, ref_frames, cm);
x->force_skip = 0;
set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
- // Prune aggressively when best mode is skippable.
- int mul_fact = search_state.best_mode_skippable ? mode_thresh_mul_fact
- : (1 << MODE_THRESH_QBITS);
- int64_t mode_threshold =
- (search_state.mode_threshold[mode_enum] * mul_fact) >>
- MODE_THRESH_QBITS;
-
- if (search_state.best_rd < mode_threshold) continue;
-
- if (sf->inter_sf.prune_comp_search_by_single_result > 0 && comp_pred) {
- if (compound_skip_by_single_states(cpi, &search_state, this_mode,
- ref_frame, second_ref_frame, x))
- continue;
- }
-
- const int compmode_cost =
- is_comp_ref_allowed(mbmi->sb_type) ? comp_inter_cost[comp_pred] : 0;
- const int real_compmode_cost =
- cm->current_frame.reference_mode == REFERENCE_MODE_SELECT
- ? compmode_cost
- : 0;
-
- if (ref_frame == INTRA_FRAME) {
- if ((!cpi->oxcf.enable_smooth_intra ||
- sf->intra_sf.disable_smooth_intra) &&
- (mbmi->mode == SMOOTH_PRED || mbmi->mode == SMOOTH_H_PRED ||
- mbmi->mode == SMOOTH_V_PRED))
- continue;
- if (!cpi->oxcf.enable_paeth_intra && mbmi->mode == PAETH_PRED) continue;
- if (sf->inter_sf.adaptive_mode_search > 1)
- if ((x->source_variance << num_pels_log2_lookup[bsize]) >
- search_state.best_pred_sse)
- continue;
-
- // Intra modes will be handled in another loop later.
- assert(intra_mode_num < INTRA_MODES);
- intra_mode_idx_ls[intra_mode_num++] = mode_enum;
- continue;
- }
+ // Apply speed features to decide if this inter mode can be skipped
+ if (skip_inter_mode(cpi, x, bsize, ref_frame_rd, midx, &sf_args)) continue;
// Select prediction reference frames.
for (i = 0; i < num_planes; i++) {
@@ -4519,6 +4559,12 @@
const int ref_frame_cost = comp_pred
? ref_costs_comp[ref_frame][second_ref_frame]
: ref_costs_single[ref_frame];
+ const int compmode_cost =
+ is_comp_ref_allowed(mbmi->sb_type) ? comp_inter_cost[comp_pred] : 0;
+ const int real_compmode_cost =
+ cm->current_frame.reference_mode == REFERENCE_MODE_SELECT
+ ? compmode_cost
+ : 0;
// Point to variables that are maintained between loop iterations
args.single_newmv = search_state.single_newmv;
args.single_newmv_rate = search_state.single_newmv_rate;