1 /*
2  * Copyright (c) 2016, Alliance for Open Media. All rights reserved
3  *
4  * This source code is subject to the terms of the BSD 2 Clause License and
5  * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
6  * was not distributed with this source code in the LICENSE file, you can
7  * obtain it at www.aomedia.org/license/software. If the Alliance for Open
8  * Media Patent License 1.0 was not distributed with this source code in the
9  * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
10  */
11 
12 #include <limits.h>
13 
14 #include "av1/common/reconintra.h"
15 
16 #include "av1/encoder/encoder.h"
17 #include "av1/encoder/speed_features.h"
18 #include "av1/encoder/rdopt.h"
19 
20 #include "aom_dsp/aom_dsp_common.h"
21 
22 #define MAX_MESH_SPEED 5  // Max speed setting for mesh motion method
23 // Max speed setting for tx domain evaluation
24 #define MAX_TX_DOMAIN_EVAL_SPEED 5
25 static MESH_PATTERN
26     good_quality_mesh_patterns[MAX_MESH_SPEED + 1][MAX_MESH_STEP] = {
27       { { 64, 8 }, { 28, 4 }, { 15, 1 }, { 7, 1 } },
28       { { 64, 8 }, { 28, 4 }, { 15, 1 }, { 7, 1 } },
29       { { 64, 8 }, { 14, 2 }, { 7, 1 }, { 7, 1 } },
30       { { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
31       { { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
32       { { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
33     };
34 
35 // TODO(huisu@google.com): These settings are pretty relaxed, tune them for
36 // each speed setting
37 static MESH_PATTERN intrabc_mesh_patterns[MAX_MESH_SPEED + 1][MAX_MESH_STEP] = {
38   { { 256, 1 }, { 256, 1 }, { 0, 0 }, { 0, 0 } },
39   { { 256, 1 }, { 256, 1 }, { 0, 0 }, { 0, 0 } },
40   { { 64, 1 }, { 64, 1 }, { 0, 0 }, { 0, 0 } },
41   { { 64, 1 }, { 64, 1 }, { 0, 0 }, { 0, 0 } },
42   { { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
43   { { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
44 };
45 
46 // Threshold values to be used for pruning the txfm_domain_distortion
47 // based on block MSE
48 // Index 0: Default mode evaluation, Winner mode processing is not
49 // applicable (Eg : IntraBc). Index 1: Mode evaluation.
50 // Index 2: Winner mode evaluation. Index 1 and 2 are applicable when
51 // enable_winner_mode_for_use_tx_domain_dist speed feature is ON
52 // TODO(any): Experiment the threshold logic based on variance metric
53 static unsigned int tx_domain_dist_thresholds[3][MODE_EVAL_TYPES] = {
54   { UINT_MAX, UINT_MAX, UINT_MAX }, { 22026, 22026, 22026 }, { 0, 0, 0 }
55 };
56 
57 // Transform domain distortion type to be used for default, mode and winner mode
58 // evaluation Index 0: Default mode evaluation, Winner mode processing is not
59 // applicable (Eg : IntraBc). Index 1: Mode evaluation. Index 2: Winner mode
60 // evaluation. Index 1 and 2 are applicable when
61 // enable_winner_mode_for_use_tx_domain_dist speed feature is ON
62 static unsigned int tx_domain_dist_types[3][MODE_EVAL_TYPES] = { { 0, 2, 0 },
63                                                                  { 1, 2, 0 },
64                                                                  { 2, 2, 0 } };
65 
66 // Threshold values to be used for disabling coeff RD-optimization
67 // based on block MSE / qstep^2.
68 // TODO(any): Experiment the threshold logic based on variance metric.
69 // For each row, the indices are as follows.
70 // Index 0: Default mode evaluation, Winner mode processing is not applicable
71 // (Eg : IntraBc)
72 // Index 1: Mode evaluation.
73 // Index 2: Winner mode evaluation.
74 // Index 1 and 2 are applicable when enable_winner_mode_for_coeff_opt speed
75 // feature is ON
76 // There are 6 levels with increasing speed, mapping to vertical indices.
77 static unsigned int coeff_opt_dist_thresholds[6][MODE_EVAL_TYPES] = {
78   { UINT_MAX, UINT_MAX, UINT_MAX },
79   { 3200, 250, UINT_MAX },
80   { 1728, 142, UINT_MAX },
81   { 864, 142, UINT_MAX },
82   { 432, 86, UINT_MAX },
83   { 216, 86, UINT_MAX }
84 };
85 
86 // Transform size to be used for default, mode and winner mode evaluation
87 // Index 0: Default mode evaluation, Winner mode processing is not applicable
88 // (Eg : IntraBc) Index 1: Mode evaluation. Index 2: Winner mode evaluation.
89 // Index 1 and 2 are applicable when enable_winner_mode_for_tx_size_srch speed
90 // feature is ON
91 static TX_SIZE_SEARCH_METHOD tx_size_search_methods[3][MODE_EVAL_TYPES] = {
92   { USE_FULL_RD, USE_LARGESTALL, USE_FULL_RD },
93   { USE_FAST_RD, USE_LARGESTALL, USE_FULL_RD },
94   { USE_LARGESTALL, USE_LARGESTALL, USE_FULL_RD }
95 };
96 
97 // Predict transform skip levels to be used for default, mode and winner mode
98 // evaluation. Index 0: Default mode evaluation, Winner mode processing is not
99 // applicable. Index 1: Mode evaluation, Index 2: Winner mode evaluation
100 // Values indicate the aggressiveness of skip flag prediction.
101 // 0 : no early skip prediction
102 // 1 : conservative early skip prediction using DCT_DCT
103 // 2 : early skip prediction based on SSE
104 static unsigned int predict_skip_levels[3][MODE_EVAL_TYPES] = { { 0, 0, 0 },
105                                                                 { 1, 1, 1 },
106                                                                 { 1, 2, 1 } };
107 
108 // Intra only frames, golden frames (except alt ref overlays) and
109 // alt ref frames tend to be coded at a higher than ambient quality
frame_is_boosted(const AV1_COMP * cpi)110 static int frame_is_boosted(const AV1_COMP *cpi) {
111   return frame_is_kf_gf_arf(cpi);
112 }
113 
dim_to_size(int dim)114 static BLOCK_SIZE dim_to_size(int dim) {
115   switch (dim) {
116     case 4: return BLOCK_4X4;
117     case 8: return BLOCK_8X8;
118     case 16: return BLOCK_16X16;
119     case 32: return BLOCK_32X32;
120     case 64: return BLOCK_64X64;
121     case 128: return BLOCK_128X128;
122     default: assert(0); return 0;
123   }
124 }
125 
set_good_speed_feature_framesize_dependent(const AV1_COMP * const cpi,SPEED_FEATURES * const sf,int speed)126 static void set_good_speed_feature_framesize_dependent(
127     const AV1_COMP *const cpi, SPEED_FEATURES *const sf, int speed) {
128   const AV1_COMMON *const cm = &cpi->common;
129   const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
130   const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
131   const int is_4k_or_larger = AOMMIN(cm->width, cm->height) >= 2160;
132 
133   if (is_480p_or_larger) {
134     sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
135     if (is_720p_or_larger)
136       sf->part_sf.auto_max_partition_based_on_simple_motion = ADAPT_PRED;
137     else
138       sf->part_sf.auto_max_partition_based_on_simple_motion = RELAXED_PRED;
139   } else {
140     sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
141     sf->part_sf.auto_max_partition_based_on_simple_motion = DIRECT_PRED;
142   }
143 
144   if (is_4k_or_larger) {
145     sf->part_sf.default_min_partition_size = BLOCK_8X8;
146   }
147 
148   // TODO(huisu@google.com): train models for 720P and above.
149   if (!is_720p_or_larger) {
150     sf->part_sf.ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
151     sf->part_sf.ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
152     sf->part_sf.ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
153     sf->part_sf.ml_partition_search_breakout_thresh[3] = 500;  // BLOCK_64X64
154     sf->part_sf.ml_partition_search_breakout_thresh[4] = -1;   // BLOCK_128X128
155     sf->part_sf.ml_early_term_after_part_split_level = 1;
156   }
157 
158   if (speed >= 1) {
159     if (is_720p_or_larger) {
160       sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
161     } else if (is_480p_or_larger) {
162       sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
163     } else {
164       sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
165     }
166 
167     if (!is_720p_or_larger) {
168       sf->part_sf.ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
169       sf->part_sf.ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
170       sf->part_sf.ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
171       sf->part_sf.ml_partition_search_breakout_thresh[3] = 300;  // BLOCK_64X64
172       sf->part_sf.ml_partition_search_breakout_thresh[4] = -1;  // BLOCK_128X128
173     }
174     sf->part_sf.ml_early_term_after_part_split_level = 2;
175   }
176 
177   if (speed >= 2) {
178     if (is_720p_or_larger) {
179       sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
180     } else if (is_480p_or_larger) {
181       sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
182     } else {
183       sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
184     }
185 
186     if (is_720p_or_larger) {
187       sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
188       sf->part_sf.partition_search_breakout_rate_thr = 120;
189     } else {
190       sf->part_sf.partition_search_breakout_dist_thr = (1 << 22);
191       sf->part_sf.partition_search_breakout_rate_thr = 100;
192     }
193 
194     if (is_720p_or_larger) {
195       sf->inter_sf.prune_obmc_prob_thresh = 16;
196     } else {
197       sf->inter_sf.prune_obmc_prob_thresh = 8;
198     }
199 
200     if (is_480p_or_larger) {
201       sf->tx_sf.tx_type_search.prune_tx_type_using_stats = 1;
202     }
203   }
204 
205   if (speed >= 3) {
206     sf->part_sf.ml_early_term_after_part_split_level = 0;
207 
208     if (is_720p_or_larger) {
209       sf->part_sf.partition_search_breakout_dist_thr = (1 << 25);
210       sf->part_sf.partition_search_breakout_rate_thr = 200;
211     } else {
212       sf->part_sf.max_intra_bsize = BLOCK_32X32;
213       sf->part_sf.partition_search_breakout_dist_thr = (1 << 23);
214       sf->part_sf.partition_search_breakout_rate_thr = 120;
215     }
216   }
217 
218   if (speed >= 4) {
219     if (is_720p_or_larger) {
220       sf->part_sf.partition_search_breakout_dist_thr = (1 << 26);
221     } else {
222       sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
223     }
224 
225     if (is_480p_or_larger) {
226       sf->tx_sf.tx_type_search.prune_tx_type_using_stats = 2;
227     }
228 
229     sf->inter_sf.prune_obmc_prob_thresh = 16;
230   }
231 
232   if (speed >= 5) {
233     if (is_720p_or_larger) {
234       sf->inter_sf.prune_warped_prob_thresh = 16;
235     } else if (is_480p_or_larger) {
236       sf->inter_sf.prune_warped_prob_thresh = 8;
237     }
238   }
239 }
240 
set_rt_speed_feature_framesize_dependent(const AV1_COMP * const cpi,SPEED_FEATURES * const sf,int speed)241 static void set_rt_speed_feature_framesize_dependent(const AV1_COMP *const cpi,
242                                                      SPEED_FEATURES *const sf,
243                                                      int speed) {
244   const AV1_COMMON *const cm = &cpi->common;
245   const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
246   const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
247   const int is_360p_or_larger = AOMMIN(cm->width, cm->height) >= 360;
248 
249   (void)is_720p_or_larger;  // Not used so far
250 
251   if (!is_360p_or_larger) {
252     if (speed >= 6) sf->rt_sf.force_tx_search_off = 1;
253     if (speed >= 8) {
254       sf->rt_sf.use_modeled_non_rd_cost = 0;
255       sf->rt_sf.use_nonrd_filter_search = 0;
256     }
257   }
258   if (is_360p_or_larger) {
259     if (speed >= 7) {
260       sf->interp_sf.disable_filter_search_var_thresh = 0;
261     }
262   }
263   if (!is_480p_or_larger) {
264     if (speed == 7) {
265       sf->rt_sf.nonrd_check_partition_merge_mode = 2;
266     }
267     if (speed >= 8) {
268       sf->mv_sf.subpel_search_method = SUBPEL_TREE;
269 
270       sf->rt_sf.estimate_motion_for_var_based_partition = 1;
271     }
272   }
273 }
274 
set_good_speed_features_framesize_independent(const AV1_COMP * const cpi,SPEED_FEATURES * const sf,int speed)275 static void set_good_speed_features_framesize_independent(
276     const AV1_COMP *const cpi, SPEED_FEATURES *const sf, int speed) {
277   const AV1_COMMON *const cm = &cpi->common;
278   const GF_GROUP *const gf_group = &cpi->gf_group;
279   const int boosted = frame_is_boosted(cpi);
280   const int is_boosted_arf2_bwd_type =
281       boosted || gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE;
282   const int allow_screen_content_tools =
283       cm->features.allow_screen_content_tools;
284   if (!cpi->oxcf.large_scale_tile) {
285     sf->hl_sf.high_precision_mv_usage = LAST_MV_DATA;
286   }
287 
288   // Speed 0 for all speed features that give neutral coding performance change.
289   sf->gm_sf.gm_disable_recode = 1;
290   sf->gm_sf.gm_search_type = GM_REDUCED_REF_SEARCH_SKIP_L2_L3;
291 
292   sf->part_sf.less_rectangular_check_level = 1;
293   sf->part_sf.ml_prune_4_partition = 1;
294   sf->part_sf.ml_prune_ab_partition = 1;
295   sf->part_sf.ml_prune_rect_partition = 1;
296   sf->part_sf.prune_ext_partition_types_search_level = 1;
297   sf->part_sf.simple_motion_search_prune_rect = 1;
298 
299   sf->inter_sf.disable_wedge_search_edge_thresh = 0;
300   sf->inter_sf.disable_wedge_search_var_thresh = 0;
301   // TODO(debargha): Test, tweak and turn on either 1 or 2
302   sf->inter_sf.inter_mode_rd_model_estimation = 1;
303   sf->inter_sf.model_based_post_interp_filter_breakout = 1;
304   sf->inter_sf.prune_compound_using_single_ref = 1;
305   sf->inter_sf.prune_mode_search_simple_translation = 1;
306   sf->inter_sf.prune_motion_mode_level = 1;
307   sf->inter_sf.prune_ref_frame_for_rect_partitions =
308       (boosted || (allow_screen_content_tools))
309           ? 0
310           : (is_boosted_arf2_bwd_type ? 1 : 2);
311   sf->inter_sf.prune_wedge_pred_diff_based = 1;
312   sf->inter_sf.reduce_inter_modes = 1;
313   sf->inter_sf.selective_ref_frame = 1;
314   sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;
315 
316   sf->interp_sf.cb_pred_filter_search = 0;
317   sf->interp_sf.use_fast_interpolation_filter_search = 1;
318 
319   sf->intra_sf.intra_pruning_with_hog = 1;
320   sf->intra_sf.intra_pruning_with_hog_thresh = -1.2f;
321 
322   sf->tx_sf.adaptive_txb_search_level = 1;
323   sf->tx_sf.intra_tx_size_search_init_depth_sqr = 1;
324   sf->tx_sf.model_based_prune_tx_search_level = 1;
325   sf->tx_sf.tx_type_search.use_reduced_intra_txset = 1;
326 
327   sf->rt_sf.use_nonrd_pick_mode = 0;
328   sf->rt_sf.use_real_time_ref_set = 0;
329 
330   if (cpi->twopass.fr_content_type == FC_GRAPHICS_ANIMATION)
331     sf->mv_sf.exhaustive_searches_thresh = (1 << 24);
332   else
333     sf->mv_sf.exhaustive_searches_thresh = (1 << 25);
334 
335   sf->rd_sf.perform_coeff_opt = 1;
336 
337   if (speed >= 1) {
338     sf->gm_sf.disable_adaptive_warp_error_thresh = 0;
339     sf->gm_sf.gm_search_type = GM_REDUCED_REF_SEARCH_SKIP_L2_L3_ARF2;
340     sf->gm_sf.prune_ref_frame_for_gm_search = boosted ? 0 : 1;
341 
342     sf->part_sf.intra_cnn_split = 1;
343     sf->part_sf.simple_motion_search_early_term_none = 1;
344     // TODO(Venkat): Clean-up frame type dependency for
345     // simple_motion_search_split in partition search function and set the
346     // speed feature accordingly
347     sf->part_sf.simple_motion_search_split = allow_screen_content_tools ? 1 : 2;
348 
349     sf->mv_sf.exhaustive_searches_thresh <<= 1;
350     sf->mv_sf.obmc_full_pixel_search_level = 1;
351     sf->mv_sf.use_accurate_subpel_search = USE_4_TAPS;
352 
353     sf->inter_sf.disable_interinter_wedge_newmv_search = boosted ? 0 : 1;
354     sf->inter_sf.prune_comp_search_by_single_result = boosted ? 2 : 1;
355     sf->inter_sf.prune_comp_type_by_comp_avg = 1;
356     sf->inter_sf.prune_comp_type_by_model_rd = boosted ? 0 : 1;
357     sf->inter_sf.prune_motion_mode_level = 2;
358     sf->inter_sf.prune_ref_frame_for_rect_partitions =
359         (frame_is_intra_only(&cpi->common) || (allow_screen_content_tools))
360             ? 0
361             : (boosted ? 1 : 2);
362     sf->inter_sf.reduce_inter_modes = boosted ? 1 : 2;
363     sf->inter_sf.reuse_inter_intra_mode = 1;
364     sf->inter_sf.selective_ref_frame = 2;
365     sf->inter_sf.skip_repeated_newmv = 1;
366 
367     sf->interp_sf.cb_pred_filter_search = 0;
368     sf->interp_sf.use_interp_filter = 1;
369     sf->intra_sf.prune_palette_search_level = 1;
370 
371     sf->tx_sf.adaptive_txb_search_level = 2;
372     sf->tx_sf.inter_tx_size_search_init_depth_rect = 1;
373     sf->tx_sf.inter_tx_size_search_init_depth_sqr = 1;
374     sf->tx_sf.intra_tx_size_search_init_depth_rect = 1;
375     sf->tx_sf.model_based_prune_tx_search_level = 0;
376     sf->tx_sf.tx_type_search.ml_tx_split_thresh = 4000;
377     sf->tx_sf.tx_type_search.prune_mode = PRUNE_2D_FAST;
378     sf->tx_sf.tx_type_search.skip_tx_search = 1;
379     sf->tx_sf.use_intra_txb_hash = 1;
380 
381     sf->rd_sf.perform_coeff_opt = boosted ? 2 : 3;
382     sf->rd_sf.tx_domain_dist_level = boosted ? 1 : 2;
383     sf->rd_sf.tx_domain_dist_thres_level = 1;
384 
385     sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL1;
386     sf->lpf_sf.dual_sgr_penalty_level = 1;
387     sf->lpf_sf.enable_sgr_ep_pruning = 1;
388 
389     // TODO(any, yunqing): move this feature to speed 0.
390     sf->tpl_sf.skip_alike_starting_mv = 1;
391   }
392 
393   if (speed >= 2) {
394     sf->gm_sf.gm_erroradv_type = GM_ERRORADV_TR_2;
395 
396     sf->part_sf.allow_partition_search_skip = 1;
397 
398     sf->mv_sf.auto_mv_step_size = 1;
399     sf->mv_sf.subpel_iters_per_step = 1;
400 
401     // TODO(chiyotsai@google.com): We can get 10% speed up if we move
402     // adaptive_rd_thresh to speed 1. But currently it performs poorly on some
403     // clips (e.g. 5% loss on dinner_1080p). We need to examine the sequence a
404     // bit more closely to figure out why.
405     sf->inter_sf.adaptive_rd_thresh = 1;
406     sf->inter_sf.comp_inter_joint_search_thresh = BLOCK_SIZES_ALL;
407     sf->inter_sf.disable_interinter_wedge_newmv_search = 1;
408     sf->inter_sf.disable_wedge_search_edge_thresh = 0;
409     sf->inter_sf.disable_wedge_search_var_thresh = 100;
410     sf->inter_sf.fast_interintra_wedge_search = 1;
411     sf->inter_sf.fast_wedge_sign_estimate = 1;
412     sf->inter_sf.prune_comp_search_by_single_result = boosted ? 4 : 1;
413     sf->inter_sf.prune_compound_using_neighbors = 1;
414     sf->inter_sf.prune_comp_type_by_comp_avg = 2;
415     sf->inter_sf.prune_warp_using_wmtype = 1;
416     sf->inter_sf.selective_ref_frame = 3;
417     sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_DISABLED;
418 
419     // TODO(Sachin): Enable/Enhance this speed feature for speed 2 & 3
420     sf->interp_sf.adaptive_interp_filter_search = 1;
421     sf->interp_sf.disable_dual_filter = 1;
422     sf->interp_sf.disable_filter_search_var_thresh = 100;
423 
424     sf->intra_sf.disable_smooth_intra =
425         !frame_is_intra_only(&cpi->common) || (cpi->rc.frames_to_key != 1);
426 
427     sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 3 : 4;
428 
429     sf->lpf_sf.prune_wiener_based_on_src_var = 1;
430     sf->lpf_sf.prune_sgr_based_on_wiener = !allow_screen_content_tools;
431   }
432 
433   if (speed >= 3) {
434     sf->hl_sf.high_precision_mv_usage = CURRENT_Q;
435     sf->hl_sf.recode_loop = ALLOW_RECODE_KFARFGF;
436 
437     sf->gm_sf.gm_search_type = GM_DISABLE_SEARCH;
438 
439     sf->part_sf.less_rectangular_check_level = 2;
440     sf->part_sf.simple_motion_search_prune_agg = 1;
441     sf->part_sf.prune_4_partition_using_split_info =
442         !allow_screen_content_tools;
443 
444     // adaptive_motion_search breaks encoder multi-thread tests.
445     // The values in x->pred_mv[] differ for single and multi-thread cases.
446     // See aomedia:1778.
447     // sf->mv_sf.adaptive_motion_search = 1;
448     sf->mv_sf.full_pixel_search_level = 1;
449     sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED;
450     sf->mv_sf.use_accurate_subpel_search = USE_2_TAPS;
451     sf->mv_sf.search_method = DIAMOND;
452 
453     sf->inter_sf.disable_sb_level_mv_cost_upd = 1;
454     // TODO(yunqing): evaluate this speed feature for speed 1 & 2, and combine
455     // it with cpi->sf.disable_wedge_search_var_thresh.
456     sf->inter_sf.disable_wedge_interintra_search = 1;
457     // TODO(any): Experiment with the early exit mechanism for speeds 0, 1 and 2
458     // and clean-up the speed feature
459     sf->inter_sf.perform_best_rd_based_gating_for_chroma = 1;
460     sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 1;
461     sf->inter_sf.prune_comp_search_by_single_result = boosted ? 4 : 2;
462     sf->inter_sf.prune_motion_mode_level = boosted ? 2 : 3;
463     sf->inter_sf.selective_ref_frame = 4;
464     sf->inter_sf.skip_repeated_ref_mv = 1;
465     sf->inter_sf.skip_repeated_full_newmv = 1;
466     if (cpi->oxcf.enable_smooth_interintra)
467       sf->inter_sf.disable_smooth_interintra = boosted ? 0 : 1;
468     sf->inter_sf.reuse_compound_type_decision = 1;
469     sf->inter_sf.txfm_rd_gate_level = (boosted || allow_screen_content_tools)
470                                           ? 0
471                                           : (is_boosted_arf2_bwd_type ? 1 : 2);
472 
473     sf->intra_sf.prune_palette_search_level = 2;
474 
475     sf->tpl_sf.skip_alike_starting_mv = 2;
476     sf->tpl_sf.prune_intra_modes = 1;
477     sf->tpl_sf.reduce_first_step_size = 6;
478 
479     sf->tx_sf.adaptive_txb_search_level = boosted ? 2 : 3;
480     sf->tx_sf.tx_type_search.use_skip_flag_prediction =
481         allow_screen_content_tools ? 1 : 2;
482 
483     // TODO(any): Refactor the code related to following winner mode speed
484     // features
485     sf->winner_mode_sf.enable_winner_mode_for_coeff_opt = 1;
486     // TODO(any): Experiment with this speed feature by enabling for key frames
487     sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch =
488         frame_is_intra_only(&cpi->common) ? 0 : 1;
489     sf->winner_mode_sf.enable_winner_mode_for_use_tx_domain_dist =
490         !allow_screen_content_tools;
491     sf->winner_mode_sf.motion_mode_for_winner_cand =
492         boosted
493             ? 0
494             : gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE ? 1
495                                                                          : 2;
496 
497     // TODO(any): evaluate if these lpf features can be moved to speed 2.
498     sf->lpf_sf.prune_sgr_based_on_wiener = allow_screen_content_tools ? 0 : 2;
499     sf->lpf_sf.disable_loop_restoration_chroma =
500         (boosted || allow_screen_content_tools) ? 0 : 1;
501     sf->lpf_sf.reduce_wiener_window_size = !boosted;
502     sf->lpf_sf.prune_wiener_based_on_src_var = 2;
503 
504     sf->hl_sf.second_alt_ref_filtering = 0;
505   }
506 
507   if (speed >= 4) {
508     sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
509 
510     sf->part_sf.simple_motion_search_prune_agg = 2;
511     sf->part_sf.prune_ab_partition_using_split_info =
512         !allow_screen_content_tools;
513 
514     sf->inter_sf.adaptive_mode_search = 1;
515     sf->inter_sf.alt_ref_search_fp = 1;
516     sf->inter_sf.prune_ref_mv_idx_search = 1;
517     sf->inter_sf.txfm_rd_gate_level =
518         (boosted || allow_screen_content_tools) ? 0 : 3;
519 
520     sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 2;
521     sf->inter_sf.prune_compound_using_neighbors = 2;
522     sf->inter_sf.disable_smooth_interintra = 1;
523 
524     sf->interp_sf.cb_pred_filter_search = 1;
525     sf->interp_sf.skip_sharp_interp_filter_search = 1;
526     sf->interp_sf.use_interp_filter = 2;
527     sf->interp_sf.adaptive_interp_filter_search = 2;
528 
529     sf->intra_sf.intra_uv_mode_mask[TX_16X16] = UV_INTRA_DC_H_V_CFL;
530     sf->intra_sf.intra_uv_mode_mask[TX_32X32] = UV_INTRA_DC_H_V_CFL;
531     sf->intra_sf.intra_uv_mode_mask[TX_64X64] = UV_INTRA_DC_H_V_CFL;
532     sf->intra_sf.intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
533     sf->intra_sf.intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
534     sf->intra_sf.intra_y_mode_mask[TX_64X64] = INTRA_DC_H_V;
535     // TODO(any): Experiment with this speed feature set to 2 for higher quality
536     // presets as well
537     sf->intra_sf.skip_intra_in_interframe = 2;
538 
539     sf->tx_sf.tx_type_search.enable_winner_mode_tx_type_pruning = 1;
540     sf->tx_sf.tx_type_search.fast_intra_tx_type_search = 1;
541     sf->tx_sf.tx_type_search.prune_mode = PRUNE_2D_MORE;
542     sf->tx_sf.tx_type_search.prune_tx_type_est_rd = 1;
543     // TODO(any): Experiment with enabling of this speed feature as hash state
544     // is reset during winner mode processing
545     sf->tx_sf.use_intra_txb_hash = 0;
546 
547     sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 3 : 5;
548     sf->rd_sf.tx_domain_dist_thres_level = 2;
549 
550     // TODO(any): Extend multi-winner mode processing support for inter frames
551     sf->winner_mode_sf.enable_multiwinner_mode_process =
552         frame_is_intra_only(&cpi->common) ? 1 : 0;
553     sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch = 1;
554 
555     sf->lpf_sf.cdef_pick_method = allow_screen_content_tools
556                                       ? CDEF_FAST_SEARCH_LVL1
557                                       : CDEF_FAST_SEARCH_LVL2;
558 
559     // TODO(any): The following features have no impact on quality and speed,
560     // and are disabled.
561     // sf->part_sf.partition_search_breakout_rate_thr = 300;
562     // sf->interp_sf.disable_filter_search_var_thresh = 200;
563     // sf->rd_sf.use_fast_coef_costing = 1;
564 
565     // TODO(any): The following features give really bad quality/speed trade
566     // off. Needs to be re-worked.
567     // sf->mv_sf.search_method = BIGDIA;
568     // sf->inter_sf.adaptive_rd_thresh = 4;
569     // sf->rd_sf.tx_domain_dist_level = 2;
570     // sf->rt_sf.mode_search_skip_flags =
571     //     (cm->current_frame.frame_type == KEY_FRAME)
572     //     ? 0
573     //     : FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER |
574     //     FLAG_SKIP_COMP_BESTINTRA | FLAG_SKIP_INTRA_LOWVAR |
575     //     FLAG_EARLY_TERMINATE;
576   }
577 
578   if (speed >= 5) {
579     sf->part_sf.simple_motion_search_prune_agg = 3;
580     sf->part_sf.ext_partition_eval_thresh =
581         allow_screen_content_tools ? BLOCK_8X8 : BLOCK_16X16;
582 
583     sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 3;
584     sf->inter_sf.disable_interinter_wedge = 1;
585     sf->inter_sf.disable_obmc = 1;
586     sf->inter_sf.disable_onesided_comp = 1;
587     sf->inter_sf.txfm_rd_gate_level =
588         (boosted || allow_screen_content_tools) ? 0 : 4;
589     sf->inter_sf.prune_inter_modes_if_skippable = 1;
590 
591     sf->lpf_sf.lpf_pick = LPF_PICK_FROM_FULL_IMAGE_NON_DUAL;
592     sf->lpf_sf.disable_lr_filter = 1;
593 
594     sf->mv_sf.simple_motion_subpel_force_stop = QUARTER_PEL;
595     sf->mv_sf.prune_mesh_search = 1;
596     sf->mv_sf.reduce_search_range = 1;
597 
598     sf->tpl_sf.subpel_force_stop = QUARTER_PEL;
599   }
600 
601   if (speed >= 6) {
602   }
603 }
604 
605 // TODO(kyslov): now this is very similar to
606 // set_good_speed_features_framesize_independent
607 //               except it sets non-rd flag on speed8. This function will likely
608 //               be modified in the future with RT-specific speed features
set_rt_speed_features_framesize_independent(AV1_COMP * cpi,SPEED_FEATURES * sf,int speed)609 static void set_rt_speed_features_framesize_independent(AV1_COMP *cpi,
610                                                         SPEED_FEATURES *sf,
611                                                         int speed) {
612   AV1_COMMON *const cm = &cpi->common;
613   const int boosted = frame_is_boosted(cpi);
614 
615   // Speed 0 for all speed features that give neutral coding performance change.
616   sf->gm_sf.gm_disable_recode = 1;
617   sf->gm_sf.gm_search_type = GM_REDUCED_REF_SEARCH_SKIP_L2_L3;
618 
619   sf->part_sf.less_rectangular_check_level = 1;
620   sf->part_sf.ml_prune_4_partition = 1;
621   sf->part_sf.ml_prune_ab_partition = 1;
622   sf->part_sf.ml_prune_rect_partition = 1;
623   sf->part_sf.prune_ext_partition_types_search_level = 1;
624 
625   // TODO(debargha): Test, tweak and turn on either 1 or 2
626   sf->inter_sf.inter_mode_rd_model_estimation = 0;
627   sf->inter_sf.disable_wedge_search_edge_thresh = 0;
628   sf->inter_sf.disable_wedge_search_var_thresh = 0;
629   sf->inter_sf.model_based_post_interp_filter_breakout = 1;
630   sf->inter_sf.prune_compound_using_single_ref = 0;
631   sf->inter_sf.prune_mode_search_simple_translation = 1;
632   sf->inter_sf.prune_motion_mode_level = 1;
633   sf->inter_sf.prune_ref_frame_for_rect_partitions = !boosted;
634   sf->inter_sf.prune_wedge_pred_diff_based = 1;
635   sf->inter_sf.reduce_inter_modes = 1;
636   sf->inter_sf.selective_ref_frame = 1;
637   sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;
638 
639   sf->interp_sf.cb_pred_filter_search = 0;
640   sf->interp_sf.use_fast_interpolation_filter_search = 1;
641 
642   sf->intra_sf.intra_pruning_with_hog = 1;
643   sf->intra_sf.intra_pruning_with_hog_thresh = -1.2f;
644 
645   sf->mv_sf.full_pixel_search_level = 1;
646   sf->mv_sf.exhaustive_searches_thresh = INT_MAX;
647 
648   sf->rt_sf.check_intra_pred_nonrd = 1;
649   sf->rt_sf.estimate_motion_for_var_based_partition = 1;
650   sf->rt_sf.hybrid_intra_pickmode = 0;
651   sf->rt_sf.nonrd_prune_ref_frame_search = 0;
652   sf->rt_sf.reuse_inter_pred_nonrd = 0;
653   sf->rt_sf.use_comp_ref_nonrd = 1;
654   sf->rt_sf.use_nonrd_filter_search = 1;
655   sf->rt_sf.use_nonrd_pick_mode = 0;
656   sf->rt_sf.use_real_time_ref_set = 0;
657   sf->tx_sf.adaptive_txb_search_level = 1;
658   sf->tx_sf.intra_tx_size_search_init_depth_sqr = 1;
659   sf->tx_sf.model_based_prune_tx_search_level = 1;
660   sf->tx_sf.tx_type_search.use_reduced_intra_txset = 1;
661 
662   if (speed >= 1) {
663     sf->gm_sf.gm_erroradv_type = GM_ERRORADV_TR_1;
664     sf->gm_sf.gm_search_type = GM_REDUCED_REF_SEARCH_SKIP_L2_L3_ARF2;
665 
666     sf->part_sf.prune_ext_partition_types_search_level = 2;
667     sf->part_sf.simple_motion_search_prune_rect = 1;
668 
669     sf->mv_sf.obmc_full_pixel_search_level = 1;
670     sf->mv_sf.use_accurate_subpel_search = USE_4_TAPS;
671 
672     sf->inter_sf.prune_comp_search_by_single_result = 1;
673     sf->inter_sf.reuse_inter_intra_mode = 1;
674     sf->inter_sf.selective_ref_frame = 2;
675     sf->inter_sf.skip_repeated_newmv = 1;
676     sf->inter_sf.disable_wedge_search_var_thresh = 0;
677     sf->inter_sf.disable_wedge_search_edge_thresh = 0;
678     sf->inter_sf.prune_comp_type_by_comp_avg = 1;
679     sf->inter_sf.prune_motion_mode_level = 2;
680     sf->inter_sf.prune_single_motion_modes_by_simple_trans = 1;
681 
682     sf->interp_sf.cb_pred_filter_search = 1;
683     sf->interp_sf.use_interp_filter = 1;
684 
685     sf->tx_sf.adaptive_txb_search_level = 2;
686     sf->tx_sf.intra_tx_size_search_init_depth_rect = 1;
687     sf->tx_sf.tx_size_search_lgr_block = 1;
688     sf->tx_sf.tx_type_search.ml_tx_split_thresh = 4000;
689     sf->tx_sf.tx_type_search.skip_tx_search = 1;
690     sf->tx_sf.use_intra_txb_hash = 1;
691 
692     sf->rd_sf.optimize_b_precheck = 1;
693     sf->rd_sf.tx_domain_dist_level = boosted ? 0 : 1;
694     sf->rd_sf.tx_domain_dist_thres_level = 1;
695 
696     sf->lpf_sf.dual_sgr_penalty_level = 1;
697   }
698 
699   if (speed >= 2) {
700     sf->gm_sf.gm_erroradv_type = GM_ERRORADV_TR_2;
701 
702     sf->part_sf.allow_partition_search_skip = 1;
703     sf->part_sf.partition_search_breakout_rate_thr = 80;
704 
705     sf->mv_sf.auto_mv_step_size = 1;
706     sf->mv_sf.subpel_iters_per_step = 1;
707 
708     sf->inter_sf.adaptive_rd_thresh = 1;
709     sf->inter_sf.comp_inter_joint_search_thresh = BLOCK_SIZES_ALL;
710     sf->inter_sf.disable_wedge_search_edge_thresh = 0;
711     sf->inter_sf.disable_wedge_search_var_thresh = 100;
712     sf->inter_sf.fast_wedge_sign_estimate = 1;
713     sf->inter_sf.prune_comp_type_by_comp_avg = 2;
714     sf->inter_sf.selective_ref_frame = 3;
715     sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_DISABLED;
716 
717     sf->interp_sf.adaptive_interp_filter_search = 1;
718     sf->interp_sf.cb_pred_filter_search = 0;
719     sf->interp_sf.disable_dual_filter = 1;
720     sf->interp_sf.disable_filter_search_var_thresh = 100;
721 
722     sf->tx_sf.inter_tx_size_search_init_depth_rect = 1;
723     sf->tx_sf.inter_tx_size_search_init_depth_sqr = 1;
724     sf->tx_sf.model_based_prune_tx_search_level = 0;
725 
726     sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL1;
727   }
728 
729   if (speed >= 3) {
730     sf->hl_sf.recode_loop = ALLOW_RECODE_KFARFGF;
731 
732     sf->gm_sf.gm_search_type = GM_DISABLE_SEARCH;
733 
734     sf->part_sf.less_rectangular_check_level = 2;
735 
736     sf->mv_sf.use_accurate_subpel_search = USE_2_TAPS;
737     // adaptive_motion_search breaks encoder multi-thread tests.
738     // The values in x->pred_mv[] differ for single and multi-thread cases.
739     // See aomedia:1778.
740     // sf->mv_sf.adaptive_motion_search = 1;
741 
742     sf->inter_sf.adaptive_rd_thresh = 2;
743     sf->inter_sf.disable_sb_level_mv_cost_upd = 1;
744     // TODO(yunqing): evaluate this speed feature for speed 1 & 2, and combine
745     // it with cpi->sf.disable_wedge_search_var_thresh.
746     sf->inter_sf.disable_wedge_interintra_search = 1;
747     sf->inter_sf.prune_comp_search_by_single_result = 2;
748     sf->inter_sf.prune_motion_mode_level = boosted ? 2 : 3;
749     sf->inter_sf.prune_warp_using_wmtype = 1;
750     sf->inter_sf.selective_ref_frame = 4;
751 
752     sf->tx_sf.tx_type_search.prune_mode = PRUNE_2D_FAST;
753 
754     sf->rd_sf.tx_domain_dist_level = 1;
755 
756     sf->winner_mode_sf.tx_size_search_level = boosted ? 0 : 2;
757   }
758 
759   if (speed >= 4) {
760     sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED;
761 
762     sf->inter_sf.adaptive_mode_search = 1;
763     sf->inter_sf.alt_ref_search_fp = 1;
764 
765     sf->interp_sf.skip_sharp_interp_filter_search = 1;
766 
767     sf->tx_sf.tx_type_search.fast_inter_tx_type_search = 1;
768     sf->tx_sf.tx_type_search.fast_intra_tx_type_search = 1;
769     sf->tx_sf.use_intra_txb_hash = 0;
770 
771     sf->rd_sf.use_mb_rd_hash = 0;
772 
773     sf->winner_mode_sf.tx_size_search_level = frame_is_intra_only(cm) ? 0 : 2;
774   }
775 
776   if (speed >= 5) {
777     sf->hl_sf.recode_loop = ALLOW_RECODE_KFMAXBW;
778 
779     sf->inter_sf.adaptive_rd_thresh = 4;
780     sf->interp_sf.disable_filter_search_var_thresh = 200;
781 
782     sf->rd_sf.use_fast_coef_costing = 1;
783     sf->rd_sf.tx_domain_dist_level = 2;
784     sf->rd_sf.tx_domain_dist_thres_level = 2;
785     sf->winner_mode_sf.tx_size_search_level = 1;
786 
787     sf->rt_sf.mode_search_skip_flags =
788         (cm->current_frame.frame_type == KEY_FRAME)
789             ? 0
790             : FLAG_SKIP_INTRA_DIRMISMATCH | FLAG_SKIP_INTRA_BESTINTER |
791                   FLAG_SKIP_COMP_BESTINTRA | FLAG_SKIP_INTRA_LOWVAR |
792                   FLAG_EARLY_TERMINATE;
793     sf->hl_sf.frame_parameter_update = 0;
794 
795     sf->part_sf.default_max_partition_size = BLOCK_128X128;
796     sf->part_sf.default_min_partition_size = BLOCK_8X8;
797     sf->part_sf.max_intra_bsize = BLOCK_32X32;
798     sf->part_sf.partition_search_breakout_rate_thr = 500;
799     sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
800     sf->part_sf.adjust_var_based_rd_partitioning = 2;
801 
802     sf->mv_sf.search_method = FAST_DIAMOND;
803     sf->mv_sf.subpel_force_stop = QUARTER_PEL;
804     sf->mv_sf.use_fullpel_costlist = 1;
805     sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
806 
807     sf->inter_sf.adaptive_mode_search = 2;
808     sf->inter_sf.inter_mode_rd_model_estimation = 2;
809 
810     for (int i = 0; i < TX_SIZES; ++i) {
811       sf->intra_sf.intra_y_mode_mask[i] = INTRA_DC;
812       sf->intra_sf.intra_uv_mode_mask[i] = UV_INTRA_DC_CFL;
813     }
814 
815     sf->tx_sf.tx_type_search.prune_mode = PRUNE_2D_MORE;
816     sf->tx_sf.use_inter_txb_hash = 0;
817     sf->tx_sf.refine_fast_tx_search_results = 0;
818 
819     sf->rd_sf.optimize_coefficients = NO_TRELLIS_OPT;
820     sf->rd_sf.simple_model_rd_from_var = 1;
821 
822     sf->lpf_sf.cdef_pick_method = CDEF_PICK_FROM_Q;
823     sf->lpf_sf.lpf_pick = LPF_PICK_FROM_Q;
824 
825     sf->rt_sf.mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
826     sf->rt_sf.num_inter_modes_for_tx_search = 5;
827     sf->rt_sf.skip_interp_filter_search = 1;
828     sf->rt_sf.use_comp_ref_nonrd = 0;
829     sf->rt_sf.use_real_time_ref_set = 1;
830     sf->rt_sf.use_simple_rd_model = 1;
831   }
832 
833   if (speed >= 6) {
834     sf->part_sf.adjust_var_based_rd_partitioning = 1;
835   }
836 
837   if (speed >= 7) {
838     sf->hl_sf.frame_parameter_update = 0;
839 
840     sf->part_sf.default_max_partition_size = BLOCK_128X128;
841     sf->part_sf.default_min_partition_size = BLOCK_8X8;
842     sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
843 
844     sf->mv_sf.search_method = FAST_DIAMOND;
845     sf->mv_sf.subpel_force_stop = QUARTER_PEL;
846     sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED;
847 
848     sf->inter_sf.inter_mode_rd_model_estimation = 2;
849 
850     sf->lpf_sf.cdef_pick_method = CDEF_PICK_FROM_Q;
851     sf->lpf_sf.lpf_pick = LPF_PICK_FROM_Q;
852 
853     sf->rt_sf.mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
854     sf->rt_sf.nonrd_prune_ref_frame_search = 1;
855     sf->rt_sf.reuse_inter_pred_nonrd = 0;
856     sf->rt_sf.short_circuit_low_temp_var = 0;
857     sf->rt_sf.skip_interp_filter_search = 0;
858     sf->rt_sf.use_comp_ref_nonrd = 0;
859     sf->rt_sf.use_nonrd_altref_frame = 1;
860     sf->rt_sf.use_nonrd_pick_mode = 1;
861     sf->rt_sf.nonrd_check_partition_merge_mode = 1;
862     sf->rt_sf.nonrd_check_partition_split = 0;
863     sf->rt_sf.hybrid_intra_pickmode = 1;
864   }
865 
866   if (speed >= 8) {
867     sf->rt_sf.estimate_motion_for_var_based_partition = 0;
868     sf->rt_sf.short_circuit_low_temp_var = 1;
869     sf->rt_sf.reuse_inter_pred_nonrd = 1;
870     sf->rt_sf.use_nonrd_altref_frame = 0;
871     sf->rt_sf.nonrd_prune_ref_frame_search = 2;
872     sf->rt_sf.nonrd_check_partition_merge_mode = 0;
873     sf->rt_sf.nonrd_check_partition_split = 0;
874     sf->rt_sf.use_modeled_non_rd_cost = 1;
875     sf->rt_sf.source_metrics_sb_nonrd = 1;
876     sf->interp_sf.cb_pred_filter_search = 1;
877   }
878 }
879 
init_hl_sf(HIGH_LEVEL_SPEED_FEATURES * hl_sf)880 static AOM_INLINE void init_hl_sf(HIGH_LEVEL_SPEED_FEATURES *hl_sf) {
881   // best quality defaults
882   hl_sf->frame_parameter_update = 1;
883   hl_sf->recode_loop = ALLOW_RECODE;
884   hl_sf->disable_overlay_frames = 0;
885   hl_sf->adaptive_overlay_encoding = 1;
886   // Recode loop tolerance %.
887   hl_sf->recode_tolerance = 25;
888   hl_sf->high_precision_mv_usage = CURRENT_Q;
889   hl_sf->second_alt_ref_filtering = 1;
890 }
891 
init_tpl_sf(TPL_SPEED_FEATURES * tpl_sf)892 static AOM_INLINE void init_tpl_sf(TPL_SPEED_FEATURES *tpl_sf) {
893   tpl_sf->prune_intra_modes = 0;
894   tpl_sf->reduce_first_step_size = 0;
895   tpl_sf->skip_alike_starting_mv = 0;
896   tpl_sf->subpel_force_stop = EIGHTH_PEL;
897 }
898 
init_gm_sf(GLOBAL_MOTION_SPEED_FEATURES * gm_sf)899 static AOM_INLINE void init_gm_sf(GLOBAL_MOTION_SPEED_FEATURES *gm_sf) {
900   gm_sf->gm_erroradv_type = GM_ERRORADV_TR_0;
901   gm_sf->disable_adaptive_warp_error_thresh = 1;
902   gm_sf->selective_ref_gm = 1;
903   gm_sf->gm_search_type = GM_FULL_SEARCH;
904   gm_sf->gm_disable_recode = 0;
905   gm_sf->prune_ref_frame_for_gm_search = 0;
906 }
907 
init_part_sf(PARTITION_SPEED_FEATURES * part_sf)908 static AOM_INLINE void init_part_sf(PARTITION_SPEED_FEATURES *part_sf) {
909   part_sf->partition_search_type = SEARCH_PARTITION;
910   part_sf->less_rectangular_check_level = 0;
911   part_sf->use_square_partition_only_threshold = BLOCK_128X128;
912   part_sf->auto_max_partition_based_on_simple_motion = NOT_IN_USE;
913   part_sf->auto_min_partition_based_on_simple_motion = 0;
914   part_sf->default_max_partition_size = BLOCK_LARGEST;
915   part_sf->default_min_partition_size = BLOCK_4X4;
916   part_sf->adjust_var_based_rd_partitioning = 0;
917   part_sf->allow_partition_search_skip = 0;
918   part_sf->max_intra_bsize = BLOCK_LARGEST;
919   // This setting only takes effect when partition_search_type is set
920   // to FIXED_PARTITION.
921   part_sf->always_this_block_size = BLOCK_16X16;
922   // Recode loop tolerance %.
923   part_sf->partition_search_breakout_dist_thr = 0;
924   part_sf->partition_search_breakout_rate_thr = 0;
925   part_sf->prune_ext_partition_types_search_level = 0;
926   part_sf->ml_prune_rect_partition = 0;
927   part_sf->ml_prune_ab_partition = 0;
928   part_sf->ml_prune_4_partition = 0;
929   part_sf->ml_early_term_after_part_split_level = 0;
930   for (int i = 0; i < PARTITION_BLOCK_SIZES; ++i) {
931     part_sf->ml_partition_search_breakout_thresh[i] =
932         -1;  // -1 means not enabled.
933   }
934   part_sf->simple_motion_search_prune_agg = 0;
935   part_sf->simple_motion_search_split = 0;
936   part_sf->simple_motion_search_prune_rect = 0;
937   part_sf->simple_motion_search_early_term_none = 0;
938   part_sf->intra_cnn_split = 0;
939   part_sf->ext_partition_eval_thresh = BLOCK_8X8;
940   part_sf->prune_4_partition_using_split_info = 0;
941   part_sf->prune_ab_partition_using_split_info = 0;
942 }
943 
init_mv_sf(MV_SPEED_FEATURES * mv_sf)944 static AOM_INLINE void init_mv_sf(MV_SPEED_FEATURES *mv_sf) {
945   mv_sf->full_pixel_search_level = 0;
946   mv_sf->adaptive_motion_search = 0;
947   mv_sf->auto_mv_step_size = 0;
948   mv_sf->exhaustive_searches_thresh = 0;
949   mv_sf->obmc_full_pixel_search_level = 0;
950   mv_sf->prune_mesh_search = 0;
951   mv_sf->reduce_search_range = 0;
952   mv_sf->search_method = NSTEP;
953   mv_sf->simple_motion_subpel_force_stop = EIGHTH_PEL;
954   mv_sf->subpel_force_stop = EIGHTH_PEL;
955   mv_sf->subpel_iters_per_step = 2;
956   mv_sf->subpel_search_method = SUBPEL_TREE;
957   mv_sf->use_accurate_subpel_search = USE_8_TAPS;
958   mv_sf->use_fullpel_costlist = 0;
959 }
960 
init_inter_sf(INTER_MODE_SPEED_FEATURES * inter_sf)961 static AOM_INLINE void init_inter_sf(INTER_MODE_SPEED_FEATURES *inter_sf) {
962   inter_sf->comp_inter_joint_search_thresh = BLOCK_4X4;
963   inter_sf->adaptive_rd_thresh = 0;
964   inter_sf->model_based_post_interp_filter_breakout = 0;
965   inter_sf->reduce_inter_modes = 0;
966   inter_sf->adaptive_mode_search = 0;
967   inter_sf->alt_ref_search_fp = 0;
968   inter_sf->selective_ref_frame = 0;
969   inter_sf->prune_ref_frame_for_rect_partitions = 0;
970   inter_sf->disable_wedge_search_edge_thresh = 0;
971   inter_sf->disable_wedge_search_var_thresh = 0;
972   inter_sf->fast_wedge_sign_estimate = 0;
973   inter_sf->prune_wedge_pred_diff_based = 0;
974   inter_sf->use_dist_wtd_comp_flag = DIST_WTD_COMP_ENABLED;
975   inter_sf->reuse_inter_intra_mode = 0;
976   inter_sf->disable_sb_level_coeff_cost_upd = 0;
977   inter_sf->disable_sb_level_mv_cost_upd = 0;
978   inter_sf->prune_inter_modes_based_on_tpl = 0;
979   inter_sf->prune_comp_search_by_single_result = 0;
980   inter_sf->skip_repeated_ref_mv = 0;
981   inter_sf->skip_repeated_newmv = 0;
982   inter_sf->skip_repeated_full_newmv = 0;
983   inter_sf->prune_single_motion_modes_by_simple_trans = 0;
984   inter_sf->inter_mode_rd_model_estimation = 0;
985   inter_sf->prune_compound_using_single_ref = 0;
986   inter_sf->prune_compound_using_neighbors = 0;
987   inter_sf->disable_onesided_comp = 0;
988   inter_sf->prune_mode_search_simple_translation = 0;
989   inter_sf->prune_comp_type_by_comp_avg = 0;
990   inter_sf->disable_interinter_wedge_newmv_search = 0;
991   inter_sf->enable_interinter_diffwtd_newmv_search = 0;
992   inter_sf->disable_smooth_interintra = 0;
993   inter_sf->prune_motion_mode_level = 0;
994   inter_sf->prune_warp_using_wmtype = 0;
995   inter_sf->disable_wedge_interintra_search = 0;
996   inter_sf->fast_interintra_wedge_search = 0;
997   inter_sf->prune_comp_type_by_model_rd = 0;
998   inter_sf->perform_best_rd_based_gating_for_chroma = 0;
999   inter_sf->prune_obmc_prob_thresh = 0;
1000   inter_sf->disable_obmc = 0;
1001   inter_sf->disable_interinter_wedge = 0;
1002   inter_sf->prune_ref_mv_idx_search = 0;
1003   inter_sf->prune_warped_prob_thresh = 0;
1004   inter_sf->reuse_compound_type_decision = 0;
1005   inter_sf->txfm_rd_gate_level = 0;
1006   inter_sf->prune_inter_modes_if_skippable = 0;
1007 }
1008 
init_interp_sf(INTERP_FILTER_SPEED_FEATURES * interp_sf)1009 static AOM_INLINE void init_interp_sf(INTERP_FILTER_SPEED_FEATURES *interp_sf) {
1010   interp_sf->disable_filter_search_var_thresh = 0;
1011   interp_sf->adaptive_interp_filter_search = 0;
1012   interp_sf->use_fast_interpolation_filter_search = 0;
1013   interp_sf->disable_dual_filter = 0;
1014   interp_sf->use_interp_filter = 0;
1015   interp_sf->skip_sharp_interp_filter_search = 0;
1016 }
1017 
init_intra_sf(INTRA_MODE_SPEED_FEATURES * intra_sf)1018 static AOM_INLINE void init_intra_sf(INTRA_MODE_SPEED_FEATURES *intra_sf) {
1019   intra_sf->skip_intra_in_interframe = 1;
1020   intra_sf->intra_pruning_with_hog = 0;
1021   intra_sf->src_var_thresh_intra_skip = 1;
1022   intra_sf->prune_palette_search_level = 0;
1023 
1024   for (int i = 0; i < TX_SIZES; i++) {
1025     intra_sf->intra_y_mode_mask[i] = INTRA_ALL;
1026     intra_sf->intra_uv_mode_mask[i] = UV_INTRA_ALL;
1027   }
1028   intra_sf->disable_smooth_intra = 0;
1029 }
1030 
init_tx_sf(TX_SPEED_FEATURES * tx_sf)1031 static AOM_INLINE void init_tx_sf(TX_SPEED_FEATURES *tx_sf) {
1032   tx_sf->inter_tx_size_search_init_depth_sqr = 0;
1033   tx_sf->inter_tx_size_search_init_depth_rect = 0;
1034   tx_sf->intra_tx_size_search_init_depth_rect = 0;
1035   tx_sf->intra_tx_size_search_init_depth_sqr = 0;
1036   tx_sf->tx_size_search_lgr_block = 0;
1037   tx_sf->model_based_prune_tx_search_level = 0;
1038   tx_sf->tx_type_search.prune_mode = PRUNE_2D_ACCURATE;
1039   tx_sf->tx_type_search.ml_tx_split_thresh = 8500;
1040   tx_sf->tx_type_search.use_skip_flag_prediction = 1;
1041   tx_sf->tx_type_search.use_reduced_intra_txset = 0;
1042   tx_sf->tx_type_search.fast_intra_tx_type_search = 0;
1043   tx_sf->tx_type_search.fast_inter_tx_type_search = 0;
1044   tx_sf->tx_type_search.skip_tx_search = 0;
1045   tx_sf->tx_type_search.prune_tx_type_using_stats = 0;
1046   tx_sf->tx_type_search.prune_tx_type_est_rd = 0;
1047   tx_sf->tx_type_search.enable_winner_mode_tx_type_pruning = 0;
1048   tx_sf->txb_split_cap = 1;
1049   tx_sf->adaptive_txb_search_level = 0;
1050   tx_sf->use_intra_txb_hash = 0;
1051   tx_sf->use_inter_txb_hash = 1;
1052   tx_sf->refine_fast_tx_search_results = 1;
1053 }
1054 
init_rd_sf(RD_CALC_SPEED_FEATURES * rd_sf,const AV1_COMP * cpi)1055 static AOM_INLINE void init_rd_sf(RD_CALC_SPEED_FEATURES *rd_sf,
1056                                   const AV1_COMP *cpi) {
1057   if (cpi->oxcf.disable_trellis_quant == 3) {
1058     rd_sf->optimize_coefficients = !is_lossless_requested(&cpi->oxcf)
1059                                        ? NO_ESTIMATE_YRD_TRELLIS_OPT
1060                                        : NO_TRELLIS_OPT;
1061   } else if (cpi->oxcf.disable_trellis_quant == 2) {
1062     rd_sf->optimize_coefficients = !is_lossless_requested(&cpi->oxcf)
1063                                        ? FINAL_PASS_TRELLIS_OPT
1064                                        : NO_TRELLIS_OPT;
1065   } else if (cpi->oxcf.disable_trellis_quant == 0) {
1066     if (is_lossless_requested(&cpi->oxcf)) {
1067       rd_sf->optimize_coefficients = NO_TRELLIS_OPT;
1068     } else {
1069       rd_sf->optimize_coefficients = FULL_TRELLIS_OPT;
1070     }
1071   } else if (cpi->oxcf.disable_trellis_quant == 1) {
1072     rd_sf->optimize_coefficients = NO_TRELLIS_OPT;
1073   } else {
1074     assert(0 && "Invalid disable_trellis_quant value");
1075   }
1076   // TODO(sarahparker) Pair this with a speed setting once experiments are done
1077   rd_sf->trellis_eob_fast = 0;
1078   rd_sf->use_mb_rd_hash = 1;
1079   rd_sf->optimize_b_precheck = 0;
1080   rd_sf->use_fast_coef_costing = 0;
1081   rd_sf->simple_model_rd_from_var = 0;
1082   rd_sf->tx_domain_dist_level = 0;
1083   rd_sf->tx_domain_dist_thres_level = 0;
1084   rd_sf->use_hash_based_trellis = 0;
1085   rd_sf->perform_coeff_opt = 0;
1086 }
1087 
init_winner_mode_sf(WINNER_MODE_SPEED_FEATURES * winner_mode_sf)1088 static AOM_INLINE void init_winner_mode_sf(
1089     WINNER_MODE_SPEED_FEATURES *winner_mode_sf) {
1090   winner_mode_sf->motion_mode_for_winner_cand = 0;
1091   // Set this at the appropriate speed levels
1092   winner_mode_sf->tx_size_search_level = USE_FULL_RD;
1093   winner_mode_sf->enable_winner_mode_for_coeff_opt = 0;
1094   winner_mode_sf->enable_winner_mode_for_tx_size_srch = 0;
1095   winner_mode_sf->enable_winner_mode_for_use_tx_domain_dist = 0;
1096   winner_mode_sf->enable_multiwinner_mode_process = 0;
1097 }
1098 
init_lpf_sf(LOOP_FILTER_SPEED_FEATURES * lpf_sf)1099 static AOM_INLINE void init_lpf_sf(LOOP_FILTER_SPEED_FEATURES *lpf_sf) {
1100   lpf_sf->disable_loop_restoration_chroma = 0;
1101   lpf_sf->prune_wiener_based_on_src_var = 0;
1102   lpf_sf->prune_sgr_based_on_wiener = 0;
1103   lpf_sf->enable_sgr_ep_pruning = 0;
1104   lpf_sf->reduce_wiener_window_size = 0;
1105   lpf_sf->lpf_pick = LPF_PICK_FROM_FULL_IMAGE;
1106   lpf_sf->cdef_pick_method = CDEF_FULL_SEARCH;
1107   // Set decoder side speed feature to use less dual sgr modes
1108   lpf_sf->dual_sgr_penalty_level = 0;
1109   lpf_sf->disable_lr_filter = 0;
1110 }
1111 
init_rt_sf(REAL_TIME_SPEED_FEATURES * rt_sf)1112 static AOM_INLINE void init_rt_sf(REAL_TIME_SPEED_FEATURES *rt_sf) {
1113   rt_sf->mode_search_skip_flags = 0;
1114   rt_sf->skip_interp_filter_search = 0;
1115   rt_sf->force_tx_search_off = 0;
1116   rt_sf->num_inter_modes_for_tx_search = INT_MAX;
1117   rt_sf->use_simple_rd_model = 0;
1118   rt_sf->nonrd_check_partition_merge_mode = 0;
1119   rt_sf->nonrd_check_partition_split = 0;
1120 }
1121 
av1_set_speed_features_framesize_dependent(AV1_COMP * cpi,int speed)1122 void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi, int speed) {
1123   SPEED_FEATURES *const sf = &cpi->sf;
1124   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
1125 
1126   if (oxcf->mode == GOOD) {
1127     set_good_speed_feature_framesize_dependent(cpi, sf, speed);
1128   } else if (oxcf->mode == REALTIME) {
1129     set_rt_speed_feature_framesize_dependent(cpi, sf, speed);
1130   }
1131 
1132   // This is only used in motion vector unit test.
1133   if (cpi->oxcf.motion_vector_unit_test == 1)
1134     cpi->mv_search_params.find_fractional_mv_step = av1_return_max_sub_pixel_mv;
1135   else if (cpi->oxcf.motion_vector_unit_test == 2)
1136     cpi->mv_search_params.find_fractional_mv_step = av1_return_min_sub_pixel_mv;
1137 
1138   MACROBLOCK *const x = &cpi->td.mb;
1139   AV1_COMMON *const cm = &cpi->common;
1140   x->min_partition_size = AOMMAX(sf->part_sf.default_min_partition_size,
1141                                  dim_to_size(cpi->oxcf.min_partition_size));
1142   x->max_partition_size = AOMMIN(sf->part_sf.default_max_partition_size,
1143                                  dim_to_size(cpi->oxcf.max_partition_size));
1144   x->min_partition_size = AOMMIN(x->min_partition_size, cm->seq_params.sb_size);
1145   x->max_partition_size = AOMMIN(x->max_partition_size, cm->seq_params.sb_size);
1146 }
1147 
av1_set_speed_features_framesize_independent(AV1_COMP * cpi,int speed)1148 void av1_set_speed_features_framesize_independent(AV1_COMP *cpi, int speed) {
1149   AV1_COMMON *const cm = &cpi->common;
1150   SPEED_FEATURES *const sf = &cpi->sf;
1151   MACROBLOCK *const x = &cpi->td.mb;
1152   WinnerModeParams *const winner_mode_params = &cpi->winner_mode_params;
1153   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
1154   int i;
1155 
1156   init_hl_sf(&sf->hl_sf);
1157   init_tpl_sf(&sf->tpl_sf);
1158   init_gm_sf(&sf->gm_sf);
1159   init_part_sf(&sf->part_sf);
1160   init_mv_sf(&sf->mv_sf);
1161   init_inter_sf(&sf->inter_sf);
1162   init_interp_sf(&sf->interp_sf);
1163   init_intra_sf(&sf->intra_sf);
1164   init_tx_sf(&sf->tx_sf);
1165   init_rd_sf(&sf->rd_sf, cpi);
1166   init_winner_mode_sf(&sf->winner_mode_sf);
1167   init_lpf_sf(&sf->lpf_sf);
1168   init_rt_sf(&sf->rt_sf);
1169 
1170   if (oxcf->mode == GOOD)
1171     set_good_speed_features_framesize_independent(cpi, sf, speed);
1172   else if (oxcf->mode == REALTIME)
1173     set_rt_speed_features_framesize_independent(cpi, sf, speed);
1174 
1175   if (!cpi->seq_params_locked) {
1176     cpi->common.seq_params.enable_dual_filter &=
1177         !sf->interp_sf.disable_dual_filter;
1178     cpi->common.seq_params.enable_restoration &= !sf->lpf_sf.disable_lr_filter;
1179   }
1180 
1181   // sf->part_sf.partition_search_breakout_dist_thr is set assuming max 64x64
1182   // blocks. Normalise this if the blocks are bigger.
1183   if (MAX_SB_SIZE_LOG2 > 6) {
1184     sf->part_sf.partition_search_breakout_dist_thr <<=
1185         2 * (MAX_SB_SIZE_LOG2 - 6);
1186   }
1187 
1188   const int mesh_speed = AOMMIN(speed, MAX_MESH_SPEED);
1189   for (i = 0; i < MAX_MESH_STEP; ++i) {
1190     sf->mv_sf.mesh_patterns[i].range =
1191         good_quality_mesh_patterns[mesh_speed][i].range;
1192     sf->mv_sf.mesh_patterns[i].interval =
1193         good_quality_mesh_patterns[mesh_speed][i].interval;
1194   }
1195 
1196   // Update the mesh pattern of exhaustive motion search for intraBC
1197   // Though intraBC mesh pattern is populated for all frame types, it is used
1198   // only for intra frames of screen contents
1199   for (i = 0; i < MAX_MESH_STEP; ++i) {
1200     sf->mv_sf.intrabc_mesh_patterns[i].range =
1201         intrabc_mesh_patterns[mesh_speed][i].range;
1202     sf->mv_sf.intrabc_mesh_patterns[i].interval =
1203         intrabc_mesh_patterns[mesh_speed][i].interval;
1204   }
1205 
1206   // Slow quant, dct and trellis not worthwhile for first pass
1207   // so make sure they are always turned off.
1208   if (is_stat_generation_stage(cpi))
1209     sf->rd_sf.optimize_coefficients = NO_TRELLIS_OPT;
1210 
1211   // No recode or trellis for 1 pass.
1212   if (oxcf->pass == 0) sf->hl_sf.recode_loop = DISALLOW_RECODE;
1213 
1214   MotionVectorSearchParams *const mv_search_params = &cpi->mv_search_params;
1215   if (sf->mv_sf.subpel_search_method == SUBPEL_TREE) {
1216     mv_search_params->find_fractional_mv_step = av1_find_best_sub_pixel_tree;
1217   } else if (sf->mv_sf.subpel_search_method == SUBPEL_TREE_PRUNED) {
1218     mv_search_params->find_fractional_mv_step =
1219         av1_find_best_sub_pixel_tree_pruned;
1220   } else if (sf->mv_sf.subpel_search_method == SUBPEL_TREE_PRUNED_MORE) {
1221     mv_search_params->find_fractional_mv_step =
1222         av1_find_best_sub_pixel_tree_pruned_more;
1223   } else if (sf->mv_sf.subpel_search_method == SUBPEL_TREE_PRUNED_EVENMORE) {
1224     mv_search_params->find_fractional_mv_step =
1225         av1_find_best_sub_pixel_tree_pruned_evenmore;
1226   }
1227 
1228   x->min_partition_size = AOMMAX(sf->part_sf.default_min_partition_size,
1229                                  dim_to_size(cpi->oxcf.min_partition_size));
1230   x->max_partition_size = AOMMIN(sf->part_sf.default_max_partition_size,
1231                                  dim_to_size(cpi->oxcf.max_partition_size));
1232   x->min_partition_size = AOMMIN(x->min_partition_size, cm->seq_params.sb_size);
1233   x->max_partition_size = AOMMIN(x->max_partition_size, cm->seq_params.sb_size);
1234 
1235   // This is only used in motion vector unit test.
1236   if (cpi->oxcf.motion_vector_unit_test == 1)
1237     mv_search_params->find_fractional_mv_step = av1_return_max_sub_pixel_mv;
1238   else if (cpi->oxcf.motion_vector_unit_test == 2)
1239     mv_search_params->find_fractional_mv_step = av1_return_min_sub_pixel_mv;
1240 
1241   // assert ensures that tx_domain_dist_level is accessed correctly
1242   assert(cpi->sf.rd_sf.tx_domain_dist_thres_level >= 0 &&
1243          cpi->sf.rd_sf.tx_domain_dist_thres_level < 3);
1244   memcpy(winner_mode_params->tx_domain_dist_threshold,
1245          tx_domain_dist_thresholds[cpi->sf.rd_sf.tx_domain_dist_thres_level],
1246          sizeof(winner_mode_params->tx_domain_dist_threshold));
1247 
1248   assert(cpi->sf.rd_sf.tx_domain_dist_level >= 0 &&
1249          cpi->sf.rd_sf.tx_domain_dist_level < 3);
1250   memcpy(winner_mode_params->use_transform_domain_distortion,
1251          tx_domain_dist_types[cpi->sf.rd_sf.tx_domain_dist_level],
1252          sizeof(winner_mode_params->use_transform_domain_distortion));
1253 
1254   // assert ensures that coeff_opt_dist_thresholds is accessed correctly
1255   assert(cpi->sf.rd_sf.perform_coeff_opt >= 0 &&
1256          cpi->sf.rd_sf.perform_coeff_opt < 6);
1257   memcpy(winner_mode_params->coeff_opt_dist_threshold,
1258          coeff_opt_dist_thresholds[cpi->sf.rd_sf.perform_coeff_opt],
1259          sizeof(winner_mode_params->coeff_opt_dist_threshold));
1260 
1261   // assert ensures that predict_skip_levels is accessed correctly
1262   assert(cpi->sf.tx_sf.tx_type_search.use_skip_flag_prediction >= 0 &&
1263          cpi->sf.tx_sf.tx_type_search.use_skip_flag_prediction < 3);
1264   memcpy(winner_mode_params->predict_skip_level,
1265          predict_skip_levels[cpi->sf.tx_sf.tx_type_search
1266                                  .use_skip_flag_prediction],
1267          sizeof(winner_mode_params->predict_skip_level));
1268 
1269   // assert ensures that tx_size_search_level is accessed correctly
1270   assert(cpi->sf.winner_mode_sf.tx_size_search_level >= 0 &&
1271          cpi->sf.winner_mode_sf.tx_size_search_level < 3);
1272   memcpy(winner_mode_params->tx_size_search_methods,
1273          tx_size_search_methods[cpi->sf.winner_mode_sf.tx_size_search_level],
1274          sizeof(winner_mode_params->tx_size_search_methods));
1275 
1276   if (cpi->oxcf.row_mt == 1 && (cpi->oxcf.max_threads > 1)) {
1277     if (sf->inter_sf.inter_mode_rd_model_estimation == 1) {
1278       // Revert to type 2
1279       sf->inter_sf.inter_mode_rd_model_estimation = 2;
1280     }
1281   }
1282 }
1283 
1284 // Override some speed features based on qindex
av1_set_speed_features_qindex_dependent(AV1_COMP * cpi,int speed)1285 void av1_set_speed_features_qindex_dependent(AV1_COMP *cpi, int speed) {
1286   AV1_COMMON *const cm = &cpi->common;
1287   SPEED_FEATURES *const sf = &cpi->sf;
1288   WinnerModeParams *const winner_mode_params = &cpi->winner_mode_params;
1289   const int boosted = frame_is_boosted(cpi);
1290   const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
1291   if (is_720p_or_larger && cpi->oxcf.mode == GOOD && speed == 0) {
1292     if (cm->quant_params.base_qindex <= 80) {
1293       sf->rd_sf.perform_coeff_opt = 2;
1294       memcpy(winner_mode_params->coeff_opt_dist_threshold,
1295              coeff_opt_dist_thresholds[sf->rd_sf.perform_coeff_opt],
1296              sizeof(winner_mode_params->coeff_opt_dist_threshold));
1297       sf->part_sf.simple_motion_search_split =
1298           cm->features.allow_screen_content_tools ? 1 : 2;
1299       sf->tx_sf.inter_tx_size_search_init_depth_rect = 1;
1300       sf->tx_sf.inter_tx_size_search_init_depth_sqr = 1;
1301       sf->tx_sf.intra_tx_size_search_init_depth_rect = 1;
1302     }
1303   }
1304 
1305   if (cpi->oxcf.mode == GOOD && speed >= 3) {
1306     // Disable extended partitions for lower quantizers
1307     if (cm->quant_params.base_qindex <= 100 &&
1308         !cm->features.allow_screen_content_tools && !boosted) {
1309       sf->part_sf.ext_partition_eval_thresh = BLOCK_128X128;
1310     }
1311   }
1312 
1313   if (cpi->oxcf.mode == GOOD && speed >= 4) {
1314     // Disable extended partitions for lower quantizers
1315     const int qindex_thresh = boosted ? 80 : 120;
1316     if (cm->quant_params.base_qindex <= qindex_thresh &&
1317         !cm->features.allow_screen_content_tools &&
1318         !frame_is_intra_only(&cpi->common)) {
1319       sf->part_sf.ext_partition_eval_thresh = BLOCK_128X128;
1320     }
1321   }
1322 }
1323