Changes to exhaustive motion search.
This change alters the nature and use of exhaustive motion search. Firstly any exhaustive search is preceded by a normal step search. The exhaustive search is only carried out if the distortion resulting from the step search is above a threshold value. Secondly the simple +/- 64 exhaustive search is replaced by a multi stage mesh based search where each stage has a range and step/interval size. Subsequent stages use the best position from the previous stage as the center of the search but use a reduced range and interval size. For example: stage 1: Range +/- 64 interval 4 stage 2: Range +/- 32 interval 2 stage 3: Range +/- 15 interval 1 This process, especially when it follows on from a normal step search, has shown itself to be almost as effective as a full range exhaustive search with step 1 but greatly lowers the computational complexity such that it can be used in some cases for speeds 0-2. This patch also removes a double exhaustive search for sub 8x8 blocks which also contained a bug (the two searches used different distortion metrics). For best quality in my test animation sequence this patch has almost no impact on quality but improves encode speed by more than 5X. Restricted use in good quality speeds 0-2 yields significant quality gains on the animation test of 0.2 - 0.5 db with only a small impact on encode speed. On most clips though the quality gain and speed impact are small. Change-Id: Id22967a840e996e1db273f6ac4ff03f4f52d49aa
This commit is contained in:
@@ -1750,8 +1750,9 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
const int num_4x4_blocks_high = num_4x4_blocks_high_lookup[bsize];
|
||||
ENTROPY_CONTEXT t_above[2], t_left[2];
|
||||
int subpelmv = 1, have_ref = 0;
|
||||
SPEED_FEATURES *const sf = &cpi->sf;
|
||||
const int has_second_rf = has_second_ref(mbmi);
|
||||
const int inter_mode_mask = cpi->sf.inter_mode_mask[bsize];
|
||||
const int inter_mode_mask = sf->inter_mode_mask[bsize];
|
||||
MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
|
||||
|
||||
vp9_zero(*bsi);
|
||||
@@ -1820,7 +1821,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV) {
|
||||
MV *const new_mv = &mode_mv[NEWMV][0].as_mv;
|
||||
int step_param = 0;
|
||||
int thissme, bestsme = INT_MAX;
|
||||
int bestsme = INT_MAX;
|
||||
int sadpb = x->sadperbit4;
|
||||
MV mvp_full;
|
||||
int max_mv;
|
||||
@@ -1845,7 +1846,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
max_mv =
|
||||
VPXMAX(abs(bsi->mvp.as_mv.row), abs(bsi->mvp.as_mv.col)) >> 3;
|
||||
|
||||
if (cpi->sf.mv.auto_mv_step_size && cm->show_frame) {
|
||||
if (sf->mv.auto_mv_step_size && cm->show_frame) {
|
||||
// Take wtd average of the step_params based on the last frame's
|
||||
// max mv magnitude and the best ref mvs of the current block for
|
||||
// the given reference.
|
||||
@@ -1858,7 +1859,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
mvp_full.row = bsi->mvp.as_mv.row >> 3;
|
||||
mvp_full.col = bsi->mvp.as_mv.col >> 3;
|
||||
|
||||
if (cpi->sf.adaptive_motion_search) {
|
||||
if (sf->adaptive_motion_search) {
|
||||
mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].row >> 3;
|
||||
mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].col >> 3;
|
||||
step_param = VPXMAX(step_param, 8);
|
||||
@@ -1871,31 +1872,10 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
|
||||
bestsme = vp9_full_pixel_search(
|
||||
cpi, x, bsize, &mvp_full, step_param, sadpb,
|
||||
cpi->sf.mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
|
||||
sf->mv.subpel_search_method != SUBPEL_TREE ? cost_list : NULL,
|
||||
&bsi->ref_mv[0]->as_mv, new_mv,
|
||||
INT_MAX, 1);
|
||||
|
||||
// Should we do a full search (best quality only)
|
||||
if (cpi->oxcf.mode == BEST) {
|
||||
int_mv *const best_mv = &mi->bmi[i].as_mv[0];
|
||||
/* Check if mvp_full is within the range. */
|
||||
clamp_mv(&mvp_full, x->mv_col_min, x->mv_col_max,
|
||||
x->mv_row_min, x->mv_row_max);
|
||||
thissme = cpi->full_search_sad(x, &mvp_full,
|
||||
sadpb, 16, &cpi->fn_ptr[bsize],
|
||||
&bsi->ref_mv[0]->as_mv,
|
||||
&best_mv->as_mv);
|
||||
cost_list[1] = cost_list[2] = cost_list[3] = cost_list[4] = INT_MAX;
|
||||
if (thissme < bestsme) {
|
||||
bestsme = thissme;
|
||||
*new_mv = best_mv->as_mv;
|
||||
} else {
|
||||
// The full search result is actually worse so re-instate the
|
||||
// previous best vector
|
||||
best_mv->as_mv = *new_mv;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestsme < INT_MAX) {
|
||||
int distortion;
|
||||
cpi->find_fractional_mv_step(
|
||||
@@ -1904,8 +1884,8 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
&bsi->ref_mv[0]->as_mv,
|
||||
cm->allow_high_precision_mv,
|
||||
x->errorperbit, &cpi->fn_ptr[bsize],
|
||||
cpi->sf.mv.subpel_force_stop,
|
||||
cpi->sf.mv.subpel_iters_per_step,
|
||||
sf->mv.subpel_force_stop,
|
||||
sf->mv.subpel_iters_per_step,
|
||||
cond_cost_list(cpi, cost_list),
|
||||
x->nmvjointcost, x->mvcost,
|
||||
&distortion,
|
||||
@@ -1916,7 +1896,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
seg_mvs[i][mbmi->ref_frame[0]].as_mv = *new_mv;
|
||||
}
|
||||
|
||||
if (cpi->sf.adaptive_motion_search)
|
||||
if (sf->adaptive_motion_search)
|
||||
x->pred_mv[mbmi->ref_frame[0]] = *new_mv;
|
||||
|
||||
// restore src pointers
|
||||
@@ -1933,7 +1913,7 @@ static int64_t rd_pick_best_sub8x8_mode(VP9_COMP *cpi, MACROBLOCK *x,
|
||||
mbmi->interp_filter == EIGHTTAP) {
|
||||
// adjust src pointers
|
||||
mi_buf_shift(x, i);
|
||||
if (cpi->sf.comp_inter_joint_search_thresh <= bsize) {
|
||||
if (sf->comp_inter_joint_search_thresh <= bsize) {
|
||||
int rate_mv;
|
||||
joint_motion_search(cpi, x, bsize, frame_mv[this_mode],
|
||||
mi_row, mi_col, seg_mvs[i],
|
||||
|
||||
Reference in New Issue
Block a user