Select full-pel search method based on quantizer
For speed 1 and 2, full pixel motion search method is selected based on
the frame quantizer and resolution. Two new search methods are
introduced, NSTEP_8PT and CLAMPED_DIAMOND. The search is made more
aggressive for high quantizers, and the search window is reduced for
lower resolutions at high quantizers.
Instruction Count BD-Rate Loss(%)
cpu-used Reduction(%) avg.psnr ovr.psnr ssim
1 3.247 0.0273 0.0206 0.0373
2 4.111 0.0542 0.0539 0.1566
STATS_CHANGED
Change-Id: I557a944a7c35ccaa34e82a18e86502f7dfe7c103
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 639d914..9bdab9d 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1773,13 +1773,14 @@
// Function pointer to search site config initialization
// of different search method functions.
-typedef void (*av1_init_search_site_config)(search_site_config *cfg,
- int stride);
+typedef void (*av1_init_search_site_config)(search_site_config *cfg, int stride,
+ int level);
av1_init_search_site_config
av1_init_motion_compensation[NUM_DISTINCT_SEARCH_METHODS] = {
- av1_init_dsmotion_compensation, av1_init_motion_compensation_nstep,
- av1_init_motion_compensation_hex, av1_init_motion_compensation_bigdia,
+ av1_init_dsmotion_compensation, av1_init_motion_compensation_nstep,
+ av1_init_motion_compensation_nstep, av1_init_dsmotion_compensation,
+ av1_init_motion_compensation_hex, av1_init_motion_compensation_bigdia,
av1_init_motion_compensation_square
};
@@ -1809,10 +1810,12 @@
// Initialization of search_site_cfg for NUM_DISTINCT_SEARCH_METHODS.
for (SEARCH_METHODS i = DIAMOND; i < NUM_DISTINCT_SEARCH_METHODS; i++) {
+ const int level = ((i == NSTEP_8PT) || (i == CLAMPED_DIAMOND)) ? 1 : 0;
av1_init_motion_compensation[i](
- &mv_search_params->search_site_cfg[SS_CFG_SRC][i], y_stride);
+ &mv_search_params->search_site_cfg[SS_CFG_SRC][i], y_stride, level);
av1_init_motion_compensation[i](
- &mv_search_params->search_site_cfg[SS_CFG_LOOKAHEAD][i], y_stride_src);
+ &mv_search_params->search_site_cfg[SS_CFG_LOOKAHEAD][i], y_stride_src,
+ level);
}
// First pass search site config initialization.
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index b21e2f0..e5c7c924 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -65,7 +65,9 @@
// 5. FAST_HEX \approx FAST_DIAMOND
switch (search_method) {
case NSTEP: return DIAMOND;
+ case NSTEP_8PT: return DIAMOND;
case DIAMOND: return BIGDIA;
+ case CLAMPED_DIAMOND: return BIGDIA;
case BIGDIA: return HEX;
case SQUARE: return HEX;
case HEX: return FAST_HEX;
@@ -313,7 +315,10 @@
#define MAX_PATTERN_CANDIDATES 8 // max number of candidates per scale
#define PATTERN_CANDIDATES_REF 3 // number of refinement candidates
-void av1_init_dsmotion_compensation(search_site_config *cfg, int stride) {
+// Search site initialization for DIAMOND / CLAMPED_DIAMOND search methods.
+// level = 0: DIAMOND, level = 1: CLAMPED_DIAMOND.
+void av1_init_dsmotion_compensation(search_site_config *cfg, int stride,
+ int level) {
int num_search_steps = 0;
int stage_index = MAX_MVSEARCH_STEPS - 1;
@@ -321,7 +326,10 @@
cfg->site[stage_index][0].offset = 0;
cfg->stride = stride;
- for (int radius = MAX_FIRST_STEP; radius > 0; radius /= 2) {
+ // Choose the initial step size depending on level.
+ const int first_step = (level > 0) ? (MAX_FIRST_STEP / 4) : MAX_FIRST_STEP;
+
+ for (int radius = first_step; radius > 0;) {
int num_search_pts = 8;
const FULLPEL_MV search_site_mvs[13] = {
@@ -338,6 +346,8 @@
}
cfg->searches_per_step[stage_index] = num_search_pts;
cfg->radius[stage_index] = radius;
+ // Update the search radius based on level.
+ if (!level || ((stage_index < 9) && level)) radius /= 2;
--stage_index;
++num_search_steps;
}
@@ -388,16 +398,19 @@
cfg->num_search_steps = num_search_steps;
}
-// Search site initialization for NSTEP search method.
-void av1_init_motion_compensation_nstep(search_site_config *cfg, int stride) {
+// Search site initialization for NSTEP / NSTEP_8PT search methods.
+// level = 0: NSTEP, level = 1: NSTEP_8PT.
+void av1_init_motion_compensation_nstep(search_site_config *cfg, int stride,
+ int level) {
int num_search_steps = 0;
int stage_index = 0;
cfg->stride = stride;
int radius = 1;
- for (stage_index = 0; stage_index < 15; ++stage_index) {
+ const int num_stages = (level > 0) ? 16 : 15;
+ for (stage_index = 0; stage_index < num_stages; ++stage_index) {
int tan_radius = AOMMAX((int)(0.41 * radius), 1);
int num_search_pts = 12;
- if (radius <= 5) {
+ if ((radius <= 5) || (level > 0)) {
tan_radius = radius;
num_search_pts = 8;
}
@@ -433,7 +446,9 @@
// Search site initialization for BIGDIA / FAST_BIGDIA / FAST_DIAMOND
// search methods.
-void av1_init_motion_compensation_bigdia(search_site_config *cfg, int stride) {
+void av1_init_motion_compensation_bigdia(search_site_config *cfg, int stride,
+ int level) {
+ (void)level;
cfg->stride = stride;
// First scale has 4-closest points, the rest have 8 points in diamond
// shape at increasing scales
@@ -486,7 +501,9 @@
}
// Search site initialization for SQUARE search method.
-void av1_init_motion_compensation_square(search_site_config *cfg, int stride) {
+void av1_init_motion_compensation_square(search_site_config *cfg, int stride,
+ int level) {
+ (void)level;
cfg->stride = stride;
// All scales have 8 closest points in square shape.
static const int square_num_candidates[MAX_PATTERN_SCALES] = {
@@ -538,7 +555,9 @@
}
// Search site initialization for HEX / FAST_HEX search methods.
-void av1_init_motion_compensation_hex(search_site_config *cfg, int stride) {
+void av1_init_motion_compensation_hex(search_site_config *cfg, int stride,
+ int level) {
+ (void)level;
cfg->stride = stride;
// First scale has 8-closest points, the rest have 6 points in hex shape
// at increasing scales.
@@ -1664,7 +1683,9 @@
bigdia_search(start_mv, ms_params, step_param, 1, cost_list, best_mv);
break;
case NSTEP:
+ case NSTEP_8PT:
case DIAMOND:
+ case CLAMPED_DIAMOND:
var = full_pixel_diamond(start_mv, ms_params, step_param, cost_list,
best_mv, second_best_mv);
break;
@@ -1672,7 +1693,8 @@
}
// Should we allow a follow on exhaustive search?
- if (!run_mesh_search && search_method == NSTEP) {
+ if (!run_mesh_search &&
+ ((search_method == NSTEP) || (search_method == NSTEP_8PT))) {
int exhaustive_thr = ms_params->force_mesh_thresh;
exhaustive_thr >>=
10 - (mi_size_wide_log2[bsize] + mi_size_high_log2[bsize]);
diff --git a/av1/encoder/mcomp.h b/av1/encoder/mcomp.h
index 2519cc8..8905e92 100644
--- a/av1/encoder/mcomp.h
+++ b/av1/encoder/mcomp.h
@@ -135,22 +135,27 @@
// Search 12-points in the radius/tan_radius grid around center,
// up to 15 search stages.
NSTEP = 1,
+ // Search 8-points in the radius grid around center, up to 16 search stages.
+ NSTEP_8PT = 2,
+ // Search 8-points in the radius grid around center, upto 11 search stages
+ // with clamping of search radius.
+ CLAMPED_DIAMOND = 3,
// Search maximum 8-points in the radius grid around center,
// up to 11 search stages. First stage consists of 8 search points
// and the rest with 6 search points each in hex shape.
- HEX = 2,
+ HEX = 4,
// Search maximum 8-points in the radius grid around center,
// up to 11 search stages. First stage consists of 4 search
// points and the rest with 8 search points each.
- BIGDIA = 3,
+ BIGDIA = 5,
// Search 8-points in the square grid around center, up to 11 search stages.
- SQUARE = 4,
+ SQUARE = 6,
// HEX search with up to 2 stages.
- FAST_HEX = 5,
+ FAST_HEX = 7,
// BIGDIA search with up to 2 stages.
- FAST_DIAMOND = 6,
+ FAST_DIAMOND = 8,
// BIGDIA search with up to 3 stages.
- FAST_BIGDIA = 7,
+ FAST_BIGDIA = 9,
// Total number of search methods.
NUM_SEARCH_METHODS,
// Number of distinct search methods.
@@ -204,19 +209,24 @@
const search_site_config search_sites[NUM_SEARCH_METHODS],
int fine_search_interval);
-// Sets up configs for fullpixel diamond search method.
-void av1_init_dsmotion_compensation(search_site_config *cfg, int stride);
+// Sets up configs for fullpixel DIAMOND / CLAMPED_DIAMOND search method.
+void av1_init_dsmotion_compensation(search_site_config *cfg, int stride,
+ int level);
// Sets up configs for firstpass motion search.
void av1_init_motion_fpf(search_site_config *cfg, int stride);
-// Sets up configs for all other types of motion search method.
-void av1_init_motion_compensation_nstep(search_site_config *cfg, int stride);
+// Sets up configs for NSTEP / NSTEP_8PT motion search method.
+void av1_init_motion_compensation_nstep(search_site_config *cfg, int stride,
+ int level);
// Sets up configs for BIGDIA / FAST_DIAMOND / FAST_BIGDIA
// motion search method.
-void av1_init_motion_compensation_bigdia(search_site_config *cfg, int stride);
+void av1_init_motion_compensation_bigdia(search_site_config *cfg, int stride,
+ int level);
// Sets up configs for HEX or FAST_HEX motion search method.
-void av1_init_motion_compensation_hex(search_site_config *cfg, int stride);
+void av1_init_motion_compensation_hex(search_site_config *cfg, int stride,
+ int level);
// Sets up configs for SQUARE motion search method.
-void av1_init_motion_compensation_square(search_site_config *cfg, int stride);
+void av1_init_motion_compensation_square(search_site_config *cfg, int stride,
+ int level);
// Mv beyond the range do not produce new/different prediction block.
static INLINE void av1_set_mv_search_method(
@@ -226,14 +236,16 @@
// Array to inform which all search methods are having
// same candidates and different in number of search steps.
static const SEARCH_METHODS search_method_lookup[NUM_SEARCH_METHODS] = {
- DIAMOND, // DIAMOND
- NSTEP, // NSTEP
- HEX, // HEX
- BIGDIA, // BIGDIA
- SQUARE, // SQUARE
- HEX, // FAST_HEX
- BIGDIA, // FAST_DIAMOND
- BIGDIA // FAST_BIGDIA
+ DIAMOND, // DIAMOND
+ NSTEP, // NSTEP
+ NSTEP_8PT, // NSTEP_8PT
+ CLAMPED_DIAMOND, // CLAMPED_DIAMOND
+ HEX, // HEX
+ BIGDIA, // BIGDIA
+ SQUARE, // SQUARE
+ HEX, // FAST_HEX
+ BIGDIA, // FAST_DIAMOND
+ BIGDIA // FAST_BIGDIA
};
ms_params->search_method = search_method;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 1c17568..c38d240 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -122,6 +122,20 @@
INTER_REFS_PER_FRAME, INTER_REFS_PER_FRAME - 2, INTER_REFS_PER_FRAME - 3, 0
};
+// Qindex threshold levels used for selecting full-pel motion search.
+// ms_qthresh[i][j][k] indicates the qindex boundary value for 'k'th qindex band
+// for resolution index 'j' for aggressiveness level 'i'.
+// i = 0: conservative, i = 1: aggressive.
+// j = 0: lower than 720p resolution, j = 1: 720p or larger resolution.
+// Currently invoked only for speed 1 and 2.
+static int ms_qindex_thresh[2][2][2] = { { { 170, 50 }, { MAXQ, 200 } },
+ { { 170, 40 }, { 200, 40 } } };
+
+// Full-pel search methods for aggressive search based on qindex.
+// Index 0 is for resolutions lower than 720p, index 1 for 720p or larger
+// resolutions. Currently invoked only for speed 1 and 2.
+static SEARCH_METHODS motion_search_method[2] = { CLAMPED_DIAMOND, DIAMOND };
+
// Intra only frames, golden frames (except alt ref overlays) and
// alt ref frames tend to be coded at a higher than ambient quality
static int frame_is_boosted(const AV1_COMP *cpi) {
@@ -433,6 +447,7 @@
// TODO(any, yunqing): move this feature to speed 0.
sf->tpl_sf.skip_alike_starting_mv = 1;
+ sf->tpl_sf.search_method = NSTEP_8PT;
}
if (speed >= 2) {
@@ -1425,4 +1440,23 @@
sf->part_sf.ext_partition_eval_thresh = BLOCK_128X128;
}
}
+
+ if (cpi->oxcf.mode == GOOD && ((speed == 1) || (speed == 2))) {
+ if (!is_stat_generation_stage(cpi)) {
+ // Use faster full-pel motion search for high quantizers.
+ // Also use reduced total search range for low resolutions at high
+ // quantizers.
+ const int aggr = (speed == 1) ? 0 : 1;
+ const int qindex_thresh1 = ms_qindex_thresh[aggr][is_720p_or_larger][0];
+ const int qindex_thresh2 = ms_qindex_thresh[aggr][is_720p_or_larger][1];
+ const SEARCH_METHODS search_method =
+ motion_search_method[is_720p_or_larger];
+ if (cm->quant_params.base_qindex > qindex_thresh1) {
+ sf->mv_sf.search_method = search_method;
+ sf->tpl_sf.search_method = search_method;
+ } else if (cm->quant_params.base_qindex > qindex_thresh2) {
+ sf->mv_sf.search_method = NSTEP_8PT;
+ }
+ }
+ }
}