Commit 463ba705 authored by Alex Converse's avatar Alex Converse

vp9_rd_pick_inter_mode_sb() reorganization

* Reduce the number of short cirtcuit checks by pre-computing and combining like checks.
* Postpone non-trivial initializations until after the shortcircuits are evaluated.
* Add some consts and const pointers.

No change to the actual results of the call or output of the encoder.

Change-Id: Ie44c4702aec6e08cfe0b8b0ba3cd6b57206478d1
parent cd510ea8
......@@ -49,7 +49,6 @@ typedef struct {
int_mv ref_mvs[MAX_REF_FRAMES][MAX_MV_REF_CANDIDATES];
int rate;
int distortion;
int64_t intra_error;
int best_mode_index;
int rddiv;
int rdmult;
......@@ -63,9 +62,6 @@ typedef struct {
// search loop
int_mv pred_mv[MAX_REF_FRAMES];
INTERP_FILTER pred_interp_filter;
// Bit flag for each mode whether it has high error in comparison to others.
unsigned int modes_with_high_error;
} PICK_MODE_CONTEXT;
struct macroblock_plane {
......
......@@ -3127,10 +3127,10 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bsize,
PICK_MODE_CONTEXT *ctx,
int64_t best_rd_so_far) {
VP9_COMMON *cm = &cpi->common;
MACROBLOCKD *xd = &x->e_mbd;
MB_MODE_INFO *mbmi = &xd->mi_8x8[0]->mbmi;
const struct segmentation *seg = &cm->seg;
VP9_COMMON *const cm = &cpi->common;
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
const struct segmentation *const seg = &cm->seg;
const BLOCK_SIZE block_size = get_plane_block_size(bsize, &xd->plane[0]);
MB_PREDICTION_MODE this_mode;
MV_REFERENCE_FRAME ref_frame, second_ref_frame;
......@@ -3166,14 +3166,14 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
const int bws = num_8x8_blocks_wide_lookup[bsize] / 2;
const int bhs = num_8x8_blocks_high_lookup[bsize] / 2;
int best_skip2 = 0;
int ref_frame_mask = 0;
int mode_skip_mask = 0;
const int mode_skip_start = cpi->sf.mode_skip_start + 1;
const int *const rd_threshes = cpi->rd_threshes[segment_id][bsize];
const int *const rd_thresh_freq_fact = cpi->rd_thresh_freq_fact[bsize];
const int mode_search_skip_flags = cpi->sf.mode_search_skip_flags;
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
// Everywhere the flag is set the error is much higher than its neighbors.
ctx->modes_with_high_error = 0;
estimate_ref_frame_costs(cpi, segment_id, ref_costs_single, ref_costs_comp,
&comp_mode_p);
......@@ -3201,13 +3201,26 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
frame_mv[ZEROMV][ref_frame].as_int = 0;
}
for (ref_frame = LAST_FRAME;
ref_frame <= ALTREF_FRAME && cpi->sf.reference_masking; ++ref_frame) {
int i;
for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
if ((x->pred_mv_sad[ref_frame] >> 2) > x->pred_mv_sad[i]) {
ref_frame_mask |= (1 << ref_frame);
break;
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
// All modes from vp9_mode_order that use this frame as any ref
static const int ref_frame_mask_all[] = {
0x123291, 0x25c444, 0x39b722
};
// Fixed mv modes (NEARESTMV, NEARMV, ZEROMV) from vp9_mode_order that use
// this frame as their primary ref
static const int ref_frame_mask_fixedmv[] = {
0x121281, 0x24c404, 0x080102
};
if (!(cpi->ref_frame_flags & flag_list[ref_frame])) {
// Skip modes for missing references
mode_skip_mask |= ref_frame_mask_all[ref_frame - LAST_FRAME];
} else if (cpi->sf.reference_masking) {
for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
// Skip fixed mv modes for poor references
if ((x->pred_mv_sad[ref_frame] >> 2) > x->pred_mv_sad[i]) {
mode_skip_mask |= ref_frame_mask_fixedmv[ref_frame - LAST_FRAME];
break;
}
}
}
}
......@@ -3226,107 +3239,61 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
int64_t total_sse = INT_MAX;
int early_term = 0;
for (i = 0; i < TX_MODES; ++i)
tx_cache[i] = INT64_MAX;
x->skip = 0;
this_mode = vp9_mode_order[mode_index].mode;
ref_frame = vp9_mode_order[mode_index].ref_frame[0];
second_ref_frame = vp9_mode_order[mode_index].ref_frame[1];
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (mode_index > cpi->sf.mode_skip_start) {
if (mode_index == (cpi->sf.mode_skip_start + 1)) {
switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
case INTRA_FRAME:
mode_skip_mask = 0;
break;
case LAST_FRAME:
mode_skip_mask = LAST_FRAME_MODE_MASK;
break;
case GOLDEN_FRAME:
mode_skip_mask = GOLDEN_FRAME_MODE_MASK;
break;
case ALTREF_FRAME:
mode_skip_mask = ALT_REF_MODE_MASK;
break;
case NONE:
case MAX_REF_FRAMES:
assert(0 && "Invalid Reference frame");
}
if (mode_index == mode_skip_start) {
switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
case INTRA_FRAME:
break;
case LAST_FRAME:
mode_skip_mask |= LAST_FRAME_MODE_MASK;
break;
case GOLDEN_FRAME:
mode_skip_mask |= GOLDEN_FRAME_MODE_MASK;
break;
case ALTREF_FRAME:
mode_skip_mask |= ALT_REF_MODE_MASK;
break;
case NONE:
case MAX_REF_FRAMES:
assert(0 && "Invalid Reference frame");
}
if (mode_skip_mask & (1 << mode_index))
continue;
}
// Skip if the current reference frame has been masked off
if (ref_frame_mask & (1 << ref_frame) && this_mode != NEWMV)
if (mode_skip_mask & (1 << mode_index))
continue;
// Test best rd so far against threshold for trying this mode.
if ((best_rd < ((int64_t)cpi->rd_threshes[segment_id][bsize][mode_index] *
cpi->rd_thresh_freq_fact[bsize][mode_index] >> 5)) ||
cpi->rd_threshes[segment_id][bsize][mode_index] == INT_MAX)
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 ((second_ref_frame > INTRA_FRAME) &&
vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
continue;
mbmi->ref_frame[0] = ref_frame;
mbmi->ref_frame[1] = second_ref_frame;
if (best_rd < ((int64_t)rd_threshes[mode_index] *
rd_thresh_freq_fact[mode_index] >> 5) ||
rd_threshes[mode_index] == INT_MAX)
continue;
if (!(ref_frame == INTRA_FRAME
|| (cpi->ref_frame_flags & flag_list[ref_frame]))) {
continue;
}
if (!(second_ref_frame == NONE
|| (cpi->ref_frame_flags & flag_list[second_ref_frame]))) {
continue;
}
this_mode = vp9_mode_order[mode_index].mode;
ref_frame = vp9_mode_order[mode_index].ref_frame[0];
second_ref_frame = vp9_mode_order[mode_index].ref_frame[1];
comp_pred = second_ref_frame > INTRA_FRAME;
if (comp_pred) {
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
continue;
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
if (ref_frame != best_inter_ref_frame &&
second_ref_frame != best_inter_ref_frame)
continue;
}
set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
mbmi->uv_mode = DC_PRED;
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
: cm->interp_filter;
xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
if (comp_pred) {
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
// 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 (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME))
continue;
mode_excluded = mode_excluded ? mode_excluded
: cm->reference_mode == SINGLE_REFERENCE;
if ((mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA) &&
vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
continue;
if ((mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH) &&
ref_frame != best_inter_ref_frame &&
second_ref_frame != best_inter_ref_frame)
continue;
mode_excluded = mode_excluded ?
mode_excluded : cm->reference_mode == SINGLE_REFERENCE;
} else {
if (ref_frame != INTRA_FRAME && second_ref_frame != INTRA_FRAME)
mode_excluded = mode_excluded ?
mode_excluded : cm->reference_mode == COMPOUND_REFERENCE;
}
// 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];
}
// If the segment reference frame feature is enabled....
// then do nothing if the current ref frame is not allowed..
if (vp9_segfeature_active(seg, segment_id, SEG_LVL_REF_FRAME) &&
......@@ -3368,38 +3335,60 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
continue;
}
#ifdef MODE_TEST_HIT_STATS
// TEST/DEBUG CODE
// Keep a rcord of the number of test hits at each size
cpi->mode_test_hits[bsize]++;
#endif
if (ref_frame == INTRA_FRAME) {
TX_SIZE uv_tx;
// 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
static const unsigned int skip_intra_var_thresh[BLOCK_SIZES] = {
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
};
if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
if ((mode_search_skip_flags & FLAG_SKIP_INTRA_LOWVAR) &&
this_mode != DC_PRED &&
x->source_variance < skip_intra_var_thresh[mbmi->sb_type])
x->source_variance < skip_intra_var_thresh[bsize])
continue;
// Only search the oblique modes if the best so far is
// one of the neighboring directional modes
if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
if ((mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
(this_mode >= D45_PRED && this_mode <= TM_PRED)) {
if (vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
continue;
}
mbmi->mode = this_mode;
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
if (conditional_skipintra(mbmi->mode, best_intra_mode))
if (mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
if (conditional_skipintra(this_mode, best_intra_mode))
continue;
}
}
mbmi->mode = this_mode;
mbmi->uv_mode = DC_PRED;
mbmi->ref_frame[0] = ref_frame;
mbmi->ref_frame[1] = second_ref_frame;
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
mbmi->interp_filter = cm->interp_filter == SWITCHABLE ? EIGHTTAP
: cm->interp_filter;
x->skip = 0;
set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
xd->interp_kernel = vp9_get_interp_kernel(mbmi->interp_filter);
// 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];
}
for (i = 0; i < TX_MODES; ++i)
tx_cache[i] = INT64_MAX;
#ifdef MODE_TEST_HIT_STATS
// TEST/DEBUG CODE
// Keep a rcord of the number of test hits at each size
cpi->mode_test_hits[bsize]++;
#endif
if (ref_frame == INTRA_FRAME) {
TX_SIZE uv_tx;
super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
bsize, tx_cache, best_rd);
......@@ -3423,8 +3412,6 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
rate2 += intra_cost_penalty;
distortion2 = distortion_y + distortion_uv;
} else {
mbmi->mode = this_mode;
compmode_cost = vp9_cost_bit(comp_mode_p, second_ref_frame > INTRA_FRAME);
this_rd = handle_inter_mode(cpi, x, tile, bsize,
tx_cache,
&rate2, &distortion2, &skippable,
......@@ -3436,14 +3423,16 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
single_newmv, &total_sse, best_rd);
if (this_rd == INT64_MAX)
continue;
}
if (cm->reference_mode == REFERENCE_MODE_SELECT)
rate2 += compmode_cost;
compmode_cost = vp9_cost_bit(comp_mode_p, comp_pred);
if (cm->reference_mode == REFERENCE_MODE_SELECT)
rate2 += compmode_cost;
}
// Estimate the reference frame signaling cost and add it
// to the rolling cost variable.
if (second_ref_frame > INTRA_FRAME) {
if (comp_pred) {
rate2 += ref_costs_comp[ref_frame];
} else {
rate2 += ref_costs_single[ref_frame];
......@@ -3551,7 +3540,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
// TODO(debargha): enhance this test with a better distortion prediction
// based on qp, activity mask and history
if ((cpi->sf.mode_search_skip_flags & FLAG_EARLY_TERMINATE) &&
if ((mode_search_skip_flags & FLAG_EARLY_TERMINATE) &&
(mode_index > MIN_EARLY_TERM_INDEX)) {
const int qstep = xd->plane[0].dequant[1];
// TODO(debargha): Enhance this by specializing for each mode_index
......@@ -3661,17 +3650,6 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
}
}
// Flag all modes that have a distortion thats > 2x the best we found at
// this level.
for (mode_index = 0; mode_index < MB_MODE_COUNT; ++mode_index) {
if (mode_index == NEARESTMV || mode_index == NEARMV || mode_index == NEWMV)
continue;
if (mode_distortions[mode_index] > 2 * *returndistortion) {
ctx->modes_with_high_error |= (1 << mode_index);
}
}
assert((cm->interp_filter == SWITCHABLE) ||
(cm->interp_filter == best_mbmode.interp_filter) ||
!is_inter_block(&best_mbmode));
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment