Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/third_party/aom/av1/encoder/   (Browser von der Mozilla Stiftung Version 136.0.1©)  Datei vom 10.2.2025 mit Größe 111 kB image not shown  

Quelle  speed_features.c   Sprache: C

 
/*
 * Copyright (c) 2016, Alliance for Open Media. All rights reserved.
 *
 * This source code is subject to the terms of the BSD 2 Clause License and
 * the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
 * was not distributed with this source code in the LICENSE file, you can
 * obtain it at www.aomedia.org/license/software. If the Alliance for Open
 * Media Patent License 1.0 was not distributed with this source code in the
 * PATENTS file, you can obtain it at www.aomedia.org/license/patent.
 */


#include <limits.h>

#include "av1/common/reconintra.h"

#include "av1/encoder/encoder.h"
#include "av1/encoder/speed_features.h"
#include "av1/encoder/rdopt.h"

#include "aom_dsp/aom_dsp_common.h"

#define MAX_MESH_SPEED 5  // Max speed setting for mesh motion method
// Max speed setting for tx domain evaluation
#define MAX_TX_DOMAIN_EVAL_SPEED 5
static const MESH_PATTERN
    good_quality_mesh_patterns[MAX_MESH_SPEED + 1][MAX_MESH_STEP] = {
      { { 64, 8 }, { 28, 4 }, { 15, 1 }, { 7, 1 } },
      { { 64, 8 }, { 28, 4 }, { 15, 1 }, { 7, 1 } },
      { { 64, 8 }, { 14, 2 }, { 7, 1 }, { 7, 1 } },
      { { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
      { { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
      { { 64, 16 }, { 24, 8 }, { 12, 4 }, { 7, 1 } },
    };

// TODO(huisu@google.com): These settings are pretty relaxed, tune them for
// each speed setting
static const MESH_PATTERN
    intrabc_mesh_patterns[MAX_MESH_SPEED + 1][MAX_MESH_STEP] = {
      { { 256, 1 }, { 256, 1 }, { 0, 0 }, { 0, 0 } },
      { { 256, 1 }, { 256, 1 }, { 0, 0 }, { 0, 0 } },
      { { 64, 1 }, { 64, 1 }, { 0, 0 }, { 0, 0 } },
      { { 64, 1 }, { 64, 1 }, { 0, 0 }, { 0, 0 } },
      { { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
      { { 64, 4 }, { 16, 1 }, { 0, 0 }, { 0, 0 } },
    };

// Threshold values to be used for pruning the txfm_domain_distortion
// based on block MSE
// Index 0: Default mode evaluation, Winner mode processing is not
// applicable (Eg : IntraBc). Index 1: Mode evaluation.
// Index 2: Winner mode evaluation. Index 1 and 2 are applicable when
// enable_winner_mode_for_use_tx_domain_dist speed feature is ON
// TODO(any): Experiment the threshold logic based on variance metric
static const unsigned int tx_domain_dist_thresholds[4][MODE_EVAL_TYPES] = {
  { UINT_MAX, UINT_MAX, UINT_MAX },
  { 22026, 22026, 22026 },
  { 1377, 1377, 1377 },
  { 0, 0, 0 }
};

// Number of different levels of aggressiveness in using transform domain
// distortion during the R-D evaluation based on the speed feature
// tx_domain_dist_level.
#define TX_DOMAIN_DIST_LEVELS 4

// Transform domain distortion type to be used for default, mode and winner mode
// evaluation Index 0: Default mode evaluation, Winner mode processing is not
// applicable (Eg : IntraBc). Index 1: Mode evaluation. Index 2: Winner mode
// evaluation. Index 1 and 2 are applicable when
// enable_winner_mode_for_use_tx_domain_dist speed feature is ON
static const unsigned int
    tx_domain_dist_types[TX_DOMAIN_DIST_LEVELS][MODE_EVAL_TYPES] = {
      { 0, 2, 0 }, { 1, 2, 0 }, { 2, 2, 0 }, { 2, 2, 2 }
    };

// Threshold values to be used for disabling coeff RD-optimization
// based on block MSE / qstep^2.
// TODO(any): Experiment the threshold logic based on variance metric.
// Table has satd and dist threshold value index 0 : dist,index 1: satd
// For each row, the indices are as follows.
// Index 0: Default mode evaluation, Winner mode processing is not applicable
// (Eg : IntraBc)
// Index 1: Mode evaluation.
// Index 2: Winner mode evaluation.
// Index 1 and 2 are applicable when enable_winner_mode_for_coeff_opt speed
// feature is ON
// There are 7 levels with increasing speed, mapping to vertical indices.
static const unsigned int coeff_opt_thresholds[9][MODE_EVAL_TYPES][2] = {
  { { UINT_MAX, UINT_MAX }, { UINT_MAX, UINT_MAX }, { UINT_MAX, UINT_MAX } },
  { { 3200, UINT_MAX }, { 250, UINT_MAX }, { UINT_MAX, UINT_MAX } },
  { { 1728, UINT_MAX }, { 142, UINT_MAX }, { UINT_MAX, UINT_MAX } },
  { { 864, UINT_MAX }, { 142, UINT_MAX }, { UINT_MAX, UINT_MAX } },
  { { 432, UINT_MAX }, { 86, UINT_MAX }, { UINT_MAX, UINT_MAX } },
  { { 864, 97 }, { 142, 16 }, { UINT_MAX, UINT_MAX } },
  { { 432, 97 }, { 86, 16 }, { UINT_MAX, UINT_MAX } },
  { { 216, 25 }, { 86, 10 }, { UINT_MAX, UINT_MAX } },
  { { 216, 25 }, { 0, 10 }, { UINT_MAX, UINT_MAX } }
};

// Transform size to be used for default, mode and winner mode evaluation
// Index 0: Default mode evaluation, Winner mode processing is not applicable
// (Eg : IntraBc) Index 1: Mode evaluation. Index 2: Winner mode evaluation.
// Index 1 and 2 are applicable when enable_winner_mode_for_tx_size_srch speed
// feature is ON
static const TX_SIZE_SEARCH_METHOD
    tx_size_search_methods[4][MODE_EVAL_TYPES] = {
      { USE_FULL_RD, USE_LARGESTALL, USE_FULL_RD },
      { USE_FAST_RD, USE_LARGESTALL, USE_FULL_RD },
      { USE_LARGESTALL, USE_LARGESTALL, USE_FULL_RD },
      { USE_LARGESTALL, USE_LARGESTALL, USE_LARGESTALL }
    };

// Predict transform skip levels to be used for default, mode and winner mode
// evaluation. Index 0: Default mode evaluation, Winner mode processing is not
// applicable. Index 1: Mode evaluation, Index 2: Winner mode evaluation
// Values indicate the aggressiveness of skip flag prediction.
// 0 : no early skip prediction
// 1 : conservative early skip prediction using DCT_DCT
// 2 : early skip prediction based on SSE
static const unsigned int predict_skip_levels[3][MODE_EVAL_TYPES] = {
  { 0, 0, 0 }, { 1, 1, 1 }, { 1, 2, 1 }
};

// Predict skip or DC block level used during transform type search. It is
// indexed using the following:
// First index  : Speed feature 'dc_blk_pred_level' (0 to 3)
// Second index : Mode evaluation type (DEFAULT_EVAL, MODE_EVAL and
// WINNER_MODE_EVAL).
//
// The values of predict_dc_levels[][] indicate the aggressiveness of predicting
// a block as transform skip or DC only.
// Type 0 : No skip block or DC only block prediction
// Type 1 : Prediction of skip block based on residual mean and variance
// Type 2 : Prediction of skip block or DC only block based on residual mean and
// variance
static const unsigned int predict_dc_levels[4][MODE_EVAL_TYPES] = {
  { 0, 0, 0 }, { 1, 1, 0 }, { 2, 2, 0 }, { 2, 2, 2 }
};

#if !CONFIG_FPMT_TEST
// This table holds the maximum number of reference frames for global motion.
// The table is indexed as per the speed feature 'gm_search_type'.
// 0 : All reference frames are allowed.
// 1 : All reference frames except L2 and L3 are allowed.
// 2 : All reference frames except L2, L3 and ARF2 are allowed.
// 3 : No reference frame is allowed.
static const int gm_available_reference_frames[GM_DISABLE_SEARCH + 1] = {
  INTER_REFS_PER_FRAME, INTER_REFS_PER_FRAME - 2, INTER_REFS_PER_FRAME - 3, 0
};
#endif

// 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'.
// Aggressiveness increases from i = 0 to 2.
// j = 0: lower than 720p resolution, j = 1: 720p or larger resolution.
// Currently invoked only for speed 0, 1 and 2.
static const int ms_qindex_thresh[3][2][2] = { { { 200, 70 }, { MAXQ, 200 } },
                                               { { 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 const 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) {
  return frame_is_kf_gf_arf(cpi);
}

// Set transform rd gate level for all transform search cases.
static inline void set_txfm_rd_gate_level(
    int txfm_rd_gate_level[TX_SEARCH_CASES], int level) {
  assert(level <= MAX_TX_RD_GATE_LEVEL);
  for (int idx = 0; idx < TX_SEARCH_CASES; idx++)
    txfm_rd_gate_level[idx] = level;
}

static void set_allintra_speed_feature_framesize_dependent(
    const AV1_COMP *const cpi, SPEED_FEATURES *const sf, int speed) {
  const AV1_COMMON *const cm = &cpi->common;
  const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
  const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
  const int is_1080p_or_larger = AOMMIN(cm->width, cm->height) >= 1080;
  const int is_4k_or_larger = AOMMIN(cm->width, cm->height) >= 2160;
  const bool use_hbd = cpi->oxcf.use_highbitdepth;

  if (is_480p_or_larger) {
    sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
    if (is_720p_or_larger)
      sf->part_sf.auto_max_partition_based_on_simple_motion = ADAPT_PRED;
    else
      sf->part_sf.auto_max_partition_based_on_simple_motion = RELAXED_PRED;
  } else {
    sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
    sf->part_sf.auto_max_partition_based_on_simple_motion = DIRECT_PRED;
    if (use_hbd) sf->tx_sf.prune_tx_size_level = 1;
  }

  if (is_4k_or_larger) {
    sf->part_sf.default_min_partition_size = BLOCK_8X8;
  }

  // TODO(huisu@google.com): train models for 720P and above.
  if (!is_720p_or_larger) {
    sf->part_sf.ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
    sf->part_sf.ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
    sf->part_sf.ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
    sf->part_sf.ml_partition_search_breakout_thresh[3] = 500;  // BLOCK_64X64
    sf->part_sf.ml_partition_search_breakout_thresh[4] = -1;   // BLOCK_128X128
    sf->part_sf.ml_early_term_after_part_split_level = 1;
  }

  if (is_720p_or_larger) {
    // TODO(chiyotsai@google.com): make this speed feature adaptive based on
    // current block's vertical texture instead of hardcoded with resolution
    sf->mv_sf.use_downsampled_sad = 2;
  }

  if (speed >= 1) {
    if (is_720p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
    } else if (is_480p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
    } else {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
    }

    if (!is_720p_or_larger) {
      sf->part_sf.ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
      sf->part_sf.ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
      sf->part_sf.ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
      sf->part_sf.ml_partition_search_breakout_thresh[3] = 300;  // BLOCK_64X64
      sf->part_sf.ml_partition_search_breakout_thresh[4] = -1;  // BLOCK_128X128
    }
    sf->part_sf.ml_early_term_after_part_split_level = 2;
  }

  if (speed >= 2) {
    if (is_720p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
    } else if (is_480p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
    } else {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
    }

    if (is_720p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
      sf->part_sf.partition_search_breakout_rate_thr = 120;
    } else {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 22);
      sf->part_sf.partition_search_breakout_rate_thr = 100;
    }

    if (is_480p_or_larger) {
      sf->tx_sf.tx_type_search.prune_tx_type_using_stats = 1;
      if (use_hbd) sf->tx_sf.prune_tx_size_level = 2;
    } else {
      if (use_hbd) sf->tx_sf.prune_tx_size_level = 3;
    }
  }

  if (speed >= 3) {
    sf->part_sf.ml_early_term_after_part_split_level = 0;

    if (is_720p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 25);
      sf->part_sf.partition_search_breakout_rate_thr = 200;
    } else {
      sf->part_sf.max_intra_bsize = BLOCK_32X32;
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 23);
      sf->part_sf.partition_search_breakout_rate_thr = 120;
    }
    if (use_hbd) sf->tx_sf.prune_tx_size_level = 3;
  }

  if (speed >= 4) {
    if (is_720p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 26);
    } else {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
    }

    if (is_480p_or_larger) {
      sf->tx_sf.tx_type_search.prune_tx_type_using_stats = 2;
    }
  }

  if (speed >= 6) {
    if (is_720p_or_larger) {
      sf->part_sf.auto_max_partition_based_on_simple_motion = NOT_IN_USE;
    } else if (is_480p_or_larger) {
      sf->part_sf.auto_max_partition_based_on_simple_motion = DIRECT_PRED;
    }

    if (is_1080p_or_larger) {
      sf->part_sf.default_min_partition_size = BLOCK_8X8;
    }

    sf->part_sf.use_square_partition_only_threshold = BLOCK_16X16;
  }

  if (speed >= 7) {
    // TODO(kyslov): add more speed features to control speed/quality
  }

  if (speed >= 8) {
    if (!is_480p_or_larger) {
      sf->rt_sf.nonrd_check_partition_merge_mode = 2;
    }
    if (is_720p_or_larger) {
      sf->rt_sf.force_large_partition_blocks_intra = 1;
    }
  }

  if (speed >= 9) {
    // TODO(kyslov): add more speed features to control speed/quality
    if (!is_4k_or_larger) {
      // In av1_select_sb_size(), superblock size is set to 64x64 only for
      // resolutions less than 4k in speed>=9, to improve the multithread
      // performance. If cost update levels are set to INTERNAL_COST_UPD_OFF
      // for resolutions >= 4k, the SB size setting can be modified for these
      // resolutions as well.
      sf->inter_sf.coeff_cost_upd_level = INTERNAL_COST_UPD_OFF;
      sf->inter_sf.mode_cost_upd_level = INTERNAL_COST_UPD_OFF;
    }
  }
}

static void set_allintra_speed_features_framesize_independent(
    const AV1_COMP *const cpi, SPEED_FEATURES *const sf, int speed) {
  const AV1_COMMON *const cm = &cpi->common;
  const int allow_screen_content_tools =
      cm->features.allow_screen_content_tools;
  const int use_hbd = cpi->oxcf.use_highbitdepth;

  sf->part_sf.less_rectangular_check_level = 1;
  sf->part_sf.ml_prune_partition = 1;
  sf->part_sf.prune_ext_partition_types_search_level = 1;
  sf->part_sf.prune_part4_search = 2;
  sf->part_sf.simple_motion_search_prune_rect = 1;
  sf->part_sf.ml_predict_breakout_level = use_hbd ? 1 : 3;
  sf->part_sf.reuse_prev_rd_results_for_part_ab = 1;
  sf->part_sf.use_best_rd_for_pruning = 1;

  sf->intra_sf.intra_pruning_with_hog = 1;
  sf->intra_sf.prune_luma_palette_size_search_level = 1;
  sf->intra_sf.dv_cost_upd_level = INTERNAL_COST_UPD_OFF;
  sf->intra_sf.early_term_chroma_palette_size_search = 1;

  sf->tx_sf.adaptive_txb_search_level = 1;
  sf->tx_sf.intra_tx_size_search_init_depth_sqr = 1;
  sf->tx_sf.model_based_prune_tx_search_level = 1;
  sf->tx_sf.tx_type_search.use_reduced_intra_txset = 1;

  sf->rt_sf.use_nonrd_pick_mode = 0;
  sf->rt_sf.use_real_time_ref_set = 0;

  if (cpi->twopass_frame.fr_content_type == FC_GRAPHICS_ANIMATION ||
      cpi->use_screen_content_tools) {
    sf->mv_sf.exhaustive_searches_thresh = (1 << 20);
  } else {
    sf->mv_sf.exhaustive_searches_thresh = (1 << 25);
  }

  sf->rd_sf.perform_coeff_opt = 1;
  sf->hl_sf.superres_auto_search_type = SUPERRES_AUTO_DUAL;

  if (speed >= 1) {
    sf->part_sf.intra_cnn_based_part_prune_level =
        allow_screen_content_tools ? 0 : 2;
    sf->part_sf.simple_motion_search_early_term_none = 1;
    // TODO(Venkat): Clean-up frame type dependency for
    // simple_motion_search_split in partition search function and set the
    // speed feature accordingly
    sf->part_sf.simple_motion_search_split = allow_screen_content_tools ? 1 : 2;
    sf->part_sf.ml_predict_breakout_level = use_hbd ? 2 : 3;
    sf->part_sf.reuse_best_prediction_for_part_ab = 1;

    sf->mv_sf.exhaustive_searches_thresh <<= 1;

    sf->intra_sf.prune_palette_search_level = 1;
    sf->intra_sf.prune_luma_palette_size_search_level = 2;
    sf->intra_sf.top_intra_model_count_allowed = 3;

    sf->tx_sf.adaptive_txb_search_level = 2;
    sf->tx_sf.inter_tx_size_search_init_depth_rect = 1;
    sf->tx_sf.inter_tx_size_search_init_depth_sqr = 1;
    sf->tx_sf.intra_tx_size_search_init_depth_rect = 1;
    sf->tx_sf.model_based_prune_tx_search_level = 0;
    sf->tx_sf.tx_type_search.ml_tx_split_thresh = 4000;
    sf->tx_sf.tx_type_search.prune_2d_txfm_mode = TX_TYPE_PRUNE_2;
    sf->tx_sf.tx_type_search.skip_tx_search = 1;

    sf->rd_sf.perform_coeff_opt = 2;
    sf->rd_sf.tx_domain_dist_level = 1;
    sf->rd_sf.tx_domain_dist_thres_level = 1;

    sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL1;
    sf->lpf_sf.dual_sgr_penalty_level = 1;
    sf->lpf_sf.enable_sgr_ep_pruning = 1;
  }

  if (speed >= 2) {
    sf->mv_sf.auto_mv_step_size = 1;

    sf->intra_sf.disable_smooth_intra = 1;
    sf->intra_sf.intra_pruning_with_hog = 2;
    sf->intra_sf.prune_filter_intra_level = 1;

    sf->rd_sf.perform_coeff_opt = 3;

    sf->lpf_sf.prune_wiener_based_on_src_var = 1;
    sf->lpf_sf.prune_sgr_based_on_wiener = 1;
  }

  if (speed >= 3) {
    sf->hl_sf.high_precision_mv_usage = CURRENT_Q;
    sf->hl_sf.recode_loop = ALLOW_RECODE_KFARFGF;

    sf->part_sf.less_rectangular_check_level = 2;
    sf->part_sf.simple_motion_search_prune_agg = SIMPLE_AGG_LVL1;
    sf->part_sf.prune_ext_part_using_split_info = 1;

    sf->mv_sf.full_pixel_search_level = 1;
    sf->mv_sf.search_method = DIAMOND;

    // TODO(chiyotsai@google.com): the thresholds chosen for intra hog are
    // inherited directly from luma hog with some minor tweaking. Eventually we
    // should run this with a bayesian optimizer to find the Pareto frontier.
    sf->intra_sf.chroma_intra_pruning_with_hog = 2;
    sf->intra_sf.intra_pruning_with_hog = 3;
    sf->intra_sf.prune_palette_search_level = 2;

    sf->tx_sf.adaptive_txb_search_level = 2;
    sf->tx_sf.tx_type_search.use_skip_flag_prediction = 2;
    sf->tx_sf.use_rd_based_breakout_for_intra_tx_search = true;

    // TODO(any): evaluate if these lpf features can be moved to speed 2.
    // For screen content, "prune_sgr_based_on_wiener = 2" cause large quality
    // loss.
    sf->lpf_sf.prune_sgr_based_on_wiener = allow_screen_content_tools ? 1 : 2;
    sf->lpf_sf.disable_loop_restoration_chroma = 0;
    sf->lpf_sf.reduce_wiener_window_size = 1;
    sf->lpf_sf.prune_wiener_based_on_src_var = 2;
  }

  if (speed >= 4) {
    sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;

    sf->part_sf.simple_motion_search_prune_agg = SIMPLE_AGG_LVL2;
    sf->part_sf.simple_motion_search_reduce_search_steps = 4;
    sf->part_sf.prune_ext_part_using_split_info = 2;
    sf->part_sf.early_term_after_none_split = 1;
    sf->part_sf.ml_predict_breakout_level = 3;

    sf->intra_sf.prune_chroma_modes_using_luma_winner = 1;

    sf->mv_sf.simple_motion_subpel_force_stop = HALF_PEL;

    sf->tpl_sf.prune_starting_mv = 2;
    sf->tpl_sf.subpel_force_stop = HALF_PEL;
    sf->tpl_sf.search_method = FAST_BIGDIA;

    sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = 2;
    sf->tx_sf.tx_type_search.fast_intra_tx_type_search = 1;
    sf->tx_sf.tx_type_search.prune_2d_txfm_mode = TX_TYPE_PRUNE_3;
    sf->tx_sf.tx_type_search.prune_tx_type_est_rd = 1;

    sf->rd_sf.perform_coeff_opt = 5;
    sf->rd_sf.tx_domain_dist_thres_level = 3;

    sf->lpf_sf.lpf_pick = LPF_PICK_FROM_FULL_IMAGE_NON_DUAL;
    sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL3;

    sf->mv_sf.reduce_search_range = 1;

    sf->winner_mode_sf.enable_winner_mode_for_coeff_opt = 1;
    sf->winner_mode_sf.enable_winner_mode_for_use_tx_domain_dist = 1;
    sf->winner_mode_sf.multi_winner_mode_type = MULTI_WINNER_MODE_DEFAULT;
    sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch = 1;
  }

  if (speed >= 5) {
    sf->part_sf.simple_motion_search_prune_agg = SIMPLE_AGG_LVL3;
    sf->part_sf.ext_partition_eval_thresh =
        allow_screen_content_tools ? BLOCK_8X8 : BLOCK_16X16;
    sf->part_sf.intra_cnn_based_part_prune_level =
        allow_screen_content_tools ? 1 : 2;

    sf->intra_sf.chroma_intra_pruning_with_hog = 3;

    sf->lpf_sf.use_coarse_filter_level_search = 0;
    // Disable Wiener and Self-guided Loop restoration filters.
    sf->lpf_sf.disable_wiener_filter = true;
    sf->lpf_sf.disable_sgr_filter = true;

    sf->mv_sf.prune_mesh_search = PRUNE_MESH_SEARCH_LVL_2;

    sf->winner_mode_sf.multi_winner_mode_type = MULTI_WINNER_MODE_FAST;
  }

  if (speed >= 6) {
    sf->intra_sf.prune_smooth_intra_mode_for_chroma = 1;
    sf->intra_sf.prune_filter_intra_level = 2;
    sf->intra_sf.chroma_intra_pruning_with_hog = 4;
    sf->intra_sf.intra_pruning_with_hog = 4;
    sf->intra_sf.cfl_search_range = 1;
    sf->intra_sf.top_intra_model_count_allowed = 2;
    sf->intra_sf.adapt_top_model_rd_count_using_neighbors = 1;
    sf->intra_sf.prune_luma_odd_delta_angles_in_intra = 1;

    sf->part_sf.prune_rectangular_split_based_on_qidx =
        allow_screen_content_tools ? 0 : 2;
    sf->part_sf.prune_rect_part_using_4x4_var_deviation = true;
    sf->part_sf.prune_rect_part_using_none_pred_mode = true;
    sf->part_sf.prune_sub_8x8_partition_level =
        allow_screen_content_tools ? 0 : 1;
    sf->part_sf.prune_part4_search = 3;
    // TODO(jingning): This might not be a good trade off if the
    // target image quality is very low.
    sf->part_sf.default_max_partition_size = BLOCK_32X32;

    sf->mv_sf.use_bsize_dependent_search_method = 1;

    sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = 3;
    sf->tx_sf.tx_type_search.prune_tx_type_est_rd = 0;
    sf->tx_sf.prune_intra_tx_depths_using_nn = true;

    sf->rd_sf.perform_coeff_opt = 6;
    sf->rd_sf.tx_domain_dist_level = 3;

    sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL4;
    sf->lpf_sf.lpf_pick = LPF_PICK_FROM_Q;

    sf->winner_mode_sf.multi_winner_mode_type = MULTI_WINNER_MODE_OFF;
    sf->winner_mode_sf.prune_winner_mode_eval_level = 1;
    sf->winner_mode_sf.dc_blk_pred_level = 1;
  }
  // The following should make all-intra mode speed 7 approximately equal
  // to real-time speed 6,
  // all-intra speed 8 close to real-time speed 7, and all-intra speed 9
  // close to real-time speed 8
  if (speed >= 7) {
    sf->part_sf.default_min_partition_size = BLOCK_8X8;
    sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
    sf->lpf_sf.cdef_pick_method = CDEF_PICK_FROM_Q;
    sf->rt_sf.mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
    sf->rt_sf.var_part_split_threshold_shift = 7;
  }

  if (speed >= 8) {
    sf->rt_sf.hybrid_intra_pickmode = 1;
    sf->rt_sf.use_nonrd_pick_mode = 1;
    sf->rt_sf.nonrd_check_partition_merge_mode = 1;
    sf->rt_sf.var_part_split_threshold_shift = 8;
    // Set mask for intra modes.
    for (int i = 0; i < BLOCK_SIZES; ++i)
      if (i >= BLOCK_32X32)
        sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC;
      else
        // Use DC, H, V intra mode for block sizes < 32X32.
        sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC_H_V;
  }

  if (speed >= 9) {
    sf->inter_sf.coeff_cost_upd_level = INTERNAL_COST_UPD_SBROW;
    sf->inter_sf.mode_cost_upd_level = INTERNAL_COST_UPD_SBROW;

    sf->rt_sf.nonrd_check_partition_merge_mode = 0;
    sf->rt_sf.hybrid_intra_pickmode = 0;
    sf->rt_sf.var_part_split_threshold_shift = 9;
    sf->rt_sf.vbp_prune_16x16_split_using_min_max_sub_blk_var = true;
    sf->rt_sf.prune_h_pred_using_best_mode_so_far = true;
    sf->rt_sf.enable_intra_mode_pruning_using_neighbors = true;
    sf->rt_sf.prune_intra_mode_using_best_sad_so_far = true;
  }

  // As the speed feature prune_chroma_modes_using_luma_winner already
  // constrains the number of chroma directional mode evaluations to a maximum
  // of 1, the HOG computation and the associated pruning logic does not seem to
  // help speed-up the chroma mode evaluations. Hence disable the speed feature
  // chroma_intra_pruning_with_hog when prune_chroma_modes_using_luma_winner is
  // enabled.
  if (sf->intra_sf.prune_chroma_modes_using_luma_winner)
    sf->intra_sf.chroma_intra_pruning_with_hog = 0;
}

static void set_good_speed_feature_framesize_dependent(
    const AV1_COMP *const cpi, SPEED_FEATURES *const sf, int speed) {
  const AV1_COMMON *const cm = &cpi->common;
  const int is_480p_or_lesser = AOMMIN(cm->width, cm->height) <= 480;
  const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
  const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
  const int is_1080p_or_larger = AOMMIN(cm->width, cm->height) >= 1080;
  const int is_4k_or_larger = AOMMIN(cm->width, cm->height) >= 2160;
  const bool use_hbd = cpi->oxcf.use_highbitdepth;
  // Speed features applicable for temporal filtering and tpl modules may be
  // changed based on frame type at places where the sf is applied (Example :
  // use_downsampled_sad). This is because temporal filtering and tpl modules
  // are called before this function (except for the first key frame).
  // TODO(deepa.kg@ittiam.com): For the speed features applicable to temporal
  // filtering and tpl modules, modify the sf initialization appropriately
  // before calling the modules.
  const int boosted = frame_is_boosted(cpi);
  const int is_boosted_arf2_bwd_type =
      boosted ||
      cpi->ppi->gf_group.update_type[cpi->gf_frame_index] == INTNL_ARF_UPDATE;
  const int is_lf_frame =
      cpi->ppi->gf_group.update_type[cpi->gf_frame_index] == LF_UPDATE;
  const int allow_screen_content_tools =
      cm->features.allow_screen_content_tools;

  if (is_480p_or_larger) {
    sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
    if (is_720p_or_larger)
      sf->part_sf.auto_max_partition_based_on_simple_motion = ADAPT_PRED;
    else
      sf->part_sf.auto_max_partition_based_on_simple_motion = RELAXED_PRED;
  } else {
    sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
    sf->part_sf.auto_max_partition_based_on_simple_motion = DIRECT_PRED;
    if (use_hbd) sf->tx_sf.prune_tx_size_level = 1;
  }

  if (is_4k_or_larger) {
    sf->part_sf.default_min_partition_size = BLOCK_8X8;
  }

  // TODO(huisu@google.com): train models for 720P and above.
  if (!is_720p_or_larger) {
    sf->part_sf.ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
    sf->part_sf.ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
    sf->part_sf.ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
    sf->part_sf.ml_partition_search_breakout_thresh[3] = 500;  // BLOCK_64X64
    sf->part_sf.ml_partition_search_breakout_thresh[4] = -1;   // BLOCK_128X128
    sf->part_sf.ml_early_term_after_part_split_level = 1;
  }

  if (is_720p_or_larger) {
    // TODO(chiyotsai@google.com): make this speed feature adaptive based on
    // current block's vertical texture instead of hardcoded with resolution
    sf->mv_sf.use_downsampled_sad = 2;
  }

  if (!is_720p_or_larger) {
    const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg;
    const int rate_tolerance =
        AOMMIN(rc_cfg->under_shoot_pct, rc_cfg->over_shoot_pct);
    sf->hl_sf.recode_tolerance = 25 + (rate_tolerance >> 2);
  }

  if (speed >= 1) {
    if (is_480p_or_lesser) sf->inter_sf.skip_newmv_in_drl = 1;

    if (is_720p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
    } else if (is_480p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
    } else {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
    }

    if (!is_720p_or_larger) {
      sf->part_sf.ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
      sf->part_sf.ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
      sf->part_sf.ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
      sf->part_sf.ml_partition_search_breakout_thresh[3] = 300;  // BLOCK_64X64
      sf->part_sf.ml_partition_search_breakout_thresh[4] = -1;  // BLOCK_128X128
    }
    sf->part_sf.ml_early_term_after_part_split_level = 2;

    sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL1;
  }

  if (speed >= 2) {
    if (is_720p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
    } else if (is_480p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
    } else {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
    }

    if (is_720p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
      sf->part_sf.partition_search_breakout_rate_thr = 120;
    } else {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 22);
      sf->part_sf.partition_search_breakout_rate_thr = 100;
    }

    if (is_720p_or_larger) {
      sf->inter_sf.prune_obmc_prob_thresh = 16;
    } else {
      sf->inter_sf.prune_obmc_prob_thresh = 8;
    }

    if (is_480p_or_larger) {
      sf->inter_sf.disable_interintra_wedge_var_thresh = 100;
    } else {
      sf->inter_sf.disable_interintra_wedge_var_thresh = UINT_MAX;
    }

    if (is_480p_or_lesser) sf->inter_sf.skip_ext_comp_nearmv_mode = 1;

    if (is_720p_or_larger) {
      sf->inter_sf.limit_inter_mode_cands = is_lf_frame ? 1 : 0;
    } else {
      sf->inter_sf.limit_inter_mode_cands = is_lf_frame ? 2 : 0;
    }

    if (is_480p_or_larger) {
      sf->tx_sf.tx_type_search.prune_tx_type_using_stats = 1;
      if (use_hbd) sf->tx_sf.prune_tx_size_level = 2;
    } else {
      if (use_hbd) sf->tx_sf.prune_tx_size_level = 3;
      sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = boosted ? 0 : 1;
      sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch = boosted ? 0 : 1;
    }

    if (!is_720p_or_larger) {
      sf->mv_sf.disable_second_mv = 1;
      sf->mv_sf.auto_mv_step_size = 2;
    } else {
      sf->mv_sf.disable_second_mv = boosted ? 0 : 2;
      sf->mv_sf.auto_mv_step_size = 1;
    }

    if (!is_720p_or_larger) {
      sf->hl_sf.recode_tolerance = 50;
      sf->inter_sf.disable_interinter_wedge_newmv_search =
          is_boosted_arf2_bwd_type ? 0 : 1;
      sf->inter_sf.enable_fast_wedge_mask_search = 1;
    }
  }

  if (speed >= 3) {
    sf->inter_sf.enable_fast_wedge_mask_search = 1;
    sf->inter_sf.skip_newmv_in_drl = 2;
    sf->inter_sf.skip_ext_comp_nearmv_mode = 1;
    sf->inter_sf.limit_inter_mode_cands = is_lf_frame ? 3 : 0;
    sf->inter_sf.disable_interinter_wedge_newmv_search = boosted ? 0 : 1;
    sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = 1;
    sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch =
        frame_is_intra_only(&cpi->common) ? 0 : 1;

    sf->part_sf.ml_early_term_after_part_split_level = 0;

    if (is_720p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 25);
      sf->part_sf.partition_search_breakout_rate_thr = 200;
      sf->part_sf.skip_non_sq_part_based_on_none = is_lf_frame ? 2 : 0;
    } else {
      sf->part_sf.max_intra_bsize = BLOCK_32X32;
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 23);
      sf->part_sf.partition_search_breakout_rate_thr = 120;
      sf->part_sf.skip_non_sq_part_based_on_none = is_lf_frame ? 1 : 0;
    }
    if (use_hbd) sf->tx_sf.prune_tx_size_level = 3;

    if (is_480p_or_larger) {
      sf->part_sf.early_term_after_none_split = 1;
    } else {
      sf->part_sf.early_term_after_none_split = 0;
    }
    if (is_720p_or_larger) {
      sf->intra_sf.skip_intra_in_interframe = boosted ? 1 : 2;
    } else {
      sf->intra_sf.skip_intra_in_interframe = boosted ? 1 : 3;
    }

    if (is_720p_or_larger) {
      sf->inter_sf.disable_interinter_wedge_var_thresh = 100;
      sf->inter_sf.limit_txfm_eval_per_mode = boosted ? 0 : 1;
    } else {
      sf->inter_sf.disable_interinter_wedge_var_thresh = UINT_MAX;
      sf->inter_sf.limit_txfm_eval_per_mode = boosted ? 0 : 2;
      sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL2;
    }

    sf->inter_sf.disable_interintra_wedge_var_thresh = UINT_MAX;
  }

  if (speed >= 4) {
    sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = 2;
    sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch = 1;
    if (is_720p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 26);
    } else {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
    }
    sf->part_sf.early_term_after_none_split = 1;

    if (is_480p_or_larger) {
      sf->tx_sf.tx_type_search.prune_tx_type_using_stats = 2;
    } else {
      sf->mv_sf.skip_fullpel_search_using_startmv = boosted ? 0 : 1;
    }

    sf->inter_sf.disable_interinter_wedge_var_thresh = UINT_MAX;
    sf->inter_sf.prune_obmc_prob_thresh = INT_MAX;
    sf->inter_sf.limit_txfm_eval_per_mode = boosted ? 0 : 2;
    if (is_480p_or_lesser) sf->inter_sf.skip_newmv_in_drl = 3;

    if (is_720p_or_larger) {
      sf->inter_sf.prune_comp_ref_frames = 1;
    } else if (is_480p_or_larger) {
      sf->inter_sf.prune_comp_ref_frames = is_boosted_arf2_bwd_type ? 0 : 1;
    }

    if (is_720p_or_larger)
      sf->hl_sf.recode_tolerance = 32;
    else
      sf->hl_sf.recode_tolerance = 55;

    sf->intra_sf.skip_intra_in_interframe = 4;

    sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL3;
  }

  if (speed >= 5) {
    if (is_720p_or_larger) {
      sf->inter_sf.prune_warped_prob_thresh = 16;
    } else if (is_480p_or_larger) {
      sf->inter_sf.prune_warped_prob_thresh = 8;
    }
    if (is_720p_or_larger) sf->hl_sf.recode_tolerance = 40;

    sf->inter_sf.skip_newmv_in_drl = 4;
    sf->inter_sf.prune_comp_ref_frames = 1;
    sf->mv_sf.skip_fullpel_search_using_startmv = boosted ? 0 : 1;

    if (!is_720p_or_larger) {
      sf->inter_sf.mv_cost_upd_level = INTERNAL_COST_UPD_SBROW_SET;
      sf->inter_sf.prune_nearest_near_mv_using_refmv_weight =
          (boosted || allow_screen_content_tools) ? 0 : 1;
      sf->mv_sf.use_downsampled_sad = 1;
    }

    if (!is_480p_or_larger) {
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 26);
    }

    if (is_480p_or_lesser) {
      sf->inter_sf.prune_nearmv_using_neighbors = PRUNE_NEARMV_LEVEL1;
    } else {
      sf->inter_sf.prune_nearmv_using_neighbors = PRUNE_NEARMV_LEVEL2;
    }

    if (is_720p_or_larger)
      sf->part_sf.ext_part_eval_based_on_cur_best =
          (allow_screen_content_tools || frame_is_intra_only(cm)) ? 0 : 1;

    if (is_480p_or_larger) {
      sf->tpl_sf.reduce_num_frames = 1;
    }
  }

  if (speed >= 6) {
    sf->tx_sf.tx_type_search.winner_mode_tx_type_pruning = 4;
    sf->inter_sf.prune_nearmv_using_neighbors = PRUNE_NEARMV_LEVEL3;
    sf->inter_sf.prune_comp_ref_frames = 2;
    sf->inter_sf.prune_nearest_near_mv_using_refmv_weight =
        (boosted || allow_screen_content_tools) ? 0 : 1;
    sf->mv_sf.skip_fullpel_search_using_startmv = boosted ? 0 : 2;

    if (is_720p_or_larger) {
      sf->part_sf.auto_max_partition_based_on_simple_motion = NOT_IN_USE;
    } else if (is_480p_or_larger) {
      sf->part_sf.auto_max_partition_based_on_simple_motion = DIRECT_PRED;
    }

    if (is_480p_or_larger) {
      sf->hl_sf.allow_sub_blk_me_in_tf = 1;
    }

    if (is_1080p_or_larger) {
      sf->part_sf.default_min_partition_size = BLOCK_8X8;
    }

    if (is_720p_or_larger) {
      sf->inter_sf.disable_masked_comp = 1;
    }

    if (!is_720p_or_larger) {
      sf->inter_sf.coeff_cost_upd_level = INTERNAL_COST_UPD_SBROW;
      sf->inter_sf.mode_cost_upd_level = INTERNAL_COST_UPD_SBROW;
    }

    if (is_720p_or_larger) {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 28);
    } else {
      sf->part_sf.use_square_partition_only_threshold = BLOCK_16X16;
      sf->part_sf.partition_search_breakout_dist_thr = (1 << 26);
    }

    if (is_720p_or_larger) {
      sf->inter_sf.prune_ref_mv_idx_search = 2;
    } else {
      sf->inter_sf.prune_ref_mv_idx_search = 1;
    }

    if (!is_720p_or_larger) {
      sf->tx_sf.tx_type_search.fast_inter_tx_type_prob_thresh =
          is_boosted_arf2_bwd_type ? 450 : 150;
    }

    sf->lpf_sf.cdef_pick_method = CDEF_FAST_SEARCH_LVL4;

    sf->hl_sf.recode_tolerance = 55;
  }
}

static void set_good_speed_features_framesize_independent(
    const AV1_COMP *const cpi, SPEED_FEATURES *const sf, int speed) {
  const AV1_COMMON *const cm = &cpi->common;
  const GF_GROUP *const gf_group = &cpi->ppi->gf_group;
  const int boosted = frame_is_boosted(cpi);
  const int is_boosted_arf2_bwd_type =
      boosted || gf_group->update_type[cpi->gf_frame_index] == INTNL_ARF_UPDATE;
  const int is_inter_frame =
      gf_group->frame_type[cpi->gf_frame_index] == INTER_FRAME;
  const int allow_screen_content_tools =
      cm->features.allow_screen_content_tools;
  const int use_hbd = cpi->oxcf.use_highbitdepth;
  if (!cpi->oxcf.tile_cfg.enable_large_scale_tile) {
    sf->hl_sf.high_precision_mv_usage = LAST_MV_DATA;
  }

  // Speed 0 for all speed features that give neutral coding performance change.
  sf->gm_sf.gm_search_type = boosted ? GM_REDUCED_REF_SEARCH_SKIP_L2_L3_ARF2
                                     : GM_SEARCH_CLOSEST_REFS_ONLY;
  sf->gm_sf.prune_ref_frame_for_gm_search = boosted ? 0 : 1;
  sf->gm_sf.disable_gm_search_based_on_stats = 1;

  sf->part_sf.less_rectangular_check_level = 1;
  sf->part_sf.ml_prune_partition = 1;
  sf->part_sf.prune_ext_partition_types_search_level = 1;
  sf->part_sf.prune_part4_search = 2;
  sf->part_sf.simple_motion_search_prune_rect = 1;
  sf->part_sf.ml_predict_breakout_level = use_hbd ? 1 : 3;
  sf->part_sf.reuse_prev_rd_results_for_part_ab = 1;
  sf->part_sf.use_best_rd_for_pruning = 1;
  sf->part_sf.simple_motion_search_prune_agg =
      allow_screen_content_tools ? NO_PRUNING : SIMPLE_AGG_LVL0;

  // TODO(debargha): Test, tweak and turn on either 1 or 2
  sf->inter_sf.inter_mode_rd_model_estimation = 1;
  sf->inter_sf.model_based_post_interp_filter_breakout = 1;
  sf->inter_sf.prune_compound_using_single_ref = 1;
  sf->inter_sf.prune_mode_search_simple_translation = 1;
  sf->inter_sf.prune_ref_frame_for_rect_partitions =
      (boosted || (allow_screen_content_tools))
          ? 0
          : (is_boosted_arf2_bwd_type ? 1 : 2);
  sf->inter_sf.reduce_inter_modes = boosted ? 1 : 2;
  sf->inter_sf.selective_ref_frame = 1;
  sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;

  sf->interp_sf.use_fast_interpolation_filter_search = 1;

  sf->intra_sf.intra_pruning_with_hog = 1;

  sf->tx_sf.adaptive_txb_search_level = 1;
  sf->tx_sf.intra_tx_size_search_init_depth_sqr = 1;
  sf->tx_sf.model_based_prune_tx_search_level = 1;
  sf->tx_sf.tx_type_search.use_reduced_intra_txset = 1;

  sf->tpl_sf.search_method = NSTEP_8PT;

  sf->rt_sf.use_nonrd_pick_mode = 0;
  sf->rt_sf.use_real_time_ref_set = 0;

  if (cpi->twopass_frame.fr_content_type == FC_GRAPHICS_ANIMATION ||
      cpi->use_screen_content_tools) {
    sf->mv_sf.exhaustive_searches_thresh = (1 << 20);
  } else {
    sf->mv_sf.exhaustive_searches_thresh = (1 << 25);
  }

  sf->rd_sf.perform_coeff_opt = 1;
  sf->hl_sf.superres_auto_search_type = SUPERRES_AUTO_DUAL;

  if (speed >= 1) {
    sf->hl_sf.adjust_num_frames_for_arf_filtering =
        allow_screen_content_tools ? 0 : 1;

    sf->part_sf.intra_cnn_based_part_prune_level =
        allow_screen_content_tools ? 0 : 2;
    sf->part_sf.simple_motion_search_early_term_none = 1;
    // TODO(Venkat): Clean-up frame type dependency for
    // simple_motion_search_split in partition search function and set the
    // speed feature accordingly
    sf->part_sf.simple_motion_search_split = allow_screen_content_tools ? 1 : 2;
    sf->part_sf.ml_predict_breakout_level = use_hbd ? 2 : 3;

    sf->mv_sf.exhaustive_searches_thresh <<= 1;
    sf->mv_sf.obmc_full_pixel_search_level = 1;
    sf->mv_sf.use_accurate_subpel_search = USE_4_TAPS;
    sf->mv_sf.disable_extensive_joint_motion_search = 1;

    sf->inter_sf.prune_comp_search_by_single_result = boosted ? 2 : 1;
    sf->inter_sf.prune_comp_type_by_comp_avg = 1;
    sf->inter_sf.prune_comp_type_by_model_rd = boosted ? 0 : 1;
    sf->inter_sf.prune_ref_frame_for_rect_partitions =
        (frame_is_intra_only(&cpi->common) || (allow_screen_content_tools))
            ? 0
            : (boosted ? 1 : 2);
    sf->inter_sf.reduce_inter_modes = boosted ? 1 : 3;
    sf->inter_sf.reuse_inter_intra_mode = 1;
    sf->inter_sf.selective_ref_frame = 2;
    sf->inter_sf.skip_arf_compound = 1;

    sf->interp_sf.use_interp_filter = 1;

    sf->intra_sf.prune_palette_search_level = 1;

    sf->tx_sf.adaptive_txb_search_level = 2;
    sf->tx_sf.inter_tx_size_search_init_depth_rect = 1;
    sf->tx_sf.inter_tx_size_search_init_depth_sqr = 1;
    sf->tx_sf.intra_tx_size_search_init_depth_rect = 1;
    sf->tx_sf.model_based_prune_tx_search_level = 0;
    sf->tx_sf.tx_type_search.ml_tx_split_thresh = 4000;
    sf->tx_sf.tx_type_search.prune_2d_txfm_mode = TX_TYPE_PRUNE_2;
    sf->tx_sf.tx_type_search.skip_tx_search = 1;

    sf->rd_sf.perform_coeff_opt = boosted ? 2 : 3;
    sf->rd_sf.tx_domain_dist_level = boosted ? 1 : 2;
    sf->rd_sf.tx_domain_dist_thres_level = 1;

    sf->lpf_sf.dual_sgr_penalty_level = 1;
    sf->lpf_sf.enable_sgr_ep_pruning = 1;

    // TODO(any, yunqing): move this feature to speed 0.
    sf->tpl_sf.skip_alike_starting_mv = 1;
  }

  if (speed >= 2) {
    sf->hl_sf.recode_loop = ALLOW_RECODE_KFARFGF;

    sf->fp_sf.skip_motion_search_threshold = 25;

    sf->gm_sf.num_refinement_steps = 2;

    sf->part_sf.reuse_best_prediction_for_part_ab =
        !frame_is_intra_only(&cpi->common);

    sf->mv_sf.simple_motion_subpel_force_stop = QUARTER_PEL;
    sf->mv_sf.subpel_iters_per_step = 1;
    sf->mv_sf.reduce_search_range = 1;

    // TODO(chiyotsai@google.com): We can get 10% speed up if we move
    // adaptive_rd_thresh to speed 1. But currently it performs poorly on some
    // clips (e.g. 5% loss on dinner_1080p). We need to examine the sequence a
    // bit more closely to figure out why.
    sf->inter_sf.adaptive_rd_thresh = 1;
    sf->inter_sf.disable_interinter_wedge_var_thresh = 100;
    sf->inter_sf.fast_interintra_wedge_search = 1;
    sf->inter_sf.prune_comp_search_by_single_result = boosted ? 4 : 1;
    sf->inter_sf.prune_ext_comp_using_neighbors = 1;
    sf->inter_sf.prune_comp_using_best_single_mode_ref = 2;
    sf->inter_sf.prune_comp_type_by_comp_avg = 2;
    sf->inter_sf.selective_ref_frame = 3;
    sf->inter_sf.use_dist_wtd_comp_flag = DIST_WTD_COMP_DISABLED;
    sf->inter_sf.enable_fast_compound_mode_search = 1;
    sf->inter_sf.reuse_mask_search_results = 1;
    set_txfm_rd_gate_level(sf->inter_sf.txfm_rd_gate_level, boosted ? 0 : 1);
    sf->inter_sf.inter_mode_txfm_breakout = boosted ? 0 : 1;
    sf->inter_sf.alt_ref_search_fp = 1;

    sf->interp_sf.adaptive_interp_filter_search = 1;
    sf->interp_sf.disable_dual_filter = 1;

    sf->intra_sf.disable_smooth_intra =
        !frame_is_intra_only(&cpi->common) || (cpi->rc.frames_to_key > 1);
    sf->intra_sf.intra_pruning_with_hog = 2;
    sf->intra_sf.skip_intra_in_interframe = is_inter_frame ? 2 : 1;
    sf->intra_sf.skip_filter_intra_in_inter_frames = 1;

    sf->tpl_sf.prune_starting_mv = 1;
    sf->tpl_sf.search_method = DIAMOND;

    sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 3 : 4;
    sf->rd_sf.use_mb_rd_hash = 1;

    sf->lpf_sf.prune_wiener_based_on_src_var = 1;
    sf->lpf_sf.prune_sgr_based_on_wiener = 1;
    sf->lpf_sf.disable_loop_restoration_chroma = boosted ? 0 : 1;
    sf->lpf_sf.reduce_wiener_window_size = boosted ? 0 : 1;

    // TODO(any): Re-evaluate this feature set to 1 in speed 2.
    sf->tpl_sf.allow_compound_pred = 0;
    sf->tpl_sf.prune_ref_frames_in_tpl = 1;
  }

  if (speed >= 3) {
    sf->hl_sf.high_precision_mv_usage = CURRENT_Q;

    sf->gm_sf.prune_ref_frame_for_gm_search = 1;
    sf->gm_sf.prune_zero_mv_with_sse = 1;
    sf->gm_sf.num_refinement_steps = 0;

    sf->part_sf.less_rectangular_check_level = 2;
    sf->part_sf.simple_motion_search_prune_agg =
        allow_screen_content_tools
            ? SIMPLE_AGG_LVL0
            : (boosted ? SIMPLE_AGG_LVL1 : QIDX_BASED_AGG_LVL1);
    sf->part_sf.prune_ext_part_using_split_info = 1;
    sf->part_sf.simple_motion_search_rect_split = 1;

    sf->mv_sf.full_pixel_search_level = 1;
    sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED;
    sf->mv_sf.search_method = DIAMOND;
    sf->mv_sf.disable_second_mv = 2;
    sf->mv_sf.prune_mesh_search = PRUNE_MESH_SEARCH_LVL_1;
    sf->mv_sf.use_intrabc = 0;

    sf->inter_sf.disable_interinter_wedge_newmv_search = boosted ? 0 : 1;
    sf->inter_sf.mv_cost_upd_level = INTERNAL_COST_UPD_SBROW;
    sf->inter_sf.disable_onesided_comp = 1;
    sf->inter_sf.disable_interintra_wedge_var_thresh = UINT_MAX;
    // TODO(any): Experiment with the early exit mechanism for speeds 0, 1 and 2
    // and clean-up the speed feature
    sf->inter_sf.perform_best_rd_based_gating_for_chroma = 1;
    sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 1;
    sf->inter_sf.prune_comp_search_by_single_result = boosted ? 4 : 2;
    sf->inter_sf.selective_ref_frame = 5;
    sf->inter_sf.reuse_compound_type_decision = 1;
    set_txfm_rd_gate_level(sf->inter_sf.txfm_rd_gate_level,
                           boosted ? 0 : (is_boosted_arf2_bwd_type ? 1 : 2));
    sf->inter_sf.inter_mode_txfm_breakout = boosted ? 0 : 2;

    sf->interp_sf.adaptive_interp_filter_search = 2;

    // TODO(chiyotsai@google.com): the thresholds chosen for intra hog are
    // inherited directly from luma hog with some minor tweaking. Eventually we
    // should run this with a bayesian optimizer to find the Pareto frontier.
    sf->intra_sf.chroma_intra_pruning_with_hog = 2;
    sf->intra_sf.intra_pruning_with_hog = 3;
    sf->intra_sf.prune_palette_search_level = 2;
    sf->intra_sf.top_intra_model_count_allowed = 2;

    sf->tpl_sf.prune_starting_mv = 2;
    sf->tpl_sf.skip_alike_starting_mv = 2;
    sf->tpl_sf.prune_intra_modes = 1;
    sf->tpl_sf.reduce_first_step_size = 6;
    sf->tpl_sf.subpel_force_stop = QUARTER_PEL;
    sf->tpl_sf.gop_length_decision_method = 1;

    sf->tx_sf.adaptive_txb_search_level = boosted ? 2 : 3;
    sf->tx_sf.tx_type_search.use_skip_flag_prediction = 2;
    sf->tx_sf.tx_type_search.prune_2d_txfm_mode = TX_TYPE_PRUNE_3;

    // TODO(any): Refactor the code related to following winner mode speed
    // features
    sf->winner_mode_sf.enable_winner_mode_for_coeff_opt = 1;
    sf->winner_mode_sf.enable_winner_mode_for_use_tx_domain_dist = 1;
    sf->winner_mode_sf.motion_mode_for_winner_cand =
        boosted                                                          ? 0
        : gf_group->update_type[cpi->gf_frame_index] == INTNL_ARF_UPDATE ? 1
                                                                         : 2;
    sf->winner_mode_sf.prune_winner_mode_eval_level = boosted ? 0 : 4;

    // For screen content, "prune_sgr_based_on_wiener = 2" cause large quality
    // loss.
    sf->lpf_sf.prune_sgr_based_on_wiener = allow_screen_content_tools ? 1 : 2;
    sf->lpf_sf.prune_wiener_based_on_src_var = 2;
    sf->lpf_sf.use_coarse_filter_level_search =
        frame_is_intra_only(&cpi->common) ? 0 : 1;
    sf->lpf_sf.use_downsampled_wiener_stats = 1;
  }

  if (speed >= 4) {
    sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;

    sf->gm_sf.prune_zero_mv_with_sse = 2;
    sf->gm_sf.downsample_level = 1;

    sf->part_sf.simple_motion_search_prune_agg =
        allow_screen_content_tools ? SIMPLE_AGG_LVL0 : SIMPLE_AGG_LVL2;
    sf->part_sf.simple_motion_search_reduce_search_steps = 4;
    sf->part_sf.prune_ext_part_using_split_info = 2;
    sf->part_sf.ml_predict_breakout_level = 3;
    sf->part_sf.prune_rectangular_split_based_on_qidx =
        (allow_screen_content_tools || frame_is_intra_only(&cpi->common)) ? 0
                                                                          : 1;

    sf->inter_sf.alt_ref_search_fp = 2;
    sf->inter_sf.txfm_rd_gate_level[TX_SEARCH_DEFAULT] = boosted ? 0 : 3;
    sf->inter_sf.txfm_rd_gate_level[TX_SEARCH_MOTION_MODE] = boosted ? 0 : 5;
    sf->inter_sf.txfm_rd_gate_level[TX_SEARCH_COMP_TYPE_MODE] = boosted ? 0 : 3;

    sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 2;
    sf->inter_sf.prune_ext_comp_using_neighbors = 2;
    sf->inter_sf.prune_obmc_prob_thresh = INT_MAX;
    sf->inter_sf.disable_interinter_wedge_var_thresh = UINT_MAX;

    sf->interp_sf.cb_pred_filter_search = 1;
    sf->interp_sf.skip_sharp_interp_filter_search = 1;
    sf->interp_sf.use_interp_filter = 2;

    sf->intra_sf.intra_uv_mode_mask[TX_16X16] = UV_INTRA_DC_H_V_CFL;
    sf->intra_sf.intra_uv_mode_mask[TX_32X32] = UV_INTRA_DC_H_V_CFL;
    sf->intra_sf.intra_uv_mode_mask[TX_64X64] = UV_INTRA_DC_H_V_CFL;
    // TODO(any): "intra_y_mode_mask" doesn't help much at speed 4.
    // sf->intra_sf.intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
    // sf->intra_sf.intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
    // sf->intra_sf.intra_y_mode_mask[TX_64X64] = INTRA_DC_H_V;
    sf->intra_sf.skip_intra_in_interframe = 4;

    sf->mv_sf.simple_motion_subpel_force_stop = HALF_PEL;
    sf->mv_sf.prune_mesh_search = PRUNE_MESH_SEARCH_LVL_2;

    sf->tpl_sf.subpel_force_stop = HALF_PEL;
    sf->tpl_sf.search_method = FAST_BIGDIA;
    sf->tpl_sf.use_sad_for_mode_decision = 1;

    sf->tx_sf.tx_type_search.fast_intra_tx_type_search = 1;

    sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 5 : 7;

    // TODO(any): Extend multi-winner mode processing support for inter frames
    sf->winner_mode_sf.multi_winner_mode_type =
        frame_is_intra_only(&cpi->common) ? MULTI_WINNER_MODE_DEFAULT
                                          : MULTI_WINNER_MODE_OFF;
    sf->winner_mode_sf.dc_blk_pred_level = boosted ? 0 : 2;

    sf->lpf_sf.lpf_pick = LPF_PICK_FROM_FULL_IMAGE_NON_DUAL;
  }

  if (speed >= 5) {
    sf->hl_sf.weight_calc_level_in_tf = 1;
    sf->hl_sf.adjust_num_frames_for_arf_filtering =
        allow_screen_content_tools ? 0 : 2;

    sf->fp_sf.reduce_mv_step_param = 4;

    sf->part_sf.simple_motion_search_prune_agg =
        allow_screen_content_tools ? SIMPLE_AGG_LVL0 : SIMPLE_AGG_LVL3;
    sf->part_sf.ext_partition_eval_thresh =
        allow_screen_content_tools ? BLOCK_8X8 : BLOCK_16X16;
    sf->part_sf.prune_sub_8x8_partition_level =
        allow_screen_content_tools ? 1 : 2;

    sf->mv_sf.warp_search_method = WARP_SEARCH_DIAMOND;

    sf->inter_sf.prune_inter_modes_if_skippable = 1;
    sf->inter_sf.prune_single_ref = is_boosted_arf2_bwd_type ? 0 : 1;
    sf->inter_sf.txfm_rd_gate_level[TX_SEARCH_DEFAULT] = boosted ? 0 : 4;
    sf->inter_sf.txfm_rd_gate_level[TX_SEARCH_COMP_TYPE_MODE] = boosted ? 0 : 5;
    sf->inter_sf.enable_fast_compound_mode_search = 2;

    sf->interp_sf.skip_interp_filter_search = boosted ? 0 : 1;

    sf->intra_sf.chroma_intra_pruning_with_hog = 3;

    // TODO(any): Extend multi-winner mode processing support for inter frames
    sf->winner_mode_sf.multi_winner_mode_type =
        frame_is_intra_only(&cpi->common) ? MULTI_WINNER_MODE_FAST
                                          : MULTI_WINNER_MODE_OFF;

    // Disable Self-guided Loop restoration filter.
    sf->lpf_sf.disable_sgr_filter = true;
    sf->lpf_sf.disable_wiener_coeff_refine_search = true;

    sf->tpl_sf.prune_starting_mv = 3;
    sf->tpl_sf.use_y_only_rate_distortion = 1;
    sf->tpl_sf.subpel_force_stop = FULL_PEL;
    sf->tpl_sf.gop_length_decision_method = 2;
    sf->tpl_sf.use_sad_for_mode_decision = 2;

    sf->winner_mode_sf.dc_blk_pred_level = 2;

    sf->fp_sf.disable_recon = 1;
  }

  if (speed >= 6) {
    sf->hl_sf.disable_extra_sc_testing = 1;
    sf->hl_sf.second_alt_ref_filtering = 0;

    sf->gm_sf.downsample_level = 2;

    sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 3;
    sf->inter_sf.selective_ref_frame = 6;
    sf->inter_sf.prune_single_ref = is_boosted_arf2_bwd_type ? 0 : 2;
    sf->inter_sf.prune_ext_comp_using_neighbors = 3;

    sf->intra_sf.chroma_intra_pruning_with_hog = 4;
    sf->intra_sf.intra_pruning_with_hog = 4;
    sf->intra_sf.intra_uv_mode_mask[TX_32X32] = UV_INTRA_DC;
    sf->intra_sf.intra_uv_mode_mask[TX_64X64] = UV_INTRA_DC;
    sf->intra_sf.intra_y_mode_mask[TX_32X32] = INTRA_DC;
    sf->intra_sf.intra_y_mode_mask[TX_64X64] = INTRA_DC;
    sf->intra_sf.early_term_chroma_palette_size_search = 1;

    sf->part_sf.prune_rectangular_split_based_on_qidx =
        boosted || allow_screen_content_tools ? 0 : 2;

    sf->part_sf.prune_part4_search = 3;

    sf->mv_sf.simple_motion_subpel_force_stop = FULL_PEL;
    sf->mv_sf.use_bsize_dependent_search_method = 1;

    sf->tpl_sf.gop_length_decision_method = 3;

    sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 6 : 8;

    sf->winner_mode_sf.dc_blk_pred_level = 3;
    sf->winner_mode_sf.multi_winner_mode_type = MULTI_WINNER_MODE_OFF;

    sf->fp_sf.skip_zeromv_motion_search = 1;
  }
}

static void set_rt_speed_feature_framesize_dependent(const AV1_COMP *const cpi,
                                                     SPEED_FEATURES *const sf,
                                                     int speed) {
  const AV1_COMMON *const cm = &cpi->common;
  const int boosted = frame_is_boosted(cpi);
  const int is_1080p_or_larger = AOMMIN(cm->width, cm->height) >= 1080;
  const int is_720p_or_larger = AOMMIN(cm->width, cm->height) >= 720;
  const int is_480p_or_larger = AOMMIN(cm->width, cm->height) >= 480;
  const int is_360p_or_larger = AOMMIN(cm->width, cm->height) >= 360;

  if (!is_360p_or_larger) {
    sf->rt_sf.prune_intra_mode_based_on_mv_range = 1;
    sf->rt_sf.prune_inter_modes_wrt_gf_arf_based_on_sad = 1;
    if (speed >= 6)
      sf->winner_mode_sf.prune_winner_mode_eval_level = boosted ? 0 : 2;
    if (speed == 7) sf->rt_sf.prefer_large_partition_blocks = 2;
    if (speed >= 7) {
      sf->lpf_sf.cdef_pick_method = CDEF_PICK_FROM_Q;
      sf->rt_sf.check_only_zero_zeromv_on_large_blocks = true;
      sf->rt_sf.use_rtc_tf = 2;
    }
    if (speed == 8) sf->rt_sf.prefer_large_partition_blocks = 1;
    if (speed >= 8) {
      sf->rt_sf.use_nonrd_filter_search = 1;
      sf->rt_sf.tx_size_level_based_on_qstep = 1;
    }
    if (speed >= 9) {
      sf->rt_sf.use_comp_ref_nonrd = 0;
      sf->rt_sf.nonrd_aggressive_skip = 1;
      sf->rt_sf.skip_intra_pred = 1;
      // Only turn on enable_ref_short_signaling for low resolution when only
      // LAST and GOLDEN ref frames are used.
      sf->rt_sf.enable_ref_short_signaling =
          (!sf->rt_sf.use_nonrd_altref_frame &&
           (!sf->rt_sf.use_comp_ref_nonrd ||
            (!sf->rt_sf.ref_frame_comp_nonrd[1] &&
             !sf->rt_sf.ref_frame_comp_nonrd[2])));

// TODO(kyslov) Re-enable when AV1 models are trained
#if 0
#if CONFIG_RT_ML_PARTITIONING
      if (!frame_is_intra_only(cm)) {
        sf->part_sf.partition_search_type = ML_BASED_PARTITION;
        sf->rt_sf.reuse_inter_pred_nonrd = 0;
      }
#endif
#endif
      sf->rt_sf.use_adaptive_subpel_search = false;
    }
    if (speed >= 10) {
      // TODO(yunqingwang@google.com): To be conservative, disable
      // sf->rt_sf.estimate_motion_for_var_based_partition = 3 for speed 10/qvga
      // for now. May enable it in the future.
      sf->rt_sf.estimate_motion_for_var_based_partition = 0;
      sf->rt_sf.skip_intra_pred = 2;
      sf->rt_sf.hybrid_intra_pickmode = 3;
      sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 1;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 2;
      sf->rt_sf.use_nonrd_filter_search = 0;
    }
  } else {
    sf->rt_sf.prune_intra_mode_based_on_mv_range = 2;
    sf->intra_sf.skip_filter_intra_in_inter_frames = 1;
    if (speed <= 5) {
      sf->tx_sf.tx_type_search.fast_inter_tx_type_prob_thresh =
          boosted ? INT_MAX : 350;
      sf->winner_mode_sf.prune_winner_mode_eval_level = boosted ? 0 : 2;
    }
    if (speed == 6) sf->part_sf.disable_8x8_part_based_on_qidx = 1;
    if (speed >= 6) sf->rt_sf.skip_newmv_mode_based_on_sse = 2;
    if (speed == 7) {
      sf->rt_sf.prefer_large_partition_blocks = 1;
      // Enable this feature for [360p, 720p] resolution range initially.
      // Only enable for low bitdepth to mitigate issue: b/303023614.
      if (!cpi->rc.rtc_external_ratectrl &&
          AOMMIN(cm->width, cm->height) <= 720 && !cpi->oxcf.use_highbitdepth)
        sf->hl_sf.accurate_bit_estimate = cpi->oxcf.q_cfg.aq_mode == NO_AQ;
    }
    if (speed >= 7) {
      sf->rt_sf.use_rtc_tf = 1;
    }
    if (speed == 8 && !cpi->ppi->use_svc) {
      sf->rt_sf.short_circuit_low_temp_var = 0;
      sf->rt_sf.use_nonrd_altref_frame = 1;
    }
    if (speed >= 8) sf->rt_sf.tx_size_level_based_on_qstep = 2;
    if (speed >= 9) {
      sf->rt_sf.gf_length_lvl = 1;
      sf->rt_sf.skip_cdef_sb = 1;
      sf->rt_sf.sad_based_adp_altref_lag = 2;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 2;
      sf->rt_sf.use_adaptive_subpel_search = true;
      sf->interp_sf.cb_pred_filter_search = 1;
    }
    if (speed >= 10) {
      sf->rt_sf.hybrid_intra_pickmode = 2;
      sf->rt_sf.sad_based_adp_altref_lag = 4;
      sf->rt_sf.tx_size_level_based_on_qstep = 0;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 3;
      sf->rt_sf.use_adaptive_subpel_search = false;
      sf->interp_sf.cb_pred_filter_search = 2;
    }
  }
  if (!is_480p_or_larger) {
    if (speed == 7) {
      sf->rt_sf.nonrd_check_partition_merge_mode = 2;
    }
  }
  if (!is_720p_or_larger) {
    if (speed >= 9) {
      sf->rt_sf.force_large_partition_blocks_intra = 1;
    }
  } else {
    if (speed >= 6) sf->rt_sf.skip_newmv_mode_based_on_sse = 3;
    if (speed == 7) sf->rt_sf.prefer_large_partition_blocks = 0;
    if (speed >= 7) {
      sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 2;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 1;
    }
    if (speed >= 9) {
      sf->rt_sf.sad_based_adp_altref_lag = 1;
      sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 0;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 2;
    }
    if (speed >= 10) {
      sf->rt_sf.sad_based_adp_altref_lag = 3;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 3;
    }
  }
  // TODO(Any): Check/Tune settings of other sfs for 1080p.
  if (is_1080p_or_larger) {
    if (speed >= 7) {
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 0;
      sf->rt_sf.use_adaptive_subpel_search = 0;
    }
    if (speed >= 9) sf->interp_sf.cb_pred_filter_search = 0;
  } else {
    if (speed >= 9) sf->lpf_sf.cdef_pick_method = CDEF_PICK_FROM_Q;
    if (speed >= 10) sf->rt_sf.nonrd_aggressive_skip = 1;
  }
  // TODO(marpan): Tune settings for speed 11 video mode,
  if (speed >= 11 && cpi->oxcf.tune_cfg.content != AOM_CONTENT_SCREEN) {
    sf->rt_sf.skip_cdef_sb = 1;
    sf->rt_sf.force_only_last_ref = 1;
    sf->rt_sf.selective_cdf_update = 1;
    sf->rt_sf.use_nonrd_filter_search = 0;
    if (is_360p_or_larger) {
      sf->part_sf.fixed_partition_size = BLOCK_32X32;
      sf->rt_sf.use_fast_fixed_part = 1;
      sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 2;
    }
    sf->rt_sf.increase_source_sad_thresh = 1;
    sf->rt_sf.part_early_exit_zeromv = 2;
    sf->rt_sf.set_zeromv_skip_based_on_source_sad = 2;
    for (int i = 0; i < BLOCK_SIZES; ++i) {
      sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC;
    }
    sf->rt_sf.hybrid_intra_pickmode = 0;
  }
  // Setting for SVC, or when the ref_frame_config control is
  // used to set the reference structure.
  if (cpi->ppi->use_svc || cpi->ppi->rtc_ref.set_ref_frame_config) {
    const RTC_REF *const rtc_ref = &cpi->ppi->rtc_ref;
    // For SVC: for greater than 2 temporal layers, use better mv search on
    // base temporal layers, and only on base spatial layer if highest
    // resolution is above 640x360.
    if (cpi->svc.number_temporal_layers >= 2 &&
        cpi->svc.temporal_layer_id == 0 &&
        (cpi->svc.spatial_layer_id == 0 ||
         cpi->oxcf.frm_dim_cfg.width * cpi->oxcf.frm_dim_cfg.height <=
             640 * 360)) {
      sf->mv_sf.search_method = NSTEP;
      sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED;
      sf->rt_sf.fullpel_search_step_param = 10;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 0;
      if (cm->width * cm->height <= 352 * 288)
        sf->rt_sf.nonrd_prune_ref_frame_search = 2;
      sf->rt_sf.force_large_partition_blocks_intra = 0;
    }
    if (speed >= 8) {
      if (cpi->svc.number_temporal_layers > 2)
        sf->rt_sf.disable_cdf_update_non_reference_frame = true;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 3;
      if (rtc_ref->non_reference_frame) {
        sf->rt_sf.nonrd_aggressive_skip = 1;
        sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
      }
    }
    if (speed <= 9 && cpi->svc.number_temporal_layers > 2 &&
        cpi->svc.temporal_layer_id == 0)
      sf->rt_sf.check_only_zero_zeromv_on_large_blocks = false;
    else
      sf->rt_sf.check_only_zero_zeromv_on_large_blocks = true;
    sf->rt_sf.frame_level_mode_cost_update = false;

    // Compound mode enabling.
    if (rtc_ref->ref_frame_comp[0] || rtc_ref->ref_frame_comp[1] ||
        rtc_ref->ref_frame_comp[2]) {
      sf->rt_sf.use_comp_ref_nonrd = 1;
      sf->rt_sf.ref_frame_comp_nonrd[0] =
          rtc_ref->ref_frame_comp[0] && rtc_ref->reference[GOLDEN_FRAME - 1];
      sf->rt_sf.ref_frame_comp_nonrd[1] =
          rtc_ref->ref_frame_comp[1] && rtc_ref->reference[LAST2_FRAME - 1];
      sf->rt_sf.ref_frame_comp_nonrd[2] =
          rtc_ref->ref_frame_comp[2] && rtc_ref->reference[ALTREF_FRAME - 1];
    } else {
      sf->rt_sf.use_comp_ref_nonrd = 0;
    }

    if (cpi->svc.number_spatial_layers > 1 ||
        cpi->svc.number_temporal_layers > 1)
      sf->hl_sf.accurate_bit_estimate = 0;

    sf->rt_sf.estimate_motion_for_var_based_partition = 1;

    // For single layers RPS: bias/adjustment for recovery frame.
    if (cpi->ppi->rtc_ref.bias_recovery_frame) {
      sf->mv_sf.search_method = NSTEP;
      sf->mv_sf.subpel_search_method = SUBPEL_TREE;
      sf->rt_sf.fullpel_search_step_param = 8;
      sf->rt_sf.nonrd_aggressive_skip = 0;
    }
  }
  // Screen settings.
  if (cpi->oxcf.tune_cfg.content == AOM_CONTENT_SCREEN) {
    // TODO(marpan): Check settings for speed 7 and 8.
    if (speed >= 7) {
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 1;
      sf->mv_sf.use_bsize_dependent_search_method = 0;
      sf->rt_sf.skip_cdef_sb = 1;
      sf->rt_sf.increase_color_thresh_palette = 1;
      if (!frame_is_intra_only(cm)) sf->rt_sf.dct_only_palette_nonrd = 1;
    }
    if (speed >= 8) {
      sf->rt_sf.nonrd_check_partition_merge_mode = 3;
      sf->rt_sf.nonrd_prune_ref_frame_search = 1;
      sf->rt_sf.use_nonrd_filter_search = 0;
      sf->rt_sf.prune_hv_pred_modes_using_src_sad = false;
    }
    if (speed >= 9) {
      sf->rt_sf.prune_idtx_nonrd = 1;
      sf->rt_sf.part_early_exit_zeromv = 2;
      sf->rt_sf.skip_lf_screen = 1;
      sf->rt_sf.nonrd_prune_ref_frame_search = 3;
      sf->rt_sf.var_part_split_threshold_shift = 10;
      sf->mv_sf.subpel_search_method = SUBPEL_TREE_PRUNED_MORE;
      sf->rt_sf.reduce_mv_pel_precision_highmotion = 3;
      sf->rt_sf.reduce_mv_pel_precision_lowcomplex = 1;
      sf->lpf_sf.cdef_pick_method = CDEF_PICK_FROM_Q;
      sf->rt_sf.nonrd_check_partition_merge_mode = 0;
      sf->interp_sf.cb_pred_filter_search = 0;
    }
    if (speed >= 10) {
      if (cm->width * cm->height > 1920 * 1080)
        sf->part_sf.disable_8x8_part_based_on_qidx = 1;
      sf->rt_sf.screen_content_cdef_filter_qindex_thresh = 80;
      sf->rt_sf.part_early_exit_zeromv = 1;
      sf->rt_sf.nonrd_aggressive_skip = 1;
      sf->rt_sf.thresh_active_maps_skip_lf_cdef = 90;
      sf->rt_sf.hybrid_intra_pickmode = 0;
      sf->rt_sf.dct_only_palette_nonrd = 1;
      sf->rt_sf.prune_palette_search_nonrd = 1;
      sf->rt_sf.prune_intra_mode_using_best_sad_so_far = true;
      sf->rt_sf.rc_faster_convergence_static = 1;
      sf->rt_sf.rc_compute_spatial_var_sc = 1;
    }
    if (speed >= 11) {
      sf->rt_sf.skip_lf_screen = 2;
      sf->rt_sf.skip_cdef_sb = 2;
      sf->rt_sf.prune_palette_search_nonrd = 2;
      sf->rt_sf.increase_color_thresh_palette = 0;
      sf->rt_sf.prune_h_pred_using_best_mode_so_far = true;
      sf->rt_sf.enable_intra_mode_pruning_using_neighbors = true;
    }
    sf->rt_sf.skip_encoding_non_reference_slide_change =
        cpi->oxcf.rc_cfg.drop_frames_water_mark > 0 ? 1 : 0;
    sf->rt_sf.skip_newmv_flat_blocks_screen = 1;
    sf->rt_sf.use_idtx_nonrd = 1;
    sf->rt_sf.higher_thresh_scene_detection = 0;
    sf->rt_sf.use_nonrd_altref_frame = 0;
    sf->rt_sf.use_rtc_tf = 0;
    sf->rt_sf.use_comp_ref_nonrd = 0;
    sf->rt_sf.source_metrics_sb_nonrd = 1;
    if (cpi->rc.high_source_sad == 1) {
      sf->rt_sf.prefer_large_partition_blocks = 0;
      sf->part_sf.max_intra_bsize = BLOCK_128X128;
      for (int i = 0; i < BLOCK_SIZES; ++i) {
        if (i > BLOCK_32X32)
          sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC;
        else
          sf->rt_sf.intra_y_mode_bsize_mask_nrd[i] = INTRA_DC_H_V;
      }
    }
    if (speed >= 11 && cpi->rc.high_motion_content_screen_rtc) {
      sf->rt_sf.higher_thresh_scene_detection = 1;
      sf->rt_sf.force_only_last_ref = 1;
      sf->rt_sf.use_nonrd_filter_search = 0;
      sf->part_sf.fixed_partition_size = BLOCK_32X32;
      sf->rt_sf.use_fast_fixed_part = 1;
      sf->rt_sf.increase_source_sad_thresh = 1;
      sf->rt_sf.selective_cdf_update = 1;
      sf->mv_sf.search_method = FAST_DIAMOND;
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=91 H=95 G=92

¤ Dauer der Verarbeitung: 0.15 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.