Implements several heuristics to prune mode search

Skips mode searches for intra and compound inter modes depending
on the best mode so far and the reference frames. The various
heuristics to be used are selected by bits from a flag. The
previous direction based intra mode search pruning is also absorbed
in this framework.

Specifically the flags and their impact are:

1) FLAG_SKIP_INTRA_BESTINTER (skip intra mode search for oblique
directional modes and TM_PRED if the best so far is
an inter mode)
derfraw300: -0.15%, 10% speedup

2) FLAG_SKIP_INTRA_DIRMISMATCH (skip D27, D63, D117 and D153
mode search if the best so far is not one of the closest
hor/vert/diagonal directions.
derfraw300: -0.05%, about 9% speedup

3) FLAG_SKIP_COMP_BESTINTRA (skip compound prediction mode
search if the best so far is an intra mode)
derfraw300: -0.06%, about 7-8% speedup

4) FLAG_SKIP_COMP_REFMISMATCH (skip compound prediction search
if the best single ref inter mode does not have the same ref
as one of the two references being tested in the compound mode)
derfraw300: -0.56%, about 10% speedup

Change-Id: I1a736cd29b36325489e7af9f32698d6394b2c495
This commit is contained in:
Deb Mukherjee 2013-07-03 14:47:54 -07:00
parent a38cf2658a
commit d9b62160a0
4 changed files with 117 additions and 23 deletions

View File

@ -2018,14 +2018,14 @@ static void select_txfm_mode(VP9_COMP *cpi) {
} else if (cpi->common.current_video_frame == 0) {
cpi->common.txfm_mode = TX_MODE_SELECT;
} else {
if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
cpi->common.txfm_mode = ALLOW_32X32;
} else if (cpi->sf.tx_size_search_method == USE_FULL_RD) {
int frame_type = get_frame_type(cpi);
cpi->common.txfm_mode =
cpi->rd_tx_select_threshes[frame_type][ALLOW_32X32]
> cpi->rd_tx_select_threshes[frame_type][TX_MODE_SELECT] ?
ALLOW_32X32 : TX_MODE_SELECT;
} else if (cpi->sf.tx_size_search_method == USE_LARGESTALL) {
cpi->common.txfm_mode = ALLOW_32X32;
} else {
unsigned int total = 0;
int i;

View File

@ -718,7 +718,7 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
sf->adjust_partitioning_from_last_frame = 0;
sf->last_partitioning_redo_frequency = 4;
sf->disable_splitmv = 0;
sf->conditional_oblique_intramodes = 0;
sf->mode_search_skip_flags = 0;
// Skip any mode not chosen at size < X for all sizes > X
// Hence BLOCK_SIZE_SB64X64 (skip is off)
@ -755,13 +755,15 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
cpi->common.show_frame == 0) ?
USE_FULL_RD :
USE_LARGESTALL);
sf->conditional_oblique_intramodes = 1;
sf->disable_splitmv =
(MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;
sf->use_square_partition_only = !(cpi->common.frame_type == KEY_FRAME ||
cpi->common.intra_only ||
cpi->common.show_frame == 0);
sf->disable_splitmv =
(MIN(cpi->common.width, cpi->common.height) >= 720)? 1 : 0;
sf->unused_mode_skip_lvl = BLOCK_SIZE_SB32X32;
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA;
}
if (speed == 2) {
sf->adjust_thresholds_by_speed = 1;
@ -771,12 +773,19 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
sf->use_lastframe_partitioning = 1;
sf->adjust_partitioning_from_last_frame = 1;
sf->last_partitioning_redo_frequency = 3;
sf->tx_size_search_method = USE_LARGESTALL;
sf->conditional_oblique_intramodes = 1;
sf->unused_mode_skip_lvl = BLOCK_SIZE_SB32X32;
sf->reduce_first_step_size = 1;
sf->optimize_coefficients = 0;
// sf->reference_masking = 1;
sf->tx_size_search_method = ((cpi->common.frame_type == KEY_FRAME ||
cpi->common.intra_only ||
cpi->common.show_frame == 0) ?
USE_FULL_RD :
USE_LARGESTALL);
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA |
FLAG_SKIP_COMP_REFMISMATCH;
}
if (speed == 3) {
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
@ -787,7 +796,10 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
USE_FULL_RD :
USE_LARGESTALL);
sf->reduce_first_step_size = 1;
sf->conditional_oblique_intramodes = 1;
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA |
FLAG_SKIP_COMP_REFMISMATCH;
}
if (speed == 4) {
sf->comp_inter_joint_search_thresh = BLOCK_SIZE_TYPES;
@ -798,7 +810,10 @@ void vp9_set_speed_features(VP9_COMP *cpi) {
cpi->common.show_frame == 0) ?
USE_FULL_RD :
USE_LARGESTALL);
sf->conditional_oblique_intramodes = 1;
sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH |
FLAG_SKIP_INTRA_BESTINTER |
FLAG_SKIP_COMP_BESTINTRA |
FLAG_SKIP_COMP_REFMISMATCH;
}
/*
if (speed == 2) {

View File

@ -207,6 +207,30 @@ typedef enum {
USE_LARGESTALL
} TX_SIZE_SEARCH_METHOD;
typedef enum {
// Values should be powers of 2 so that they can be selected as bits of
// an integer flags field
// terminate search early based on distortion so far compared to
// qp step, distortion in the neighborhood of the frame, etc.
FLAG_EARLY_TERMINATE = 1,
// skips comp inter modes if the best so far is an intra mode
FLAG_SKIP_COMP_BESTINTRA = 2,
// skips comp inter modes if the best single intermode so far does
// not have the same reference as one of the two references being
// tested
FLAG_SKIP_COMP_REFMISMATCH = 4,
// skips oblique intra modes if the best so far is an inter mode
FLAG_SKIP_INTRA_BESTINTER = 8,
// skips oblique intra modes at angles 27, 63, 117, 153 if the best
// intra so far is not one of the neighboring directions
FLAG_SKIP_INTRA_DIRMISMATCH = 16,
} MODE_SEARCH_SKIP_LOGIC;
typedef struct {
int RD;
SEARCH_METHODS search_method;
@ -245,10 +269,11 @@ typedef struct {
int adjust_partitioning_from_last_frame;
int last_partitioning_redo_frequency;
int disable_splitmv;
// Search the D27, D63, D117 and D153 modes
// only if the best intra mode so far is one
// of the two directional modes nearest to each.
int conditional_oblique_intramodes;
// Implements various heuristics to skip searching modes
// The heuristics selected are based on flags
// defined in the MODE_SEARCH_SKIP_HEURISTICS enum
unsigned int mode_search_skip_flags;
} SPEED_FEATURES;
enum BlockSize {

View File

@ -1146,8 +1146,8 @@ static void super_block_yrd(VP9_COMP *cpi,
*psse = sse[mbmi->txfm_size];
}
static int conditional_skip(MB_PREDICTION_MODE mode,
MB_PREDICTION_MODE best_intra_mode) {
static int conditional_skipintra(MB_PREDICTION_MODE mode,
MB_PREDICTION_MODE best_intra_mode) {
if (mode == D117_PRED &&
best_intra_mode != V_PRED &&
best_intra_mode != D135_PRED)
@ -1206,8 +1206,8 @@ static int64_t rd_pick_intra4x4block(VP9_COMP *cpi, MACROBLOCK *x, int ib,
int ratey = 0;
// Only do the oblique modes if the best so far is
// one of the neighboring directional modes
if (cpi->sf.conditional_oblique_intramodes) {
if (conditional_skip(mode, *best_mode))
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
if (conditional_skipintra(mode, *best_mode))
continue;
}
@ -2916,7 +2916,10 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
vp9_prob comp_mode_p;
int64_t best_overall_rd = INT64_MAX;
int64_t best_intra_rd = INT64_MAX;
int64_t best_inter_rd = INT64_MAX;
MB_PREDICTION_MODE best_intra_mode = DC_PRED;
// MB_PREDICTION_MODE best_inter_mode = ZEROMV;
MV_REFERENCE_FRAME best_inter_ref_frame = LAST_FRAME;
INTERPOLATIONFILTERTYPE best_filter = SWITCHABLE;
INTERPOLATIONFILTERTYPE tmp_best_filter = SWITCHABLE;
int rate_uv_intra[TX_SIZE_MAX_SB], rate_uv_tokenonly[TX_SIZE_MAX_SB];
@ -3031,6 +3034,7 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
int i;
int this_skip2 = 0;
int64_t total_sse = INT_MAX;
int early_term = 0;
for (i = 0; i < NB_TXFM_MODES; ++i)
txfm_cache[i] = INT64_MAX;
@ -3088,6 +3092,16 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
continue;
}
comp_pred = mbmi->ref_frame[1] > 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 == INTRA_FRAME)
continue;
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
if (vp9_mode_order[mode_index].ref_frame != best_inter_ref_frame &&
vp9_mode_order[mode_index].second_ref_frame != best_inter_ref_frame)
continue;
}
// TODO(jingning, jkoleszar): scaling reference frame not supported for
// SPLITMV.
if (mbmi->ref_frame[0] > 0 &&
@ -3108,7 +3122,6 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
set_scale_factors(xd, mbmi->ref_frame[0], mbmi->ref_frame[1],
scale_factor);
comp_pred = mbmi->ref_frame[1] > INTRA_FRAME;
mbmi->mode = this_mode;
mbmi->uv_mode = DC_PRED;
@ -3186,6 +3199,12 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
if (this_mode == I4X4_PRED) {
int rate;
/*
if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
(vp9_mode_order[best_mode_index].ref_frame > INTRA_FRAME))
continue;
*/
mbmi->txfm_size = TX_4X4;
rd_pick_intra4x4mby_modes(cpi, x, &rate, &rate_y,
&distortion_y, INT64_MAX);
@ -3205,8 +3224,13 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
TX_SIZE uv_tx;
// Only search the oblique modes if the best so far is
// one of the neighboring directional modes
if (cpi->sf.conditional_oblique_intramodes) {
if (conditional_skip(mbmi->mode, best_intra_mode))
if ((cpi->sf.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 > INTRA_FRAME)
continue;
}
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_DIRMISMATCH) {
if (conditional_skipintra(mbmi->mode, best_intra_mode))
continue;
}
super_block_yrd(cpi, x, &rate_y, &distortion_y, &skippable, NULL,
@ -3249,6 +3273,16 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
PARTITION_INFO tmp_best_partition;
int pred_exists = 0;
int uv_skippable;
if (is_comp_pred) {
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME)
continue;
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
if (vp9_mode_order[mode_index].ref_frame != best_inter_ref_frame &&
vp9_mode_order[mode_index].second_ref_frame !=
best_inter_ref_frame)
continue;
}
this_rd_thresh = (mbmi->ref_frame[0] == LAST_FRAME) ?
cpi->rd_threshes[bsize][THR_NEWMV] :
@ -3441,13 +3475,22 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
this_rd = RDCOST(x->rdmult, x->rddiv, rate2, distortion2);
}
// Keep record of best intra distortion
// Keep record of best intra rd
if (xd->mode_info_context->mbmi.ref_frame[0] == INTRA_FRAME &&
xd->mode_info_context->mbmi.mode <= TM_PRED &&
this_rd < best_intra_rd) {
best_intra_rd = this_rd;
best_intra_mode = xd->mode_info_context->mbmi.mode;
}
// Keep record of best inter rd with single reference
if (xd->mode_info_context->mbmi.ref_frame[0] > INTRA_FRAME &&
xd->mode_info_context->mbmi.ref_frame[1] == NONE &&
!mode_excluded &&
this_rd < best_inter_rd) {
best_inter_rd = this_rd;
best_inter_ref_frame = ref_frame;
// best_inter_mode = xd->mode_info_context->mbmi.mode;
}
if (!disable_skip && mbmi->ref_frame[0] == INTRA_FRAME)
for (i = 0; i < NB_PREDICTION_TYPES; ++i)
@ -3475,6 +3518,8 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
if (this_rd < best_rd || x->skip) {
if (!mode_excluded) {
// Note index of best mode so far
const int qstep = xd->plane[0].dequant[1];
best_mode_index = mode_index;
if (ref_frame == INTRA_FRAME) {
@ -3492,6 +3537,12 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
if (this_mode == I4X4_PRED || this_mode == SPLITMV)
for (i = 0; i < 4; i++)
best_bmodes[i] = xd->mode_info_context->bmi[i];
// 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 (ref_frame > INTRA_FRAME && distortion2 * 4 < qstep * qstep)
early_term = 1;
}
#if 0
// Testing this mode gave rise to an improvement in best error score.
@ -3567,6 +3618,9 @@ int64_t vp9_rd_pick_inter_mode_sb(VP9_COMP *cpi, MACROBLOCK *x,
}
}
if (early_term)
break;
if (x->skip && !mode_excluded)
break;
}