rtc: Abstract code related to inter mode evaluation

Abstracted code related to inter mode evaluation to the function
handle_inter_mode_nonrd(). The new function created in this patch
is similar to handle_inter_mode() function in rd path.

Change-Id: I946e0137dc2dd1dbfffe5a0a91f731c864ffdc62
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index b4ca51d..1f54d38 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -3545,6 +3545,436 @@
   return false;
 }
 
+// Function to perform inter mode evaluation for non-rd
+static AOM_FORCE_INLINE bool handle_inter_mode_nonrd(
+    AV1_COMP *cpi, MACROBLOCK *x, InterModeSearchStateNonrd *search_state,
+    PICK_MODE_CONTEXT *ctx, PRED_BUFFER **this_mode_pred,
+    PRED_BUFFER *tmp_buffer, InterPredParams inter_pred_params_sr,
+    int *best_early_term, unsigned int *sse_zeromv_norm, bool *check_globalmv,
+#if CONFIG_AV1_TEMPORAL_DENOISING
+    int64_t *zero_last_cost_orig, int denoise_svc_pickmode,
+#endif
+    int idx, int force_mv_inter_layer, int comp_pred, int skip_pred_mv,
+    const int gf_temporal_ref, const int use_model_yrd_large,
+    const int filter_search_enabled_blk, BLOCK_SIZE bsize,
+    PREDICTION_MODE this_mode, InterpFilter filt_select,
+    const int cb_pred_filter_search, const int reuse_inter_pred) {
+  AV1_COMMON *const cm = &cpi->common;
+  MACROBLOCKD *const xd = &x->e_mbd;
+  MB_MODE_INFO *const mi = xd->mi[0];
+  const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
+  const int mi_row = xd->mi_row;
+  const int mi_col = xd->mi_col;
+  struct macroblockd_plane *const pd = &xd->plane[0];
+  const int bw = block_size_wide[bsize];
+  const InterpFilter filter_ref = cm->features.interp_filter;
+  const InterpFilter default_interp_filter = EIGHTTAP_REGULAR;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
+  const ModeCosts *mode_costs = &x->mode_costs;
+
+  MV_REFERENCE_FRAME ref_frame = mi->ref_frame[0];
+  MV_REFERENCE_FRAME ref_frame2 = mi->ref_frame[1];
+  const int num_8x8_blocks = ctx->num_4x4_blk / 4;
+  unsigned int var = UINT_MAX;
+  int this_early_term = 0;
+  int rate_mv = 0;
+  int is_skippable;
+  int skip_this_mv = 0;
+  unsigned int var_threshold = UINT_MAX;
+  PREDICTION_MODE this_best_mode;
+  RD_STATS nonskip_rdc;
+  av1_invalid_rd_stats(&nonskip_rdc);
+
+  if (this_mode == NEWMV && !force_mv_inter_layer) {
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_start(&ms_stat.timer2);
+#endif
+    const bool skip_newmv = search_new_mv(
+        cpi, x, search_state->frame_mv, ref_frame, gf_temporal_ref, bsize,
+        mi_row, mi_col, &rate_mv, &search_state->best_rdc);
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_mark(&ms_stat.timer2);
+    ms_stat.ms_time[bsize][this_mode] +=
+        aom_usec_timer_elapsed(&ms_stat.timer2);
+#endif
+    if (skip_newmv) {
+      return true;
+    }
+  }
+
+  for (PREDICTION_MODE inter_mv_mode = NEARESTMV; inter_mv_mode <= NEWMV;
+       inter_mv_mode++) {
+    if (inter_mv_mode == this_mode) continue;
+    if (!comp_pred && search_state->mode_checked[inter_mv_mode][ref_frame] &&
+        search_state->frame_mv[this_mode][ref_frame].as_int ==
+            search_state->frame_mv[inter_mv_mode][ref_frame].as_int) {
+      skip_this_mv = 1;
+      break;
+    }
+  }
+
+  if (skip_this_mv && !comp_pred) return true;
+
+  // For screen: for spatially flat blocks with non-zero motion,
+  // skip newmv if the motion vector is (0, 0), and color is not set.
+  if (this_mode == NEWMV && cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN &&
+      cpi->svc.spatial_layer_id == 0 && cpi->sf.rt_sf.source_metrics_sb_nonrd) {
+    if (search_state->frame_mv[this_mode][ref_frame].as_int == 0 &&
+        x->content_state_sb.source_sad_nonrd != kZeroSad &&
+        ((x->color_sensitivity[0] == 0 && x->color_sensitivity[1] == 0) ||
+         cpi->rc.high_source_sad) &&
+        x->source_variance == 0)
+      return true;
+  }
+
+  mi->mode = this_mode;
+  mi->mv[0].as_int = search_state->frame_mv[this_mode][ref_frame].as_int;
+  mi->mv[1].as_int = 0;
+  if (comp_pred)
+    mi->mv[1].as_int = search_state->frame_mv[this_mode][ref_frame2].as_int;
+
+  if (reuse_inter_pred) {
+    if (!*this_mode_pred) {
+      *this_mode_pred = &tmp_buffer[3];
+    } else {
+      *this_mode_pred = &tmp_buffer[get_pred_buffer(tmp_buffer, 3)];
+      pd->dst.buf = (*this_mode_pred)->data;
+      pd->dst.stride = bw;
+    }
+  }
+
+  if (idx == 0 && !skip_pred_mv) {
+    // Set color sensitivity on first tested mode only.
+    // Use y-sad already computed in find_predictors: take the sad with motion
+    // vector closest to 0; the uv-sad computed below in set_color_sensitivity
+    // is for zeromv.
+    // For screen: first check if golden reference is being used, if so,
+    // force color_sensitivity on if the color sensitivity for sb_g is on.
+    if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN &&
+        search_state->use_ref_frame_mask[GOLDEN_FRAME]) {
+      if (x->color_sensitivity_sb_g[0] == 1) x->color_sensitivity[0] = 1;
+      if (x->color_sensitivity_sb_g[1] == 1) x->color_sensitivity[1] = 1;
+    } else {
+      int y_sad = x->pred_mv0_sad[LAST_FRAME];
+      if (x->pred_mv1_sad[LAST_FRAME] != INT_MAX &&
+          (abs(search_state->frame_mv[NEARMV][LAST_FRAME].as_mv.col) +
+           abs(search_state->frame_mv[NEARMV][LAST_FRAME].as_mv.row)) <
+              (abs(search_state->frame_mv[NEARESTMV][LAST_FRAME].as_mv.col) +
+               abs(search_state->frame_mv[NEARESTMV][LAST_FRAME].as_mv.row)))
+        y_sad = x->pred_mv1_sad[LAST_FRAME];
+      set_color_sensitivity(cpi, x, bsize, y_sad, x->source_variance,
+                            search_state->yv12_mb[LAST_FRAME]);
+    }
+  }
+
+  mi->motion_mode = SIMPLE_TRANSLATION;
+#if !CONFIG_REALTIME_ONLY
+  if (cpi->oxcf.motion_mode_cfg.allow_warped_motion) {
+    calc_num_proj_ref(cpi, x, mi);
+  }
+#endif
+  // set variance threshold for compound more pruning
+  if (cpi->sf.rt_sf.prune_compoundmode_with_singlecompound_var && comp_pred &&
+      use_model_yrd_large) {
+    const PREDICTION_MODE single_mode0 = compound_ref0_mode(this_mode);
+    const PREDICTION_MODE single_mode1 = compound_ref1_mode(this_mode);
+    var_threshold =
+        AOMMIN(var_threshold,
+               search_state->vars[INTER_OFFSET(single_mode0)][ref_frame]);
+    var_threshold =
+        AOMMIN(var_threshold,
+               search_state->vars[INTER_OFFSET(single_mode1)][ref_frame2]);
+  }
+
+  // decide interpolation filter, build prediction signal, get sse
+  const bool is_mv_subpel =
+      (mi->mv[0].as_mv.row & 0x07) || (mi->mv[0].as_mv.col & 0x07);
+  const bool enable_filt_search_this_mode =
+      (filter_search_enabled_blk == 2)
+          ? true
+          : (filter_search_enabled_blk && !force_mv_inter_layer && !comp_pred &&
+             (ref_frame == LAST_FRAME || !x->nonrd_prune_ref_frame_search));
+  if (is_mv_subpel && enable_filt_search_this_mode) {
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_start(&ms_stat.timer2);
+#endif
+    search_filter_ref(cpi, x, &search_state->this_rdc, &inter_pred_params_sr,
+                      mi_row, mi_col, tmp_buffer, bsize, reuse_inter_pred,
+                      this_mode_pred, &this_early_term, &var,
+                      use_model_yrd_large, search_state->best_pickmode.best_sse,
+                      comp_pred);
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_mark(&ms_stat.timer2);
+    ms_stat.ifs_time[bsize][this_mode] +=
+        aom_usec_timer_elapsed(&ms_stat.timer2);
+#endif
+#if !CONFIG_REALTIME_ONLY
+  } else if (cpi->oxcf.motion_mode_cfg.allow_warped_motion &&
+             this_mode == NEWMV) {
+    search_motion_mode(cpi, x, &search_state->this_rdc, mi_row, mi_col, bsize,
+                       &this_early_term, use_model_yrd_large, &rate_mv,
+                       search_state->best_pickmode.best_sse);
+    if (this_mode == NEWMV) {
+      search_state->frame_mv[this_mode][ref_frame] = mi->mv[0];
+    }
+#endif
+  } else {
+    mi->interp_filters =
+        (filter_ref == SWITCHABLE)
+            ? av1_broadcast_interp_filter(default_interp_filter)
+            : av1_broadcast_interp_filter(filter_ref);
+    if (force_mv_inter_layer)
+      mi->interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
+
+    // If it is sub-pel motion and cb_pred_filter_search is enabled, select
+    // the pre-decided filter
+    if (is_mv_subpel && cb_pred_filter_search)
+      mi->interp_filters = av1_broadcast_interp_filter(filt_select);
+
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_start(&ms_stat.timer2);
+#endif
+    if (!comp_pred) {
+      SubpelParams subpel_params;
+      // Initialize inter mode level params for single reference mode.
+      init_inter_mode_params(&mi->mv[0].as_mv, &inter_pred_params_sr,
+                             &subpel_params, xd->block_ref_scale_factors[0],
+                             pd->pre->width, pd->pre->height);
+      av1_enc_build_inter_predictor_y_nonrd(xd, &inter_pred_params_sr,
+                                            &subpel_params);
+    } else {
+      av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0, 0);
+    }
+
+    if (use_model_yrd_large) {
+      model_skip_for_sb_y_large(cpi, bsize, mi_row, mi_col, x, xd,
+                                &search_state->this_rdc, &this_early_term, 0,
+                                search_state->best_pickmode.best_sse, &var,
+                                var_threshold);
+    } else {
+      model_rd_for_sb_y(cpi, bsize, x, xd, &search_state->this_rdc, &var, 0,
+                        &this_early_term);
+    }
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_mark(&ms_stat.timer2);
+    ms_stat.model_rd_time[bsize][this_mode] +=
+        aom_usec_timer_elapsed(&ms_stat.timer2);
+#endif
+  }
+
+  // update variance for single mode
+  if (!comp_pred) {
+    search_state->vars[INTER_OFFSET(this_mode)][ref_frame] = var;
+    if (search_state->frame_mv[this_mode][ref_frame].as_int == 0) {
+      search_state->vars[INTER_OFFSET(GLOBALMV)][ref_frame] = var;
+    }
+  }
+  // prune compound mode based on single mode var threshold
+  if (comp_pred && var > var_threshold) {
+    if (reuse_inter_pred) free_pred_buffer(*this_mode_pred);
+    return true;
+  }
+
+  if (ref_frame == LAST_FRAME &&
+      search_state->frame_mv[this_mode][ref_frame].as_int == 0) {
+    *sse_zeromv_norm = (unsigned int)(search_state->this_rdc.sse >>
+                                      (b_width_log2_lookup[bsize] +
+                                       b_height_log2_lookup[bsize]));
+  }
+
+  if (cpi->sf.rt_sf.sse_early_term_inter_search &&
+      early_term_inter_search_with_sse(
+          cpi->sf.rt_sf.sse_early_term_inter_search, bsize,
+          search_state->this_rdc.sse, search_state->best_pickmode.best_sse,
+          this_mode)) {
+    if (reuse_inter_pred) free_pred_buffer(*this_mode_pred);
+    return true;
+  }
+
+#if COLLECT_PICK_MODE_STAT
+  ms_stat.num_nonskipped_searches[bsize][this_mode]++;
+#endif
+
+  const int skip_ctx = av1_get_skip_txfm_context(xd);
+  const int skip_txfm_cost = mode_costs->skip_txfm_cost[skip_ctx][1];
+  const int no_skip_txfm_cost = mode_costs->skip_txfm_cost[skip_ctx][0];
+  const int64_t sse_y = search_state->this_rdc.sse;
+
+  if (this_early_term) {
+    search_state->this_rdc.skip_txfm = 1;
+    search_state->this_rdc.rate = skip_txfm_cost;
+    search_state->this_rdc.dist = search_state->this_rdc.sse << 4;
+  } else {
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_start(&ms_stat.timer2);
+#endif
+    block_yrd(x, &search_state->this_rdc, &is_skippable, bsize, mi->tx_size, 1);
+    if (search_state->this_rdc.skip_txfm ||
+        RDCOST(x->rdmult, search_state->this_rdc.rate,
+               search_state->this_rdc.dist) >=
+            RDCOST(x->rdmult, 0, search_state->this_rdc.sse)) {
+      if (!search_state->this_rdc.skip_txfm) {
+        // Need to store "real" rdc for possible future use if UV rdc
+        // disallows tx skip
+        nonskip_rdc = search_state->this_rdc;
+        nonskip_rdc.rate += no_skip_txfm_cost;
+      }
+      search_state->this_rdc.rate = skip_txfm_cost;
+      search_state->this_rdc.skip_txfm = 1;
+      search_state->this_rdc.dist = search_state->this_rdc.sse;
+    } else {
+      search_state->this_rdc.rate += no_skip_txfm_cost;
+    }
+    if ((x->color_sensitivity[0] || x->color_sensitivity[1])) {
+      RD_STATS rdc_uv;
+      const BLOCK_SIZE uv_bsize = get_plane_block_size(
+          bsize, xd->plane[1].subsampling_x, xd->plane[1].subsampling_y);
+      if (x->color_sensitivity[0]) {
+        av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
+                                      AOM_PLANE_U, AOM_PLANE_U);
+      }
+      if (x->color_sensitivity[1]) {
+        av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
+                                      AOM_PLANE_V, AOM_PLANE_V);
+      }
+      const int64_t sse_uv =
+          model_rd_for_sb_uv(cpi, uv_bsize, x, xd, &rdc_uv, 1, 2);
+      search_state->this_rdc.sse += sse_uv;
+      // Restore Y rdc if UV rdc disallows txfm skip
+      if (search_state->this_rdc.skip_txfm && !rdc_uv.skip_txfm &&
+          nonskip_rdc.rate != INT_MAX)
+        search_state->this_rdc = nonskip_rdc;
+      if (!comp_pred) {
+        search_state->uv_dist[INTER_OFFSET(this_mode)][ref_frame] = rdc_uv.dist;
+      }
+      search_state->this_rdc.rate += rdc_uv.rate;
+      search_state->this_rdc.dist += rdc_uv.dist;
+      search_state->this_rdc.skip_txfm =
+          search_state->this_rdc.skip_txfm && rdc_uv.skip_txfm;
+    }
+#if COLLECT_PICK_MODE_STAT
+    aom_usec_timer_mark(&ms_stat.timer2);
+    ms_stat.txfm_time[bsize][this_mode] +=
+        aom_usec_timer_elapsed(&ms_stat.timer2);
+#endif
+  }
+
+  this_best_mode = this_mode;
+  // TODO(kyslov) account for UV prediction cost
+  search_state->this_rdc.rate += rate_mv;
+  if (comp_pred) {
+    const int16_t mode_ctx =
+        av1_mode_context_analyzer(mbmi_ext->mode_context, mi->ref_frame);
+    search_state->this_rdc.rate += cost_mv_ref(mode_costs, this_mode, mode_ctx);
+  } else {
+    // If the current mode has zeromv but is not GLOBALMV, compare the rate
+    // cost. If GLOBALMV is cheaper, use GLOBALMV instead.
+    if (this_mode != GLOBALMV &&
+        search_state->frame_mv[this_mode][ref_frame].as_int ==
+            search_state->frame_mv[GLOBALMV][ref_frame].as_int) {
+      if (is_globalmv_better(this_mode, ref_frame, rate_mv, mode_costs,
+                             search_state->single_inter_mode_costs, mbmi_ext)) {
+        this_best_mode = GLOBALMV;
+      }
+    }
+
+    search_state->this_rdc.rate +=
+        search_state
+            ->single_inter_mode_costs[INTER_OFFSET(this_best_mode)][ref_frame];
+  }
+
+  if (!comp_pred && search_state->frame_mv[this_mode][ref_frame].as_int == 0 &&
+      var < UINT_MAX) {
+    search_state->vars[INTER_OFFSET(GLOBALMV)][ref_frame] = var;
+  }
+
+  search_state->this_rdc.rate += search_state->ref_costs_single[ref_frame];
+
+  search_state->this_rdc.rdcost = RDCOST(x->rdmult, search_state->this_rdc.rate,
+                                         search_state->this_rdc.dist);
+  if (cpi->oxcf.rc_cfg.mode == AOM_CBR && !comp_pred) {
+    newmv_diff_bias(xd, this_best_mode, &search_state->this_rdc, bsize,
+                    search_state->frame_mv[this_best_mode][ref_frame].as_mv.row,
+                    search_state->frame_mv[this_best_mode][ref_frame].as_mv.col,
+                    cpi->speed, x->source_variance, x->content_state_sb);
+  }
+
+#if CONFIG_AV1_TEMPORAL_DENOISING
+  if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc_pickmode &&
+      cpi->denoiser.denoising_level > kDenLowLow) {
+    av1_denoiser_update_frame_stats(mi, sse_y, this_mode, ctx);
+    // Keep track of zero_last cost.
+    if (ref_frame == LAST_FRAME &&
+        search_state->frame_mv[this_mode][ref_frame].as_int == 0)
+      *zero_last_cost_orig = search_state->this_rdc.rdcost;
+  }
+#else
+  (void)(sse_y);
+#endif
+
+  search_state->mode_checked[this_mode][ref_frame] = 1;
+  search_state->mode_checked[this_best_mode][ref_frame] = 1;
+
+  if (*check_globalmv) {
+    int32_t abs_mv =
+        abs(search_state->frame_mv[this_best_mode][ref_frame].as_mv.row) +
+        abs(search_state->frame_mv[this_best_mode][ref_frame].as_mv.col);
+    // Early exit check: if the magnitude of this_best_mode's mv is small
+    // enough, we skip GLOBALMV check in the next loop iteration.
+    if (abs_mv < 2) {
+      *check_globalmv = false;
+    }
+  }
+#if COLLECT_PICK_MODE_STAT
+  aom_usec_timer_mark(&ms_stat.timer1);
+  ms_stat.nonskipped_search_times[bsize][this_mode] +=
+      aom_usec_timer_elapsed(&ms_stat.timer1);
+#endif
+
+  if (search_state->this_rdc.rdcost < search_state->best_rdc.rdcost) {
+    search_state->best_rdc = search_state->this_rdc;
+    *best_early_term = this_early_term;
+    search_state->best_pickmode.best_sse = sse_y;
+    search_state->best_pickmode.best_mode = this_best_mode;
+    search_state->best_pickmode.best_motion_mode = mi->motion_mode;
+    search_state->best_pickmode.wm_params = mi->wm_params;
+    search_state->best_pickmode.num_proj_ref = mi->num_proj_ref;
+    search_state->best_pickmode.best_pred_filter = mi->interp_filters;
+    search_state->best_pickmode.best_tx_size = mi->tx_size;
+    search_state->best_pickmode.best_ref_frame = ref_frame;
+    search_state->best_pickmode.best_second_ref_frame = ref_frame2;
+    search_state->best_pickmode.best_mode_skip_txfm =
+        search_state->this_rdc.skip_txfm;
+    search_state->best_pickmode.best_mode_initial_skip_flag =
+        (nonskip_rdc.rate == INT_MAX && search_state->this_rdc.skip_txfm);
+    if (!search_state->best_pickmode.best_mode_skip_txfm) {
+      memcpy(search_state->best_pickmode.blk_skip, txfm_info->blk_skip,
+             sizeof(txfm_info->blk_skip[0]) * num_8x8_blocks);
+    }
+
+    // This is needed for the compound modes.
+    search_state->frame_mv_best[this_best_mode][ref_frame].as_int =
+        search_state->frame_mv[this_best_mode][ref_frame].as_int;
+    if (ref_frame2 > NONE_FRAME) {
+      search_state->frame_mv_best[this_best_mode][ref_frame2].as_int =
+          search_state->frame_mv[this_best_mode][ref_frame2].as_int;
+    }
+
+    if (reuse_inter_pred) {
+      free_pred_buffer(search_state->best_pickmode.best_pred);
+      search_state->best_pickmode.best_pred = *this_mode_pred;
+    }
+  } else {
+    if (reuse_inter_pred) free_pred_buffer(*this_mode_pred);
+  }
+
+  if (*best_early_term && (idx > 0 || cpi->sf.rt_sf.nonrd_aggressive_skip)) {
+    txfm_info->skip_txfm = 1;
+    return false;
+  }
+  return true;
+}
+
 void av1_nonrd_pick_inter_mode_sb(AV1_COMP *cpi, TileDataEnc *tile_data,
                                   MACROBLOCK *x, RD_STATS *rd_cost,
                                   BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx) {
@@ -3554,8 +3984,6 @@
   MB_MODE_INFO *const mi = xd->mi[0];
   struct macroblockd_plane *const pd = &xd->plane[0];
   const MB_MODE_INFO_EXT *const mbmi_ext = &x->mbmi_ext;
-  const InterpFilter filter_ref = cm->features.interp_filter;
-  const InterpFilter default_interp_filter = EIGHTTAP_REGULAR;
   MV_REFERENCE_FRAME ref_frame, ref_frame2;
   const unsigned char segment_id = mi->segment_id;
   int best_early_term = 0;
@@ -3703,17 +4131,8 @@
       break;
     }
 
-    int rate_mv = 0;
-    int is_skippable;
-    int this_early_term = 0;
-    int skip_this_mv = 0;
     int comp_pred = 0;
-    unsigned int var = UINT_MAX;
     PREDICTION_MODE this_mode;
-    RD_STATS nonskip_rdc;
-    av1_invalid_rd_stats(&nonskip_rdc);
-    memset(txfm_info->blk_skip, 0,
-           sizeof(txfm_info->blk_skip[0]) * num_8x8_blocks);
 
     // Check the inter mode can be skipped based on mode statistics and speed
     // features settings.
@@ -3734,395 +4153,20 @@
     mi->ref_frame[0] = ref_frame;
     mi->ref_frame[1] = ref_frame2;
     set_ref_ptrs(cm, xd, ref_frame, ref_frame2);
+    memset(txfm_info->blk_skip, 0,
+           sizeof(txfm_info->blk_skip[0]) * num_8x8_blocks);
 
-    if (this_mode == NEWMV && !force_mv_inter_layer) {
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_start(&ms_stat.timer2);
-#endif
-      const bool skip_newmv = search_new_mv(
-          cpi, x, search_state.frame_mv, ref_frame, gf_temporal_ref, bsize,
-          mi_row, mi_col, &rate_mv, &search_state.best_rdc);
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_mark(&ms_stat.timer2);
-      ms_stat.ms_time[bsize][this_mode] +=
-          aom_usec_timer_elapsed(&ms_stat.timer2);
-#endif
-      if (skip_newmv) {
-        continue;
-      }
-    }
-
-    for (PREDICTION_MODE inter_mv_mode = NEARESTMV; inter_mv_mode <= NEWMV;
-         inter_mv_mode++) {
-      if (inter_mv_mode == this_mode) continue;
-      if (!comp_pred && search_state.mode_checked[inter_mv_mode][ref_frame] &&
-          search_state.frame_mv[this_mode][ref_frame].as_int ==
-              search_state.frame_mv[inter_mv_mode][ref_frame].as_int) {
-        skip_this_mv = 1;
-        break;
-      }
-    }
-
-    if (skip_this_mv && !comp_pred) continue;
-
-    // For screen: for spatially flat blocks with non-zero motion,
-    // skip newmv if the motion vector is (0, 0), and color is not set.
-    if (this_mode == NEWMV &&
-        cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN &&
-        cpi->svc.spatial_layer_id == 0 &&
-        cpi->sf.rt_sf.source_metrics_sb_nonrd) {
-      if (search_state.frame_mv[this_mode][ref_frame].as_int == 0 &&
-          x->content_state_sb.source_sad_nonrd != kZeroSad &&
-          ((x->color_sensitivity[0] == 0 && x->color_sensitivity[1] == 0) ||
-           cpi->rc.high_source_sad) &&
-          x->source_variance == 0)
-        continue;
-    }
-
-    mi->mode = this_mode;
-    mi->mv[0].as_int = search_state.frame_mv[this_mode][ref_frame].as_int;
-    mi->mv[1].as_int = 0;
-    if (comp_pred)
-      mi->mv[1].as_int = search_state.frame_mv[this_mode][ref_frame2].as_int;
-
-    if (reuse_inter_pred) {
-      if (!this_mode_pred) {
-        this_mode_pred = &tmp_buffer[3];
-      } else {
-        this_mode_pred = &tmp_buffer[get_pred_buffer(tmp_buffer, 3)];
-        pd->dst.buf = this_mode_pred->data;
-        pd->dst.stride = bw;
-      }
-    }
-
-    if (idx == 0 && !skip_pred_mv) {
-      // Set color sensitivity on first tested mode only.
-      // Use y-sad already computed in find_predictors: take the sad with motion
-      // vector closest to 0; the uv-sad computed below in set_color_sensitivity
-      // is for zeromv.
-      // For screen: first check if golden reference is being used, if so,
-      // force color_sensitivity on if the color sensitivity for sb_g is on.
-      if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN &&
-          search_state.use_ref_frame_mask[GOLDEN_FRAME]) {
-        if (x->color_sensitivity_sb_g[0] == 1) x->color_sensitivity[0] = 1;
-        if (x->color_sensitivity_sb_g[1] == 1) x->color_sensitivity[1] = 1;
-      } else {
-        int y_sad = x->pred_mv0_sad[LAST_FRAME];
-        if (x->pred_mv1_sad[LAST_FRAME] != INT_MAX &&
-            (abs(search_state.frame_mv[NEARMV][LAST_FRAME].as_mv.col) +
-             abs(search_state.frame_mv[NEARMV][LAST_FRAME].as_mv.row)) <
-                (abs(search_state.frame_mv[NEARESTMV][LAST_FRAME].as_mv.col) +
-                 abs(search_state.frame_mv[NEARESTMV][LAST_FRAME].as_mv.row)))
-          y_sad = x->pred_mv1_sad[LAST_FRAME];
-        set_color_sensitivity(cpi, x, bsize, y_sad, x->source_variance,
-                              search_state.yv12_mb[LAST_FRAME]);
-      }
-    }
-    mi->motion_mode = SIMPLE_TRANSLATION;
-#if !CONFIG_REALTIME_ONLY
-    if (cpi->oxcf.motion_mode_cfg.allow_warped_motion) {
-      calc_num_proj_ref(cpi, x, mi);
-    }
-#endif
-    // set variance threshold for compound more pruning
-    unsigned int var_threshold = UINT_MAX;
-    if (cpi->sf.rt_sf.prune_compoundmode_with_singlecompound_var && comp_pred &&
-        use_model_yrd_large) {
-      const PREDICTION_MODE single_mode0 = compound_ref0_mode(this_mode);
-      const PREDICTION_MODE single_mode1 = compound_ref1_mode(this_mode);
-      var_threshold =
-          AOMMIN(var_threshold,
-                 search_state.vars[INTER_OFFSET(single_mode0)][ref_frame]);
-      var_threshold =
-          AOMMIN(var_threshold,
-                 search_state.vars[INTER_OFFSET(single_mode1)][ref_frame2]);
-    }
-    // decide interpolation filter, build prediction signal, get sse
-    const bool is_mv_subpel =
-        (mi->mv[0].as_mv.row & 0x07) || (mi->mv[0].as_mv.col & 0x07);
-    const bool enable_filt_search_this_mode =
-        (filter_search_enabled_blk == 2)
-            ? true
-            : (filter_search_enabled_blk && !force_mv_inter_layer &&
-               !comp_pred &&
-               (ref_frame == LAST_FRAME || !x->nonrd_prune_ref_frame_search));
-    if (is_mv_subpel && enable_filt_search_this_mode) {
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_start(&ms_stat.timer2);
-#endif
-      search_filter_ref(cpi, x, &search_state.this_rdc, &inter_pred_params_sr,
-                        mi_row, mi_col, tmp_buffer, bsize, reuse_inter_pred,
-                        &this_mode_pred, &this_early_term, &var,
-                        use_model_yrd_large,
-                        search_state.best_pickmode.best_sse, comp_pred);
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_mark(&ms_stat.timer2);
-      ms_stat.ifs_time[bsize][this_mode] +=
-          aom_usec_timer_elapsed(&ms_stat.timer2);
-#endif
-#if !CONFIG_REALTIME_ONLY
-    } else if (cpi->oxcf.motion_mode_cfg.allow_warped_motion &&
-               this_mode == NEWMV) {
-      search_motion_mode(cpi, x, &search_state.this_rdc, mi_row, mi_col, bsize,
-                         &this_early_term, use_model_yrd_large, &rate_mv,
-                         search_state.best_pickmode.best_sse);
-      if (this_mode == NEWMV) {
-        search_state.frame_mv[this_mode][ref_frame] = mi->mv[0];
-      }
-#endif
-    } else {
-      mi->interp_filters =
-          (filter_ref == SWITCHABLE)
-              ? av1_broadcast_interp_filter(default_interp_filter)
-              : av1_broadcast_interp_filter(filter_ref);
-      if (force_mv_inter_layer)
-        mi->interp_filters = av1_broadcast_interp_filter(EIGHTTAP_REGULAR);
-
-      // If it is sub-pel motion and cb_pred_filter_search is enabled, select
-      // the pre-decided filter
-      if (is_mv_subpel && cb_pred_filter_search)
-        mi->interp_filters = av1_broadcast_interp_filter(filt_select);
-
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_start(&ms_stat.timer2);
-#endif
-      if (!comp_pred) {
-        SubpelParams subpel_params;
-        // Initialize inter mode level params for single reference mode.
-        init_inter_mode_params(&mi->mv[0].as_mv, &inter_pred_params_sr,
-                               &subpel_params, xd->block_ref_scale_factors[0],
-                               pd->pre->width, pd->pre->height);
-        av1_enc_build_inter_predictor_y_nonrd(xd, &inter_pred_params_sr,
-                                              &subpel_params);
-      } else {
-        av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize, 0,
-                                      0);
-      }
-
-      if (use_model_yrd_large) {
-        model_skip_for_sb_y_large(cpi, bsize, mi_row, mi_col, x, xd,
-                                  &search_state.this_rdc, &this_early_term, 0,
-                                  search_state.best_pickmode.best_sse, &var,
-                                  var_threshold);
-      } else {
-        model_rd_for_sb_y(cpi, bsize, x, xd, &search_state.this_rdc, &var, 0,
-                          &this_early_term);
-      }
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_mark(&ms_stat.timer2);
-      ms_stat.model_rd_time[bsize][this_mode] +=
-          aom_usec_timer_elapsed(&ms_stat.timer2);
-#endif
-    }
-    // update variance for single mode
-    if (!comp_pred) {
-      search_state.vars[INTER_OFFSET(this_mode)][ref_frame] = var;
-      if (search_state.frame_mv[this_mode][ref_frame].as_int == 0) {
-        search_state.vars[INTER_OFFSET(GLOBALMV)][ref_frame] = var;
-      }
-    }
-    // prune compound mode based on single mode var threshold
-    if (comp_pred && var > var_threshold) {
-      if (reuse_inter_pred) free_pred_buffer(this_mode_pred);
-      continue;
-    }
-
-    if (ref_frame == LAST_FRAME &&
-        search_state.frame_mv[this_mode][ref_frame].as_int == 0) {
-      sse_zeromv_norm = (unsigned int)(search_state.this_rdc.sse >>
-                                       (b_width_log2_lookup[bsize] +
-                                        b_height_log2_lookup[bsize]));
-    }
-
-    if (cpi->sf.rt_sf.sse_early_term_inter_search &&
-        early_term_inter_search_with_sse(
-            cpi->sf.rt_sf.sse_early_term_inter_search, bsize,
-            search_state.this_rdc.sse, search_state.best_pickmode.best_sse,
-            this_mode)) {
-      if (reuse_inter_pred) free_pred_buffer(this_mode_pred);
-      continue;
-    }
-
-#if COLLECT_PICK_MODE_STAT
-    ms_stat.num_nonskipped_searches[bsize][this_mode]++;
-#endif
-
-    const int skip_ctx = av1_get_skip_txfm_context(xd);
-    const int skip_txfm_cost = mode_costs->skip_txfm_cost[skip_ctx][1];
-    const int no_skip_txfm_cost = mode_costs->skip_txfm_cost[skip_ctx][0];
-    const int64_t sse_y = search_state.this_rdc.sse;
-    if (this_early_term) {
-      search_state.this_rdc.skip_txfm = 1;
-      search_state.this_rdc.rate = skip_txfm_cost;
-      search_state.this_rdc.dist = search_state.this_rdc.sse << 4;
-    } else {
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_start(&ms_stat.timer2);
-#endif
-      block_yrd(x, &search_state.this_rdc, &is_skippable, bsize, mi->tx_size,
-                1);
-      if (search_state.this_rdc.skip_txfm ||
-          RDCOST(x->rdmult, search_state.this_rdc.rate,
-                 search_state.this_rdc.dist) >=
-              RDCOST(x->rdmult, 0, search_state.this_rdc.sse)) {
-        if (!search_state.this_rdc.skip_txfm) {
-          // Need to store "real" rdc for possible future use if UV rdc
-          // disallows tx skip
-          nonskip_rdc = search_state.this_rdc;
-          nonskip_rdc.rate += no_skip_txfm_cost;
-        }
-        search_state.this_rdc.rate = skip_txfm_cost;
-        search_state.this_rdc.skip_txfm = 1;
-        search_state.this_rdc.dist = search_state.this_rdc.sse;
-      } else {
-        search_state.this_rdc.rate += no_skip_txfm_cost;
-      }
-      if ((x->color_sensitivity[0] || x->color_sensitivity[1])) {
-        RD_STATS rdc_uv;
-        const BLOCK_SIZE uv_bsize = get_plane_block_size(
-            bsize, xd->plane[1].subsampling_x, xd->plane[1].subsampling_y);
-        if (x->color_sensitivity[0]) {
-          av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
-                                        AOM_PLANE_U, AOM_PLANE_U);
-        }
-        if (x->color_sensitivity[1]) {
-          av1_enc_build_inter_predictor(cm, xd, mi_row, mi_col, NULL, bsize,
-                                        AOM_PLANE_V, AOM_PLANE_V);
-        }
-        const int64_t sse_uv =
-            model_rd_for_sb_uv(cpi, uv_bsize, x, xd, &rdc_uv, 1, 2);
-        search_state.this_rdc.sse += sse_uv;
-        // Restore Y rdc if UV rdc disallows txfm skip
-        if (search_state.this_rdc.skip_txfm && !rdc_uv.skip_txfm &&
-            nonskip_rdc.rate != INT_MAX)
-          search_state.this_rdc = nonskip_rdc;
-        if (!comp_pred) {
-          search_state.uv_dist[INTER_OFFSET(this_mode)][ref_frame] =
-              rdc_uv.dist;
-        }
-        search_state.this_rdc.rate += rdc_uv.rate;
-        search_state.this_rdc.dist += rdc_uv.dist;
-        search_state.this_rdc.skip_txfm =
-            search_state.this_rdc.skip_txfm && rdc_uv.skip_txfm;
-      }
-#if COLLECT_PICK_MODE_STAT
-      aom_usec_timer_mark(&ms_stat.timer2);
-      ms_stat.txfm_time[bsize][this_mode] +=
-          aom_usec_timer_elapsed(&ms_stat.timer2);
-#endif
-    }
-    PREDICTION_MODE this_best_mode = this_mode;
-
-    // TODO(kyslov) account for UV prediction cost
-    search_state.this_rdc.rate += rate_mv;
-    if (comp_pred) {
-      const int16_t mode_ctx =
-          av1_mode_context_analyzer(mbmi_ext->mode_context, mi->ref_frame);
-      search_state.this_rdc.rate +=
-          cost_mv_ref(mode_costs, this_mode, mode_ctx);
-    } else {
-      // If the current mode has zeromv but is not GLOBALMV, compare the rate
-      // cost. If GLOBALMV is cheaper, use GLOBALMV instead.
-      if (this_mode != GLOBALMV &&
-          search_state.frame_mv[this_mode][ref_frame].as_int ==
-              search_state.frame_mv[GLOBALMV][ref_frame].as_int) {
-        if (is_globalmv_better(this_mode, ref_frame, rate_mv, mode_costs,
-                               search_state.single_inter_mode_costs,
-                               mbmi_ext)) {
-          this_best_mode = GLOBALMV;
-        }
-      }
-
-      search_state.this_rdc.rate +=
-          search_state
-              .single_inter_mode_costs[INTER_OFFSET(this_best_mode)][ref_frame];
-    }
-
-    if (!comp_pred && search_state.frame_mv[this_mode][ref_frame].as_int == 0 &&
-        var < UINT_MAX) {
-      search_state.vars[INTER_OFFSET(GLOBALMV)][ref_frame] = var;
-    }
-
-    search_state.this_rdc.rate += search_state.ref_costs_single[ref_frame];
-
-    search_state.this_rdc.rdcost = RDCOST(x->rdmult, search_state.this_rdc.rate,
-                                          search_state.this_rdc.dist);
-    if (cpi->oxcf.rc_cfg.mode == AOM_CBR && !comp_pred) {
-      newmv_diff_bias(
-          xd, this_best_mode, &search_state.this_rdc, bsize,
-          search_state.frame_mv[this_best_mode][ref_frame].as_mv.row,
-          search_state.frame_mv[this_best_mode][ref_frame].as_mv.col,
-          cpi->speed, x->source_variance, x->content_state_sb);
-    }
+    // Perform inter mode evaluation for non-rd
+    if (!handle_inter_mode_nonrd(
+            cpi, x, &search_state, ctx, &this_mode_pred, tmp_buffer,
+            inter_pred_params_sr, &best_early_term, &sse_zeromv_norm,
+            &check_globalmv,
 #if CONFIG_AV1_TEMPORAL_DENOISING
-    if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc_pickmode &&
-        cpi->denoiser.denoising_level > kDenLowLow) {
-      av1_denoiser_update_frame_stats(mi, sse_y, this_mode, ctx);
-      // Keep track of zero_last cost.
-      if (ref_frame == LAST_FRAME &&
-          search_state.frame_mv[this_mode][ref_frame].as_int == 0)
-        zero_last_cost_orig = search_state.this_rdc.rdcost;
-    }
-#else
-    (void)sse_y;
+            &zero_last_cost_orig, denoise_svc_pickmode,
 #endif
-
-    search_state.mode_checked[this_mode][ref_frame] = 1;
-    search_state.mode_checked[this_best_mode][ref_frame] = 1;
-
-    if (check_globalmv) {
-      int32_t abs_mv =
-          abs(search_state.frame_mv[this_best_mode][ref_frame].as_mv.row) +
-          abs(search_state.frame_mv[this_best_mode][ref_frame].as_mv.col);
-      // Early exit check: if the magnitude of this_best_mode's mv is small
-      // enough, we skip GLOBALMV check in the next loop iteration.
-      if (abs_mv < 2) {
-        check_globalmv = false;
-      }
-    }
-#if COLLECT_PICK_MODE_STAT
-    aom_usec_timer_mark(&ms_stat.timer1);
-    ms_stat.nonskipped_search_times[bsize][this_mode] +=
-        aom_usec_timer_elapsed(&ms_stat.timer1);
-#endif
-    if (search_state.this_rdc.rdcost < search_state.best_rdc.rdcost) {
-      search_state.best_rdc = search_state.this_rdc;
-      best_early_term = this_early_term;
-      search_state.best_pickmode.best_sse = sse_y;
-      search_state.best_pickmode.best_mode = this_best_mode;
-      search_state.best_pickmode.best_motion_mode = mi->motion_mode;
-      search_state.best_pickmode.wm_params = mi->wm_params;
-      search_state.best_pickmode.num_proj_ref = mi->num_proj_ref;
-      search_state.best_pickmode.best_pred_filter = mi->interp_filters;
-      search_state.best_pickmode.best_tx_size = mi->tx_size;
-      search_state.best_pickmode.best_ref_frame = ref_frame;
-      search_state.best_pickmode.best_second_ref_frame = ref_frame2;
-      search_state.best_pickmode.best_mode_skip_txfm =
-          search_state.this_rdc.skip_txfm;
-      search_state.best_pickmode.best_mode_initial_skip_flag =
-          (nonskip_rdc.rate == INT_MAX && search_state.this_rdc.skip_txfm);
-      if (!search_state.best_pickmode.best_mode_skip_txfm) {
-        memcpy(search_state.best_pickmode.blk_skip, txfm_info->blk_skip,
-               sizeof(txfm_info->blk_skip[0]) * num_8x8_blocks);
-      }
-
-      // This is needed for the compound modes.
-      search_state.frame_mv_best[this_best_mode][ref_frame].as_int =
-          search_state.frame_mv[this_best_mode][ref_frame].as_int;
-      if (ref_frame2 > NONE_FRAME) {
-        search_state.frame_mv_best[this_best_mode][ref_frame2].as_int =
-            search_state.frame_mv[this_best_mode][ref_frame2].as_int;
-      }
-
-      if (reuse_inter_pred) {
-        free_pred_buffer(search_state.best_pickmode.best_pred);
-        search_state.best_pickmode.best_pred = this_mode_pred;
-      }
-    } else {
-      if (reuse_inter_pred) free_pred_buffer(this_mode_pred);
-    }
-    if (best_early_term && (idx > 0 || cpi->sf.rt_sf.nonrd_aggressive_skip)) {
-      txfm_info->skip_txfm = 1;
+            idx, force_mv_inter_layer, comp_pred, skip_pred_mv, gf_temporal_ref,
+            use_model_yrd_large, filter_search_enabled_blk, bsize, this_mode,
+            filt_select, cb_pred_filter_search, reuse_inter_pred)) {
       break;
     }
   }