in media/libvpx/libvpx/vp9/encoder/vp9_pickmode.c [1695:2752]
void vp9_pick_inter_mode(VP9_COMP *cpi, MACROBLOCK *x, TileDataEnc *tile_data,
int mi_row, int mi_col, RD_COST *rd_cost,
BLOCK_SIZE bsize, PICK_MODE_CONTEXT *ctx) {
VP9_COMMON *const cm = &cpi->common;
SPEED_FEATURES *const sf = &cpi->sf;
SVC *const svc = &cpi->svc;
MACROBLOCKD *const xd = &x->e_mbd;
MODE_INFO *const mi = xd->mi[0];
struct macroblockd_plane *const pd = &xd->plane[0];
BEST_PICKMODE best_pickmode;
MV_REFERENCE_FRAME ref_frame;
MV_REFERENCE_FRAME usable_ref_frame, second_ref_frame;
int_mv frame_mv[MB_MODE_COUNT][MAX_REF_FRAMES];
uint8_t mode_checked[MB_MODE_COUNT][MAX_REF_FRAMES];
struct buf_2d yv12_mb[4][MAX_MB_PLANE] = { 0 };
RD_COST this_rdc, best_rdc;
// var_y and sse_y are saved to be used in skipping checking
unsigned int var_y = UINT_MAX;
unsigned int sse_y = UINT_MAX;
const int intra_cost_penalty =
vp9_get_intra_cost_penalty(cpi, bsize, cm->base_qindex, cm->y_dc_delta_q);
int64_t inter_mode_thresh =
RDCOST(x->rdmult, x->rddiv, intra_cost_penalty, 0);
const int *const rd_threshes = cpi->rd.threshes[mi->segment_id][bsize];
const int sb_row = mi_row >> MI_BLOCK_SIZE_LOG2;
int thresh_freq_fact_idx = (sb_row * BLOCK_SIZES + bsize) * MAX_MODES;
const int *const rd_thresh_freq_fact =
(cpi->sf.adaptive_rd_thresh_row_mt)
? &(tile_data->row_base_thresh_freq_fact[thresh_freq_fact_idx])
: tile_data->thresh_freq_fact[bsize];
#if CONFIG_VP9_TEMPORAL_DENOISING
const int denoise_recheck_zeromv = 1;
#endif
INTERP_FILTER filter_ref;
int pred_filter_search = cm->interp_filter == SWITCHABLE;
int const_motion[MAX_REF_FRAMES] = { 0 };
const int bh = num_4x4_blocks_high_lookup[bsize] << 2;
const int bw = num_4x4_blocks_wide_lookup[bsize] << 2;
// For speed 6, the result of interp filter is reused later in actual encoding
// process.
// tmp[3] points to dst buffer, and the other 3 point to allocated buffers.
PRED_BUFFER tmp[4];
DECLARE_ALIGNED(16, uint8_t, pred_buf[3 * 64 * 64] VPX_UNINITIALIZED);
#if CONFIG_VP9_HIGHBITDEPTH
DECLARE_ALIGNED(16, uint16_t, pred_buf_16[3 * 64 * 64] VPX_UNINITIALIZED);
#endif
struct buf_2d orig_dst = pd->dst;
PRED_BUFFER *this_mode_pred = NULL;
const int pixels_in_block = bh * bw;
int reuse_inter_pred = cpi->sf.reuse_inter_pred_sby && ctx->pred_pixel_ready;
int ref_frame_skip_mask = 0;
int idx;
int best_pred_sad = INT_MAX;
int best_early_term = 0;
int ref_frame_cost[MAX_REF_FRAMES];
int svc_force_zero_mode[3] = { 0 };
int perform_intra_pred = 1;
int use_golden_nonzeromv = 1;
int force_skip_low_temp_var = 0;
int skip_ref_find_pred[4] = { 0 };
unsigned int sse_zeromv_normalized = UINT_MAX;
unsigned int best_sse_sofar = UINT_MAX;
int gf_temporal_ref = 0;
int force_test_gf_zeromv = 0;
#if CONFIG_VP9_TEMPORAL_DENOISING
VP9_PICKMODE_CTX_DEN ctx_den;
int64_t zero_last_cost_orig = INT64_MAX;
int denoise_svc_pickmode = 1;
#endif
INTERP_FILTER filter_gf_svc = EIGHTTAP;
MV_REFERENCE_FRAME inter_layer_ref = GOLDEN_FRAME;
const struct segmentation *const seg = &cm->seg;
int comp_modes = 0;
int num_inter_modes = (cpi->use_svc) ? RT_INTER_MODES_SVC : RT_INTER_MODES;
int flag_svc_subpel = 0;
int svc_mv_col = 0;
int svc_mv_row = 0;
int no_scaling = 0;
int large_block = 0;
int use_model_yrd_large = 0;
unsigned int thresh_svc_skip_golden = 500;
unsigned int thresh_skip_golden = 500;
int force_smooth_filter = cpi->sf.force_smooth_interpol;
int scene_change_detected =
cpi->rc.high_source_sad ||
(cpi->use_svc && cpi->svc.high_source_sad_superframe);
init_best_pickmode(&best_pickmode);
x->encode_breakout = seg->enabled
? cpi->segment_encode_breakout[mi->segment_id]
: cpi->encode_breakout;
x->source_variance = UINT_MAX;
if (cpi->sf.default_interp_filter == BILINEAR) {
best_pickmode.best_pred_filter = BILINEAR;
filter_gf_svc = BILINEAR;
}
if (cpi->use_svc && svc->spatial_layer_id > 0) {
int layer =
LAYER_IDS_TO_IDX(svc->spatial_layer_id - 1, svc->temporal_layer_id,
svc->number_temporal_layers);
LAYER_CONTEXT *const lc = &svc->layer_context[layer];
if (lc->scaling_factor_num == lc->scaling_factor_den) no_scaling = 1;
}
if (svc->spatial_layer_id > 0 &&
(svc->high_source_sad_superframe || no_scaling))
thresh_svc_skip_golden = 0;
// Lower the skip threshold if lower spatial layer is better quality relative
// to current layer.
else if (svc->spatial_layer_id > 0 && cm->base_qindex > 150 &&
cm->base_qindex > svc->lower_layer_qindex + 15)
thresh_svc_skip_golden = 100;
// Increase skip threshold if lower spatial layer is lower quality relative
// to current layer.
else if (svc->spatial_layer_id > 0 && cm->base_qindex < 140 &&
cm->base_qindex < svc->lower_layer_qindex - 20)
thresh_svc_skip_golden = 1000;
if (!cpi->use_svc ||
(svc->use_gf_temporal_ref_current_layer &&
!svc->layer_context[svc->temporal_layer_id].is_key_frame)) {
struct scale_factors *const sf_last = &cm->frame_refs[LAST_FRAME - 1].sf;
struct scale_factors *const sf_golden =
&cm->frame_refs[GOLDEN_FRAME - 1].sf;
gf_temporal_ref = 1;
// For temporal long term prediction, check that the golden reference
// is same scale as last reference, otherwise disable.
if ((sf_last->x_scale_fp != sf_golden->x_scale_fp) ||
(sf_last->y_scale_fp != sf_golden->y_scale_fp)) {
gf_temporal_ref = 0;
} else {
if (cpi->rc.avg_frame_low_motion > 70)
thresh_svc_skip_golden = 500;
else
thresh_svc_skip_golden = 0;
}
}
init_ref_frame_cost(cm, xd, ref_frame_cost);
memset(&mode_checked[0][0], 0, MB_MODE_COUNT * MAX_REF_FRAMES);
if (reuse_inter_pred) {
int i;
for (i = 0; i < 3; i++) {
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth)
tmp[i].data = CONVERT_TO_BYTEPTR(&pred_buf_16[pixels_in_block * i]);
else
tmp[i].data = &pred_buf[pixels_in_block * i];
#else
tmp[i].data = &pred_buf[pixels_in_block * i];
#endif // CONFIG_VP9_HIGHBITDEPTH
tmp[i].stride = bw;
tmp[i].in_use = 0;
}
tmp[3].data = pd->dst.buf;
tmp[3].stride = pd->dst.stride;
tmp[3].in_use = 0;
}
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
x->skip = 0;
if (cpi->sf.cb_pred_filter_search) {
const int bsl = mi_width_log2_lookup[bsize];
pred_filter_search = cm->interp_filter == SWITCHABLE
? (((mi_row + mi_col) >> bsl) +
get_chessboard_index(cm->current_video_frame)) &
0x1
: 0;
}
// Instead of using vp9_get_pred_context_switchable_interp(xd) to assign
// filter_ref, we use a less strict condition on assigning filter_ref.
// This is to reduce the probabily of entering the flow of not assigning
// filter_ref and then skip filter search.
filter_ref = cm->interp_filter;
if (cpi->sf.default_interp_filter != BILINEAR) {
if (xd->above_mi && is_inter_block(xd->above_mi))
filter_ref = xd->above_mi->interp_filter;
else if (xd->left_mi && is_inter_block(xd->left_mi))
filter_ref = xd->left_mi->interp_filter;
}
// initialize mode decisions
vp9_rd_cost_reset(&best_rdc);
vp9_rd_cost_reset(rd_cost);
mi->sb_type = bsize;
mi->ref_frame[0] = NO_REF_FRAME;
mi->ref_frame[1] = NO_REF_FRAME;
mi->tx_size =
VPXMIN(max_txsize_lookup[bsize], tx_mode_to_biggest_tx_size[cm->tx_mode]);
if (sf->short_circuit_flat_blocks || sf->limit_newmv_early_exit) {
#if CONFIG_VP9_HIGHBITDEPTH
if (xd->cur_buf->flags & YV12_FLAG_HIGHBITDEPTH)
x->source_variance = vp9_high_get_sby_perpixel_variance(
cpi, &x->plane[0].src, bsize, xd->bd);
else
#endif // CONFIG_VP9_HIGHBITDEPTH
x->source_variance =
vp9_get_sby_perpixel_variance(cpi, &x->plane[0].src, bsize);
if (cpi->oxcf.content == VP9E_CONTENT_SCREEN &&
cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ && mi->segment_id > 0 &&
x->zero_temp_sad_source && x->source_variance == 0) {
mi->segment_id = 0;
vp9_init_plane_quantizers(cpi, x);
}
}
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0) {
if (cpi->use_svc) denoise_svc_pickmode = vp9_denoise_svc_non_key(cpi);
if (cpi->denoiser.denoising_level > kDenLowLow && denoise_svc_pickmode)
vp9_denoiser_reset_frame_stats(ctx);
}
#endif
if (cpi->rc.frames_since_golden == 0 && gf_temporal_ref &&
!cpi->rc.alt_ref_gf_group && !cpi->rc.last_frame_is_src_altref) {
usable_ref_frame = LAST_FRAME;
} else {
usable_ref_frame = GOLDEN_FRAME;
}
if (cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.rc_mode == VPX_VBR) {
if (cpi->rc.alt_ref_gf_group || cpi->rc.is_src_frame_alt_ref)
usable_ref_frame = ALTREF_FRAME;
if (cpi->rc.is_src_frame_alt_ref) {
skip_ref_find_pred[LAST_FRAME] = 1;
skip_ref_find_pred[GOLDEN_FRAME] = 1;
}
if (!cm->show_frame) {
if (cpi->rc.frames_since_key == 1) {
usable_ref_frame = LAST_FRAME;
skip_ref_find_pred[GOLDEN_FRAME] = 1;
skip_ref_find_pred[ALTREF_FRAME] = 1;
}
}
}
// For svc mode, on spatial_layer_id > 0: if the reference has different scale
// constrain the inter mode to only test zero motion.
if (cpi->use_svc && svc->force_zero_mode_spatial_ref &&
svc->spatial_layer_id > 0 && !gf_temporal_ref) {
if (cpi->ref_frame_flags & VP9_LAST_FLAG) {
struct scale_factors *const ref_sf = &cm->frame_refs[LAST_FRAME - 1].sf;
if (vp9_is_scaled(ref_sf)) {
svc_force_zero_mode[LAST_FRAME - 1] = 1;
inter_layer_ref = LAST_FRAME;
}
}
if (cpi->ref_frame_flags & VP9_GOLD_FLAG) {
struct scale_factors *const ref_sf = &cm->frame_refs[GOLDEN_FRAME - 1].sf;
if (vp9_is_scaled(ref_sf)) {
svc_force_zero_mode[GOLDEN_FRAME - 1] = 1;
inter_layer_ref = GOLDEN_FRAME;
}
}
}
if (cpi->sf.short_circuit_low_temp_var) {
force_skip_low_temp_var =
get_force_skip_low_temp_var(&x->variance_low[0], mi_row, mi_col, bsize);
// If force_skip_low_temp_var is set, and for short circuit mode = 1 and 3,
// skip golden reference.
if ((cpi->sf.short_circuit_low_temp_var == 1 ||
cpi->sf.short_circuit_low_temp_var == 3) &&
force_skip_low_temp_var) {
usable_ref_frame = LAST_FRAME;
}
}
if (sf->disable_golden_ref && (x->content_state_sb != kVeryHighSad ||
cpi->rc.avg_frame_low_motion < 60))
usable_ref_frame = LAST_FRAME;
if (!((cpi->ref_frame_flags & VP9_GOLD_FLAG) &&
!svc_force_zero_mode[GOLDEN_FRAME - 1] && !force_skip_low_temp_var))
use_golden_nonzeromv = 0;
if (cpi->oxcf.speed >= 8 && !cpi->use_svc &&
((cpi->rc.frames_since_golden + 1) < x->last_sb_high_content ||
x->last_sb_high_content > 40 || cpi->rc.frames_since_golden > 120))
usable_ref_frame = LAST_FRAME;
// Compound prediction modes: (0,0) on LAST/GOLDEN and ARF.
if (cm->reference_mode == REFERENCE_MODE_SELECT &&
cpi->sf.use_compound_nonrd_pickmode && usable_ref_frame == ALTREF_FRAME)
comp_modes = 2;
// If the segment reference frame feature is enabled and it's set to GOLDEN
// reference, then make sure we don't skip checking GOLDEN, this is to
// prevent possibility of not picking any mode.
if (segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME) &&
get_segdata(seg, mi->segment_id, SEG_LVL_REF_FRAME) == GOLDEN_FRAME) {
usable_ref_frame = GOLDEN_FRAME;
skip_ref_find_pred[GOLDEN_FRAME] = 0;
thresh_svc_skip_golden = 0;
}
for (ref_frame = LAST_FRAME; ref_frame <= usable_ref_frame; ++ref_frame) {
// Skip find_predictor if the reference frame is not in the
// ref_frame_flags (i.e., not used as a reference for this frame).
skip_ref_find_pred[ref_frame] =
!(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame));
if (!skip_ref_find_pred[ref_frame]) {
find_predictors(cpi, x, ref_frame, frame_mv, const_motion,
&ref_frame_skip_mask, tile_data, mi_row, mi_col, yv12_mb,
bsize, force_skip_low_temp_var, comp_modes > 0);
}
}
if (cpi->use_svc || cpi->oxcf.speed <= 7 || bsize < BLOCK_32X32)
x->sb_use_mv_part = 0;
// Set the flag_svc_subpel to 1 for SVC if the lower spatial layer used
// an averaging filter for downsampling (phase = 8). If so, we will test
// a nonzero motion mode on the spatial reference.
// The nonzero motion is half pixel shifted to left and top (-4, -4).
if (cpi->use_svc && svc->spatial_layer_id > 0 &&
svc_force_zero_mode[inter_layer_ref - 1] &&
svc->downsample_filter_phase[svc->spatial_layer_id - 1] == 8 &&
!gf_temporal_ref) {
svc_mv_col = -4;
svc_mv_row = -4;
flag_svc_subpel = 1;
}
// For SVC with quality layers, when QP of lower layer is lower
// than current layer: force check of GF-ZEROMV before early exit
// due to skip flag.
if (svc->spatial_layer_id > 0 && no_scaling &&
(cpi->ref_frame_flags & VP9_GOLD_FLAG) &&
cm->base_qindex > svc->lower_layer_qindex + 10)
force_test_gf_zeromv = 1;
// For low motion content use x->sb_is_skin in addition to VeryHighSad
// for setting large_block.
large_block = (x->content_state_sb == kVeryHighSad ||
(x->sb_is_skin && cpi->rc.avg_frame_low_motion > 70) ||
cpi->oxcf.speed < 7)
? bsize > BLOCK_32X32
: bsize >= BLOCK_32X32;
use_model_yrd_large =
cpi->oxcf.rc_mode == VPX_CBR && large_block &&
!cyclic_refresh_segment_id_boosted(xd->mi[0]->segment_id) &&
cm->base_qindex;
for (idx = 0; idx < num_inter_modes + comp_modes; ++idx) {
int rate_mv = 0;
int mode_rd_thresh;
int mode_index;
int i;
int64_t this_sse;
int is_skippable;
int this_early_term = 0;
int rd_computed = 0;
int flag_preduv_computed[2] = { 0 };
int inter_mv_mode = 0;
int skip_this_mv = 0;
int comp_pred = 0;
int force_mv_inter_layer = 0;
PREDICTION_MODE this_mode;
second_ref_frame = NO_REF_FRAME;
if (idx < num_inter_modes) {
this_mode = ref_mode_set[idx].pred_mode;
ref_frame = ref_mode_set[idx].ref_frame;
if (cpi->use_svc) {
this_mode = ref_mode_set_svc[idx].pred_mode;
ref_frame = ref_mode_set_svc[idx].ref_frame;
}
} else {
// Add (0,0) compound modes.
this_mode = ZEROMV;
ref_frame = LAST_FRAME;
if (idx == num_inter_modes + comp_modes - 1) ref_frame = GOLDEN_FRAME;
second_ref_frame = ALTREF_FRAME;
comp_pred = 1;
}
if (ref_frame > usable_ref_frame) continue;
if (skip_ref_find_pred[ref_frame]) continue;
if (svc->previous_frame_is_intra_only) {
if (ref_frame != LAST_FRAME || frame_mv[this_mode][ref_frame].as_int != 0)
continue;
}
// If the segment reference frame feature is enabled then do nothing if the
// current ref frame is not allowed.
if (segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME) &&
get_segdata(seg, mi->segment_id, SEG_LVL_REF_FRAME) != (int)ref_frame)
continue;
if (flag_svc_subpel && ref_frame == inter_layer_ref) {
force_mv_inter_layer = 1;
// Only test mode if NEARESTMV/NEARMV is (svc_mv_col, svc_mv_row),
// otherwise set NEWMV to (svc_mv_col, svc_mv_row).
if (this_mode == NEWMV) {
frame_mv[this_mode][ref_frame].as_mv.col = svc_mv_col;
frame_mv[this_mode][ref_frame].as_mv.row = svc_mv_row;
} else if (frame_mv[this_mode][ref_frame].as_mv.col != svc_mv_col ||
frame_mv[this_mode][ref_frame].as_mv.row != svc_mv_row) {
continue;
}
}
if (comp_pred) {
if (!cpi->allow_comp_inter_inter) continue;
// Skip compound inter modes if ARF is not available.
if (!(cpi->ref_frame_flags & ref_frame_to_flag(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, mi->segment_id, SEG_LVL_REF_FRAME)) continue;
}
// For CBR mode: skip the golden reference search if sse of zeromv_last is
// below threshold.
if (ref_frame == GOLDEN_FRAME && cpi->oxcf.rc_mode == VPX_CBR &&
((cpi->use_svc && sse_zeromv_normalized < thresh_svc_skip_golden) ||
(!cpi->use_svc && sse_zeromv_normalized < thresh_skip_golden)))
continue;
if (!(cpi->ref_frame_flags & ref_frame_to_flag(ref_frame))) continue;
// For screen content. If zero_temp_sad source is computed: skip
// non-zero motion check for stationary blocks. If the superblock is
// non-stationary then for flat blocks skip the zero last check (keep golden
// as it may be inter-layer reference). Otherwise (if zero_temp_sad_source
// is not computed) skip non-zero motion check for flat blocks.
// TODO(marpan): Compute zero_temp_sad_source per coding block.
if (cpi->oxcf.content == VP9E_CONTENT_SCREEN) {
if (cpi->compute_source_sad_onepass && cpi->sf.use_source_sad) {
if ((frame_mv[this_mode][ref_frame].as_int != 0 &&
x->zero_temp_sad_source) ||
(frame_mv[this_mode][ref_frame].as_int == 0 &&
x->source_variance == 0 && ref_frame == LAST_FRAME &&
!x->zero_temp_sad_source))
continue;
} else if (frame_mv[this_mode][ref_frame].as_int != 0 &&
x->source_variance == 0) {
continue;
}
}
if (!(cpi->sf.inter_mode_mask[bsize] & (1 << this_mode))) continue;
if (cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.rc_mode == VPX_VBR) {
if (cpi->rc.is_src_frame_alt_ref &&
(ref_frame != ALTREF_FRAME ||
frame_mv[this_mode][ref_frame].as_int != 0))
continue;
if (!cm->show_frame && ref_frame == ALTREF_FRAME &&
frame_mv[this_mode][ref_frame].as_int != 0)
continue;
if (cpi->rc.alt_ref_gf_group && cm->show_frame &&
cpi->rc.frames_since_golden > (cpi->rc.baseline_gf_interval >> 1) &&
ref_frame == GOLDEN_FRAME &&
frame_mv[this_mode][ref_frame].as_int != 0)
continue;
if (cpi->rc.alt_ref_gf_group && cm->show_frame &&
cpi->rc.frames_since_golden > 0 &&
cpi->rc.frames_since_golden < (cpi->rc.baseline_gf_interval >> 1) &&
ref_frame == ALTREF_FRAME &&
frame_mv[this_mode][ref_frame].as_int != 0)
continue;
}
if (const_motion[ref_frame] && this_mode == NEARMV) continue;
// Skip non-zeromv mode search for golden frame if force_skip_low_temp_var
// is set. If nearestmv for golden frame is 0, zeromv mode will be skipped
// later.
if (!force_mv_inter_layer && force_skip_low_temp_var &&
ref_frame == GOLDEN_FRAME &&
frame_mv[this_mode][ref_frame].as_int != 0) {
continue;
}
if (x->content_state_sb != kVeryHighSad &&
(cpi->sf.short_circuit_low_temp_var >= 2 ||
(cpi->sf.short_circuit_low_temp_var == 1 && bsize == BLOCK_64X64)) &&
force_skip_low_temp_var && ref_frame == LAST_FRAME &&
this_mode == NEWMV) {
continue;
}
if (cpi->use_svc) {
if (!force_mv_inter_layer && svc_force_zero_mode[ref_frame - 1] &&
frame_mv[this_mode][ref_frame].as_int != 0)
continue;
}
// Disable this drop out case if the ref frame segment level feature is
// enabled for this segment. This is to prevent the possibility that we end
// up unable to pick any mode.
if (!segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME)) {
if (sf->reference_masking &&
!(frame_mv[this_mode][ref_frame].as_int == 0 &&
ref_frame == LAST_FRAME)) {
if (usable_ref_frame < ALTREF_FRAME) {
if (!force_skip_low_temp_var && usable_ref_frame > LAST_FRAME) {
i = (ref_frame == LAST_FRAME) ? GOLDEN_FRAME : LAST_FRAME;
if ((cpi->ref_frame_flags & ref_frame_to_flag(i)))
if (x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[i] << 1))
ref_frame_skip_mask |= (1 << ref_frame);
}
} else if (!cpi->rc.is_src_frame_alt_ref &&
!(frame_mv[this_mode][ref_frame].as_int == 0 &&
ref_frame == ALTREF_FRAME)) {
int ref1 = (ref_frame == GOLDEN_FRAME) ? LAST_FRAME : GOLDEN_FRAME;
int ref2 = (ref_frame == ALTREF_FRAME) ? LAST_FRAME : ALTREF_FRAME;
if (((cpi->ref_frame_flags & ref_frame_to_flag(ref1)) &&
(x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref1] << 1))) ||
((cpi->ref_frame_flags & ref_frame_to_flag(ref2)) &&
(x->pred_mv_sad[ref_frame] > (x->pred_mv_sad[ref2] << 1))))
ref_frame_skip_mask |= (1 << ref_frame);
}
}
if (ref_frame_skip_mask & (1 << ref_frame)) continue;
}
// Select prediction reference frames.
for (i = 0; i < MAX_MB_PLANE; i++) {
xd->plane[i].pre[0] = yv12_mb[ref_frame][i];
if (comp_pred) xd->plane[i].pre[1] = yv12_mb[second_ref_frame][i];
}
mi->ref_frame[0] = ref_frame;
mi->ref_frame[1] = second_ref_frame;
set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
mode_index = mode_idx[ref_frame][INTER_OFFSET(this_mode)];
mode_rd_thresh = best_pickmode.best_mode_skip_txfm
? rd_threshes[mode_index] << 1
: rd_threshes[mode_index];
// Increase mode_rd_thresh value for GOLDEN_FRAME for improved encoding
// speed with little/no subjective quality loss.
if (cpi->sf.bias_golden && ref_frame == GOLDEN_FRAME &&
cpi->rc.frames_since_golden > 4)
mode_rd_thresh = mode_rd_thresh << 3;
if ((cpi->sf.adaptive_rd_thresh_row_mt &&
rd_less_than_thresh_row_mt(best_rdc.rdcost, mode_rd_thresh,
&rd_thresh_freq_fact[mode_index])) ||
(!cpi->sf.adaptive_rd_thresh_row_mt &&
rd_less_than_thresh(best_rdc.rdcost, mode_rd_thresh,
&rd_thresh_freq_fact[mode_index])))
if (frame_mv[this_mode][ref_frame].as_int != 0) continue;
if (this_mode == NEWMV && !force_mv_inter_layer) {
if (search_new_mv(cpi, x, frame_mv, ref_frame, gf_temporal_ref, bsize,
mi_row, mi_col, best_pred_sad, &rate_mv, best_sse_sofar,
&best_rdc))
continue;
}
// TODO(jianj): Skipping the testing of (duplicate) non-zero motion vector
// causes some regression, leave it for duplicate zero-mv for now, until
// regression issue is resolved.
for (inter_mv_mode = NEARESTMV; inter_mv_mode <= NEWMV; inter_mv_mode++) {
if (inter_mv_mode == this_mode || comp_pred) continue;
if (mode_checked[inter_mv_mode][ref_frame] &&
frame_mv[this_mode][ref_frame].as_int ==
frame_mv[inter_mv_mode][ref_frame].as_int &&
frame_mv[inter_mv_mode][ref_frame].as_int == 0) {
skip_this_mv = 1;
break;
}
}
if (skip_this_mv) continue;
// If use_golden_nonzeromv is false, NEWMV mode is skipped for golden, no
// need to compute best_pred_sad which is only used to skip golden NEWMV.
if (use_golden_nonzeromv && this_mode == NEWMV && ref_frame == LAST_FRAME &&
frame_mv[NEWMV][LAST_FRAME].as_int != INVALID_MV) {
const int pre_stride = xd->plane[0].pre[0].stride;
const uint8_t *const pre_buf =
xd->plane[0].pre[0].buf +
(frame_mv[NEWMV][LAST_FRAME].as_mv.row >> 3) * pre_stride +
(frame_mv[NEWMV][LAST_FRAME].as_mv.col >> 3);
best_pred_sad = cpi->fn_ptr[bsize].sdf(
x->plane[0].src.buf, x->plane[0].src.stride, pre_buf, pre_stride);
x->pred_mv_sad[LAST_FRAME] = best_pred_sad;
}
if (this_mode != NEARESTMV && !comp_pred &&
frame_mv[this_mode][ref_frame].as_int ==
frame_mv[NEARESTMV][ref_frame].as_int)
continue;
mi->mode = this_mode;
mi->mv[0].as_int = frame_mv[this_mode][ref_frame].as_int;
mi->mv[1].as_int = 0;
// Search for the best prediction filter type, when the resulting
// motion vector is at sub-pixel accuracy level for luma component, i.e.,
// the last three bits are all zeros.
if (reuse_inter_pred) {
if (!this_mode_pred) {
this_mode_pred = &tmp[3];
} else {
this_mode_pred = &tmp[get_pred_buffer(tmp, 3)];
pd->dst.buf = this_mode_pred->data;
pd->dst.stride = bw;
}
}
if ((this_mode == NEWMV || filter_ref == SWITCHABLE) &&
pred_filter_search &&
(ref_frame == LAST_FRAME ||
(ref_frame == GOLDEN_FRAME && !force_mv_inter_layer &&
(cpi->use_svc || cpi->oxcf.rc_mode == VPX_VBR))) &&
(((mi->mv[0].as_mv.row | mi->mv[0].as_mv.col) & 0x07) != 0)) {
rd_computed = 1;
search_filter_ref(cpi, x, &this_rdc, mi_row, mi_col, tmp, bsize,
reuse_inter_pred, &this_mode_pred, &var_y, &sse_y,
force_smooth_filter, &this_early_term,
flag_preduv_computed, use_model_yrd_large);
} else {
mi->interp_filter = (filter_ref == SWITCHABLE) ? EIGHTTAP : filter_ref;
if (cpi->use_svc && ref_frame == GOLDEN_FRAME &&
svc_force_zero_mode[ref_frame - 1])
mi->interp_filter = filter_gf_svc;
vp9_build_inter_predictors_sby(xd, mi_row, mi_col, bsize);
// For large partition blocks, extra testing is done.
if (use_model_yrd_large) {
rd_computed = 1;
model_rd_for_sb_y_large(cpi, bsize, x, xd, &this_rdc.rate,
&this_rdc.dist, &var_y, &sse_y, mi_row, mi_col,
&this_early_term, flag_preduv_computed);
} else {
rd_computed = 1;
model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc.rate, &this_rdc.dist,
&var_y, &sse_y, 0);
}
// Save normalized sse (between current and last frame) for (0, 0) motion.
if (ref_frame == LAST_FRAME &&
frame_mv[this_mode][ref_frame].as_int == 0) {
sse_zeromv_normalized =
sse_y >> (b_width_log2_lookup[bsize] + b_height_log2_lookup[bsize]);
}
if (sse_y < best_sse_sofar) best_sse_sofar = sse_y;
}
if (!this_early_term) {
this_sse = (int64_t)sse_y;
block_yrd(cpi, x, &this_rdc, &is_skippable, &this_sse, bsize,
VPXMIN(mi->tx_size, TX_16X16), rd_computed, 0);
x->skip_txfm[0] = is_skippable;
if (is_skippable) {
this_rdc.rate = vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
} else {
if (RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist) <
RDCOST(x->rdmult, x->rddiv, 0, this_sse)) {
this_rdc.rate += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 0);
} else {
this_rdc.rate = vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
this_rdc.dist = this_sse;
x->skip_txfm[0] = SKIP_TXFM_AC_DC;
}
}
if (cm->interp_filter == SWITCHABLE) {
if ((mi->mv[0].as_mv.row | mi->mv[0].as_mv.col) & 0x07)
this_rdc.rate += vp9_get_switchable_rate(cpi, xd);
}
} else {
if (cm->interp_filter == SWITCHABLE) {
if ((mi->mv[0].as_mv.row | mi->mv[0].as_mv.col) & 0x07)
this_rdc.rate += vp9_get_switchable_rate(cpi, xd);
}
this_rdc.rate += vp9_cost_bit(vp9_get_skip_prob(cm, xd), 1);
}
if (!this_early_term &&
(x->color_sensitivity[0] || x->color_sensitivity[1])) {
RD_COST rdc_uv;
const BLOCK_SIZE uv_bsize = get_plane_block_size(bsize, &xd->plane[1]);
if (x->color_sensitivity[0] && !flag_preduv_computed[0]) {
vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 1);
flag_preduv_computed[0] = 1;
}
if (x->color_sensitivity[1] && !flag_preduv_computed[1]) {
vp9_build_inter_predictors_sbp(xd, mi_row, mi_col, bsize, 2);
flag_preduv_computed[1] = 1;
}
model_rd_for_sb_uv(cpi, uv_bsize, x, xd, &rdc_uv, &var_y, &sse_y, 1, 2);
this_rdc.rate += rdc_uv.rate;
this_rdc.dist += rdc_uv.dist;
}
this_rdc.rate += rate_mv;
this_rdc.rate += cpi->inter_mode_cost[x->mbmi_ext->mode_context[ref_frame]]
[INTER_OFFSET(this_mode)];
// TODO(marpan): Add costing for compound mode.
this_rdc.rate += ref_frame_cost[ref_frame];
this_rdc.rdcost = RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
// Bias against NEWMV that is very different from its neighbors, and bias
// to small motion-lastref for noisy input.
if (cpi->oxcf.rc_mode == VPX_CBR && cpi->oxcf.speed >= 5 &&
cpi->oxcf.content != VP9E_CONTENT_SCREEN) {
vp9_NEWMV_diff_bias(&cpi->noise_estimate, xd, this_mode, &this_rdc, bsize,
frame_mv[this_mode][ref_frame].as_mv.row,
frame_mv[this_mode][ref_frame].as_mv.col,
ref_frame == LAST_FRAME, x->lowvar_highsumdiff,
x->sb_is_skin);
}
// Skipping checking: test to see if this block can be reconstructed by
// prediction only.
if (cpi->allow_encode_breakout && !xd->lossless && !scene_change_detected &&
!svc->high_num_blocks_with_motion) {
encode_breakout_test(cpi, x, bsize, mi_row, mi_col, ref_frame, this_mode,
var_y, sse_y, yv12_mb, &this_rdc.rate,
&this_rdc.dist, flag_preduv_computed);
if (x->skip) {
this_rdc.rate += rate_mv;
this_rdc.rdcost =
RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
}
}
// On spatially flat blocks for screne content: bias against zero-last
// if the sse_y is non-zero. Only on scene change or high motion frames.
if (cpi->oxcf.content == VP9E_CONTENT_SCREEN &&
(scene_change_detected || svc->high_num_blocks_with_motion) &&
ref_frame == LAST_FRAME && frame_mv[this_mode][ref_frame].as_int == 0 &&
svc->spatial_layer_id == 0 && x->source_variance == 0 && sse_y > 0) {
this_rdc.rdcost = this_rdc.rdcost << 2;
}
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0 && denoise_svc_pickmode &&
cpi->denoiser.denoising_level > kDenLowLow) {
vp9_denoiser_update_frame_stats(mi, sse_y, this_mode, ctx);
// Keep track of zero_last cost.
if (ref_frame == LAST_FRAME && frame_mv[this_mode][ref_frame].as_int == 0)
zero_last_cost_orig = this_rdc.rdcost;
}
#else
(void)ctx;
#endif
mode_checked[this_mode][ref_frame] = 1;
if (this_rdc.rdcost < best_rdc.rdcost || x->skip) {
best_rdc = this_rdc;
best_early_term = this_early_term;
best_pickmode.best_mode = this_mode;
best_pickmode.best_pred_filter = mi->interp_filter;
best_pickmode.best_tx_size = mi->tx_size;
best_pickmode.best_ref_frame = ref_frame;
best_pickmode.best_mode_skip_txfm = x->skip_txfm[0];
best_pickmode.best_second_ref_frame = second_ref_frame;
if (reuse_inter_pred) {
free_pred_buffer(best_pickmode.best_pred);
best_pickmode.best_pred = this_mode_pred;
}
} else {
if (reuse_inter_pred) free_pred_buffer(this_mode_pred);
}
if (x->skip &&
(!force_test_gf_zeromv || mode_checked[ZEROMV][GOLDEN_FRAME]))
break;
// If early termination flag is 1 and at least 2 modes are checked,
// the mode search is terminated.
if (best_early_term && idx > 0 && !scene_change_detected &&
(!force_test_gf_zeromv || mode_checked[ZEROMV][GOLDEN_FRAME])) {
x->skip = 1;
break;
}
}
mi->mode = best_pickmode.best_mode;
mi->interp_filter = best_pickmode.best_pred_filter;
mi->tx_size = best_pickmode.best_tx_size;
mi->ref_frame[0] = best_pickmode.best_ref_frame;
mi->mv[0].as_int =
frame_mv[best_pickmode.best_mode][best_pickmode.best_ref_frame].as_int;
xd->mi[0]->bmi[0].as_mv[0].as_int = mi->mv[0].as_int;
x->skip_txfm[0] = best_pickmode.best_mode_skip_txfm;
mi->ref_frame[1] = best_pickmode.best_second_ref_frame;
// For spatial enhancemanent layer: perform intra prediction only if base
// layer is chosen as the reference. Always perform intra prediction if
// LAST is the only reference, or is_key_frame is set, or on base
// temporal layer.
if (svc->spatial_layer_id && !gf_temporal_ref) {
perform_intra_pred =
svc->temporal_layer_id == 0 ||
svc->layer_context[svc->temporal_layer_id].is_key_frame ||
!(cpi->ref_frame_flags & VP9_GOLD_FLAG) ||
(!svc->layer_context[svc->temporal_layer_id].is_key_frame &&
svc_force_zero_mode[best_pickmode.best_ref_frame - 1]);
inter_mode_thresh = (inter_mode_thresh << 1) + inter_mode_thresh;
}
if ((cpi->oxcf.lag_in_frames > 0 && cpi->oxcf.rc_mode == VPX_VBR &&
cpi->rc.is_src_frame_alt_ref) ||
svc->previous_frame_is_intra_only)
perform_intra_pred = 0;
// If the segment reference frame feature is enabled and set then
// skip the intra prediction.
if (segfeature_active(seg, mi->segment_id, SEG_LVL_REF_FRAME) &&
get_segdata(seg, mi->segment_id, SEG_LVL_REF_FRAME) > 0)
perform_intra_pred = 0;
// Perform intra prediction search, if the best SAD is above a certain
// threshold.
if (best_rdc.rdcost == INT64_MAX ||
(cpi->oxcf.content == VP9E_CONTENT_SCREEN && x->source_variance == 0) ||
(scene_change_detected && perform_intra_pred) ||
((!force_skip_low_temp_var || bsize < BLOCK_32X32 ||
x->content_state_sb == kVeryHighSad) &&
perform_intra_pred && !x->skip && best_rdc.rdcost > inter_mode_thresh &&
bsize <= cpi->sf.max_intra_bsize && !x->skip_low_source_sad &&
!x->lowvar_highsumdiff)) {
struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0 };
int64_t this_sse = INT64_MAX;
int i;
PRED_BUFFER *const best_pred = best_pickmode.best_pred;
TX_SIZE intra_tx_size =
VPXMIN(max_txsize_lookup[bsize],
tx_mode_to_biggest_tx_size[cpi->common.tx_mode]);
if (reuse_inter_pred && best_pred != NULL) {
if (best_pred->data == orig_dst.buf) {
this_mode_pred = &tmp[get_pred_buffer(tmp, 3)];
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth)
vpx_highbd_convolve_copy(
CONVERT_TO_SHORTPTR(best_pred->data), best_pred->stride,
CONVERT_TO_SHORTPTR(this_mode_pred->data), this_mode_pred->stride,
NULL, 0, 0, 0, 0, bw, bh, xd->bd);
else
vpx_convolve_copy(best_pred->data, best_pred->stride,
this_mode_pred->data, this_mode_pred->stride, NULL,
0, 0, 0, 0, bw, bh);
#else
vpx_convolve_copy(best_pred->data, best_pred->stride,
this_mode_pred->data, this_mode_pred->stride, NULL, 0,
0, 0, 0, bw, bh);
#endif // CONFIG_VP9_HIGHBITDEPTH
best_pickmode.best_pred = this_mode_pred;
}
}
pd->dst = orig_dst;
for (i = 0; i < 4; ++i) {
const PREDICTION_MODE this_mode = intra_mode_list[i];
THR_MODES mode_index = mode_idx[INTRA_FRAME][mode_offset(this_mode)];
int mode_rd_thresh = rd_threshes[mode_index];
// For spatially flat blocks, under short_circuit_flat_blocks flag:
// only check DC mode for stationary blocks, otherwise also check
// H and V mode.
if (sf->short_circuit_flat_blocks && x->source_variance == 0 &&
((x->zero_temp_sad_source && this_mode != DC_PRED) || i > 2)) {
continue;
}
if (!((1 << this_mode) & cpi->sf.intra_y_mode_bsize_mask[bsize]))
continue;
if (cpi->sf.rt_intra_dc_only_low_content && this_mode != DC_PRED &&
x->content_state_sb != kVeryHighSad)
continue;
if ((cpi->sf.adaptive_rd_thresh_row_mt &&
rd_less_than_thresh_row_mt(best_rdc.rdcost, mode_rd_thresh,
&rd_thresh_freq_fact[mode_index])) ||
(!cpi->sf.adaptive_rd_thresh_row_mt &&
rd_less_than_thresh(best_rdc.rdcost, mode_rd_thresh,
&rd_thresh_freq_fact[mode_index]))) {
// Avoid this early exit for screen on base layer, for scene
// changes or high motion frames.
if (cpi->oxcf.content != VP9E_CONTENT_SCREEN ||
svc->spatial_layer_id > 0 ||
(!scene_change_detected && !svc->high_num_blocks_with_motion))
continue;
}
mi->mode = this_mode;
mi->ref_frame[0] = INTRA_FRAME;
this_rdc.dist = this_rdc.rate = 0;
args.mode = this_mode;
args.skippable = 1;
args.rdc = &this_rdc;
mi->tx_size = intra_tx_size;
compute_intra_yprediction(this_mode, bsize, x, xd);
model_rd_for_sb_y(cpi, bsize, x, xd, &this_rdc.rate, &this_rdc.dist,
&var_y, &sse_y, 1);
block_yrd(cpi, x, &this_rdc, &args.skippable, &this_sse, bsize,
VPXMIN(mi->tx_size, TX_16X16), 1, 1);
// Check skip cost here since skippable is not set for for uv, this
// mirrors the behavior used by inter
if (args.skippable) {
x->skip_txfm[0] = SKIP_TXFM_AC_DC;
this_rdc.rate = vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 1);
} else {
x->skip_txfm[0] = SKIP_TXFM_NONE;
this_rdc.rate += vp9_cost_bit(vp9_get_skip_prob(&cpi->common, xd), 0);
}
// Inter and intra RD will mismatch in scale for non-screen content.
if (cpi->oxcf.content == VP9E_CONTENT_SCREEN) {
if (x->color_sensitivity[0])
vp9_foreach_transformed_block_in_plane(xd, bsize, 1,
estimate_block_intra, &args);
if (x->color_sensitivity[1])
vp9_foreach_transformed_block_in_plane(xd, bsize, 2,
estimate_block_intra, &args);
}
this_rdc.rate += cpi->mbmode_cost[this_mode];
this_rdc.rate += ref_frame_cost[INTRA_FRAME];
this_rdc.rate += intra_cost_penalty;
this_rdc.rdcost =
RDCOST(x->rdmult, x->rddiv, this_rdc.rate, this_rdc.dist);
if (this_rdc.rdcost < best_rdc.rdcost) {
best_rdc = this_rdc;
best_pickmode.best_mode = this_mode;
best_pickmode.best_intra_tx_size = mi->tx_size;
best_pickmode.best_ref_frame = INTRA_FRAME;
best_pickmode.best_second_ref_frame = NO_REF_FRAME;
mi->uv_mode = this_mode;
mi->mv[0].as_int = INVALID_MV;
mi->mv[1].as_int = INVALID_MV;
best_pickmode.best_mode_skip_txfm = x->skip_txfm[0];
}
}
// Reset mb_mode_info to the best inter mode.
if (best_pickmode.best_ref_frame != INTRA_FRAME) {
mi->tx_size = best_pickmode.best_tx_size;
} else {
mi->tx_size = best_pickmode.best_intra_tx_size;
}
}
pd->dst = orig_dst;
mi->mode = best_pickmode.best_mode;
mi->ref_frame[0] = best_pickmode.best_ref_frame;
mi->ref_frame[1] = best_pickmode.best_second_ref_frame;
x->skip_txfm[0] = best_pickmode.best_mode_skip_txfm;
if (!is_inter_block(mi)) {
mi->interp_filter = SWITCHABLE_FILTERS;
}
if (reuse_inter_pred && best_pickmode.best_pred != NULL) {
PRED_BUFFER *const best_pred = best_pickmode.best_pred;
if (best_pred->data != orig_dst.buf && is_inter_mode(mi->mode)) {
#if CONFIG_VP9_HIGHBITDEPTH
if (cm->use_highbitdepth)
vpx_highbd_convolve_copy(
CONVERT_TO_SHORTPTR(best_pred->data), best_pred->stride,
CONVERT_TO_SHORTPTR(pd->dst.buf), pd->dst.stride, NULL, 0, 0, 0, 0,
bw, bh, xd->bd);
else
vpx_convolve_copy(best_pred->data, best_pred->stride, pd->dst.buf,
pd->dst.stride, NULL, 0, 0, 0, 0, bw, bh);
#else
vpx_convolve_copy(best_pred->data, best_pred->stride, pd->dst.buf,
pd->dst.stride, NULL, 0, 0, 0, 0, bw, bh);
#endif // CONFIG_VP9_HIGHBITDEPTH
}
}
#if CONFIG_VP9_TEMPORAL_DENOISING
if (cpi->oxcf.noise_sensitivity > 0 && cpi->resize_pending == 0 &&
denoise_svc_pickmode && cpi->denoiser.denoising_level > kDenLowLow &&
cpi->denoiser.reset == 0) {
VP9_DENOISER_DECISION decision = COPY_BLOCK;
ctx->sb_skip_denoising = 0;
// TODO(marpan): There is an issue with denoising when the
// superblock partitioning scheme is based on the pickmode.
// Remove this condition when the issue is resolved.
if (x->sb_pickmode_part) ctx->sb_skip_denoising = 1;
vp9_pickmode_ctx_den_update(&ctx_den, zero_last_cost_orig, ref_frame_cost,
frame_mv, reuse_inter_pred, &best_pickmode);
vp9_denoiser_denoise(cpi, x, mi_row, mi_col, bsize, ctx, &decision,
gf_temporal_ref);
if (denoise_recheck_zeromv)
recheck_zeromv_after_denoising(cpi, mi, x, xd, decision, &ctx_den,
yv12_mb, &best_rdc, bsize, mi_row, mi_col);
best_pickmode.best_ref_frame = ctx_den.best_ref_frame;
}
#endif
if (best_pickmode.best_ref_frame == ALTREF_FRAME ||
best_pickmode.best_second_ref_frame == ALTREF_FRAME)
x->arf_frame_usage++;
else if (best_pickmode.best_ref_frame != INTRA_FRAME)
x->lastgolden_frame_usage++;
if (cpi->sf.adaptive_rd_thresh) {
THR_MODES best_mode_idx =
mode_idx[best_pickmode.best_ref_frame][mode_offset(mi->mode)];
if (best_pickmode.best_ref_frame == INTRA_FRAME) {
// Only consider the modes that are included in the intra_mode_list.
int intra_modes = sizeof(intra_mode_list) / sizeof(PREDICTION_MODE);
int i;
// TODO(yunqingwang): Check intra mode mask and only update freq_fact
// for those valid modes.
for (i = 0; i < intra_modes; i++) {
if (cpi->sf.adaptive_rd_thresh_row_mt)
update_thresh_freq_fact_row_mt(cpi, tile_data, x->source_variance,
thresh_freq_fact_idx, INTRA_FRAME,
best_mode_idx, intra_mode_list[i]);
else
update_thresh_freq_fact(cpi, tile_data, x->source_variance, bsize,
INTRA_FRAME, best_mode_idx,
intra_mode_list[i]);
}
} else {
for (ref_frame = LAST_FRAME; ref_frame <= GOLDEN_FRAME; ++ref_frame) {
PREDICTION_MODE this_mode;
if (best_pickmode.best_ref_frame != ref_frame) continue;
for (this_mode = NEARESTMV; this_mode <= NEWMV; ++this_mode) {
if (cpi->sf.adaptive_rd_thresh_row_mt)
update_thresh_freq_fact_row_mt(cpi, tile_data, x->source_variance,
thresh_freq_fact_idx, ref_frame,
best_mode_idx, this_mode);
else
update_thresh_freq_fact(cpi, tile_data, x->source_variance, bsize,
ref_frame, best_mode_idx, this_mode);
}
}
}
}
*rd_cost = best_rdc;
}