Pack partition speed features into their own struct

BUG=aomedia:2562

Change-Id: I72f0fc829dcd4a8e91f223fe17aec6d7f71966f6
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 87c9ce1..244c551 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1904,8 +1904,8 @@
   setup_block_rdmult(cpi, x, mi_row, mi_col, bsize, NO_AQ, NULL);
 
   if (do_partition_search &&
-      cpi->sf.partition_search_type == SEARCH_PARTITION &&
-      cpi->sf.adjust_partitioning_from_last_frame) {
+      cpi->sf.part_sf.partition_search_type == SEARCH_PARTITION &&
+      cpi->sf.part_sf.adjust_partitioning_from_last_frame) {
     // Check if any of the sub blocks are further split.
     if (partition == PARTITION_SPLIT && subsize > BLOCK_8X8) {
       sub_subsize = get_partition_subsize(subsize, PARTITION_SPLIT);
@@ -2033,8 +2033,9 @@
         RDCOST(x->rdmult, last_part_rdc.rate, last_part_rdc.dist);
   }
 
-  if (do_partition_search && cpi->sf.adjust_partitioning_from_last_frame &&
-      cpi->sf.partition_search_type == SEARCH_PARTITION &&
+  if (do_partition_search &&
+      cpi->sf.part_sf.adjust_partitioning_from_last_frame &&
+      cpi->sf.part_sf.partition_search_type == SEARCH_PARTITION &&
       partition != PARTITION_SPLIT && bsize > BLOCK_8X8 &&
       (mi_row + bs < cm->mi_rows || mi_row + hbs == cm->mi_rows) &&
       (mi_col + bs < cm->mi_cols || mi_col + hbs == cm->mi_cols)) {
@@ -2637,7 +2638,7 @@
   if (bsize == BLOCK_16X16 && cpi->vaq_refresh)
     x->mb_energy = av1_log_block_var(cpi, x, bsize);
 
-  if (bsize > cpi->sf.use_square_partition_only_threshold) {
+  if (bsize > cpi->sf.part_sf.use_square_partition_only_threshold) {
     partition_horz_allowed &= !has_rows;
     partition_vert_allowed &= !has_cols;
   }
@@ -2663,7 +2664,7 @@
   // Use simple_motion_search to prune partitions. This must be done prior to
   // PARTITION_SPLIT to propagate the initial mvs to a smaller blocksize.
   const int try_split_only =
-      cpi->sf.simple_motion_search_split && do_square_split &&
+      cpi->sf.part_sf.simple_motion_search_split && do_square_split &&
       bsize >= BLOCK_8X8 && mi_row + mi_size_high[bsize] <= cm->mi_rows &&
       mi_col + mi_size_wide[bsize] <= cm->mi_cols && !frame_is_intra_only(cm) &&
       !av1_superres_scaled(cm);
@@ -2676,8 +2677,8 @@
   }
 
   const int try_prune_rect =
-      cpi->sf.simple_motion_search_prune_rect && !frame_is_intra_only(cm) &&
-      do_rectangular_split &&
+      cpi->sf.part_sf.simple_motion_search_prune_rect &&
+      !frame_is_intra_only(cm) && do_rectangular_split &&
       (do_square_split || partition_none_allowed ||
        (prune_horz && prune_vert)) &&
       (partition_horz_allowed || partition_vert_allowed) && bsize >= BLOCK_8X8;
@@ -2806,11 +2807,11 @@
       if (this_rdc.rdcost < best_rdc.rdcost) {
         // Adjust dist breakout threshold according to the partition size.
         const int64_t dist_breakout_thr =
-            cpi->sf.partition_search_breakout_dist_thr >>
+            cpi->sf.part_sf.partition_search_breakout_dist_thr >>
             ((2 * (MAX_SB_SIZE_LOG2 - 2)) -
              (mi_size_wide_log2[bsize] + mi_size_high_log2[bsize]));
         const int rate_breakout_thr =
-            cpi->sf.partition_search_breakout_rate_thr *
+            cpi->sf.part_sf.partition_search_breakout_rate_thr *
             num_pels_log2_lookup[bsize];
 
         best_rdc = this_rdc;
@@ -2821,7 +2822,7 @@
             (do_square_split || do_rectangular_split) &&
             !x->e_mbd.lossless[xd->mi[0]->segment_id] && ctx_none->skippable) {
           const int use_ml_based_breakout =
-              bsize <= cpi->sf.use_square_partition_only_threshold &&
+              bsize <= cpi->sf.part_sf.use_square_partition_only_threshold &&
               bsize > BLOCK_4X4 && xd->bd == 8;
           if (use_ml_based_breakout) {
             if (av1_ml_predict_breakout(cpi, bsize, x, &this_rdc,
@@ -2843,12 +2844,12 @@
           }
         }
 
-        if (cpi->sf.simple_motion_search_early_term_none && cm->show_frame &&
-            !frame_is_intra_only(cm) && bsize >= BLOCK_16X16 &&
-            mi_row + mi_step < cm->mi_rows && mi_col + mi_step < cm->mi_cols &&
-            this_rdc.rdcost < INT64_MAX && this_rdc.rdcost >= 0 &&
-            this_rdc.rate < INT_MAX && this_rdc.rate >= 0 &&
-            (do_square_split || do_rectangular_split)) {
+        if (cpi->sf.part_sf.simple_motion_search_early_term_none &&
+            cm->show_frame && !frame_is_intra_only(cm) &&
+            bsize >= BLOCK_16X16 && mi_row + mi_step < cm->mi_rows &&
+            mi_col + mi_step < cm->mi_cols && this_rdc.rdcost < INT64_MAX &&
+            this_rdc.rdcost >= 0 && this_rdc.rate < INT_MAX &&
+            this_rdc.rate >= 0 && (do_square_split || do_rectangular_split)) {
           av1_simple_motion_search_early_term_none(cpi, x, pc_tree, mi_row,
                                                    mi_col, bsize, &this_rdc,
                                                    &terminate_partition_search);
@@ -2941,10 +2942,10 @@
         found_best_partition = true;
         pc_tree->partitioning = PARTITION_SPLIT;
       }
-    } else if (cpi->sf.less_rectangular_check_level > 0) {
+    } else if (cpi->sf.part_sf.less_rectangular_check_level > 0) {
       // Skip rectangular partition test when partition type none gives better
       // rd than partition type split.
-      if (cpi->sf.less_rectangular_check_level == 2 || idx <= 2) {
+      if (cpi->sf.part_sf.less_rectangular_check_level == 2 || idx <= 2) {
         const int partition_none_valid = cur_none_rd > 0;
         const int partition_none_better = cur_none_rd < sum_rdc.rdcost;
         do_rectangular_split &=
@@ -2955,7 +2956,7 @@
     restore_context(x, &x_ctx, mi_row, mi_col, bsize, num_planes);
   }  // if (do_split)
 
-  if (cpi->sf.ml_early_term_after_part_split_level &&
+  if (cpi->sf.part_sf.ml_early_term_after_part_split_level &&
       !frame_is_intra_only(cm) && !terminate_partition_search &&
       do_rectangular_split &&
       (partition_horz_allowed || partition_vert_allowed)) {
@@ -2964,8 +2965,8 @@
                                   mi_col, &terminate_partition_search);
   }
 
-  if (!cpi->sf.ml_early_term_after_part_split_level &&
-      cpi->sf.ml_prune_rect_partition && !frame_is_intra_only(cm) &&
+  if (!cpi->sf.part_sf.ml_early_term_after_part_split_level &&
+      cpi->sf.part_sf.ml_prune_rect_partition && !frame_is_intra_only(cm) &&
       (partition_horz_allowed || partition_vert_allowed) &&
       !(prune_horz || prune_vert) && !terminate_partition_search) {
     av1_setup_src_planes(x, cpi->source, mi_row, mi_col, num_planes, bsize);
@@ -3181,8 +3182,8 @@
   }
 #endif
 
-  if (cpi->sf.prune_ext_partition_types_search_level) {
-    if (cpi->sf.prune_ext_partition_types_search_level == 1) {
+  if (cpi->sf.part_sf.prune_ext_partition_types_search_level) {
+    if (cpi->sf.part_sf.prune_ext_partition_types_search_level == 1) {
       // TODO(debargha,huisu@google.com): may need to tune the threshold for
       // pb_source_variance.
       horzab_partition_allowed &= (pc_tree->partitioning == PARTITION_HORZ ||
@@ -3210,10 +3211,10 @@
   }
   int horza_partition_allowed = horzab_partition_allowed;
   int horzb_partition_allowed = horzab_partition_allowed;
-  if (cpi->sf.prune_ext_partition_types_search_level) {
+  if (cpi->sf.part_sf.prune_ext_partition_types_search_level) {
     const int64_t horz_a_rd = horz_rd[1] + split_rd[0] + split_rd[1];
     const int64_t horz_b_rd = horz_rd[0] + split_rd[2] + split_rd[3];
-    switch (cpi->sf.prune_ext_partition_types_search_level) {
+    switch (cpi->sf.part_sf.prune_ext_partition_types_search_level) {
       case 1:
         horza_partition_allowed &= (horz_a_rd / 16 * 14 < best_rdc.rdcost);
         horzb_partition_allowed &= (horz_b_rd / 16 * 14 < best_rdc.rdcost);
@@ -3228,10 +3229,10 @@
 
   int verta_partition_allowed = vertab_partition_allowed;
   int vertb_partition_allowed = vertab_partition_allowed;
-  if (cpi->sf.prune_ext_partition_types_search_level) {
+  if (cpi->sf.part_sf.prune_ext_partition_types_search_level) {
     const int64_t vert_a_rd = vert_rd[1] + split_rd[0] + split_rd[2];
     const int64_t vert_b_rd = vert_rd[0] + split_rd[1] + split_rd[3];
-    switch (cpi->sf.prune_ext_partition_types_search_level) {
+    switch (cpi->sf.part_sf.prune_ext_partition_types_search_level) {
       case 1:
         verta_partition_allowed &= (vert_a_rd / 16 * 14 < best_rdc.rdcost);
         vertb_partition_allowed &= (vert_b_rd / 16 * 14 < best_rdc.rdcost);
@@ -3244,7 +3245,7 @@
     }
   }
 
-  if (cpi->sf.ml_prune_ab_partition && ext_partition_allowed &&
+  if (cpi->sf.part_sf.ml_prune_ab_partition && ext_partition_allowed &&
       partition_horz_allowed && partition_vert_allowed) {
     // TODO(huisu@google.com): x->source_variance may not be the current
     // block's variance. The correct one to use is pb_source_variance. Need to
@@ -3447,7 +3448,7 @@
       partition4_allowed && partition_vert_allowed &&
       get_plane_block_size(get_partition_subsize(bsize, PARTITION_VERT_4), xss,
                            yss) != BLOCK_INVALID;
-  if (cpi->sf.prune_ext_partition_types_search_level == 2) {
+  if (cpi->sf.part_sf.prune_ext_partition_types_search_level == 2) {
     partition_horz4_allowed &= (pc_tree->partitioning == PARTITION_HORZ ||
                                 pc_tree->partitioning == PARTITION_HORZ_A ||
                                 pc_tree->partitioning == PARTITION_HORZ_B ||
@@ -3459,7 +3460,7 @@
                                 pc_tree->partitioning == PARTITION_SPLIT ||
                                 pc_tree->partitioning == PARTITION_NONE);
   }
-  if (cpi->sf.ml_prune_4_partition && partition4_allowed &&
+  if (cpi->sf.part_sf.ml_prune_4_partition && partition4_allowed &&
       partition_horz_allowed && partition_vert_allowed) {
     av1_ml_prune_4_partition(cpi, x, bsize, pc_tree->partitioning,
                              best_rdc.rdcost, horz_rd, vert_rd, split_rd,
@@ -4300,10 +4301,10 @@
     PC_TREE *const pc_root = td->pc_root[mib_size_log2 - MIN_MIB_SIZE_LOG2];
     pc_root->index = 0;
 
-    if ((sf->simple_motion_search_split ||
-         sf->simple_motion_search_prune_rect ||
-         sf->simple_motion_search_early_term_none ||
-         sf->ml_early_term_after_part_split_level) &&
+    if ((sf->part_sf.simple_motion_search_split ||
+         sf->part_sf.simple_motion_search_prune_rect ||
+         sf->part_sf.simple_motion_search_early_term_none ||
+         sf->part_sf.ml_early_term_after_part_split_level) &&
         !frame_is_intra_only(cm) && !use_nonrd_mode) {
       init_simple_motion_search_mvs(pc_root);
     }
@@ -4337,24 +4338,24 @@
 
     // Realtime path.
     if (cpi->oxcf.mode == REALTIME && cpi->oxcf.speed >= 6) {
-      if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {
+      if (sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip) {
         set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
         const BLOCK_SIZE bsize =
-            seg_skip ? sb_size : sf->always_this_block_size;
+            seg_skip ? sb_size : sf->part_sf.always_this_block_size;
         set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
       } else if (cpi->partition_search_skippable_frame) {
         set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
         const BLOCK_SIZE bsize =
             get_rd_var_based_fixed_partition(cpi, x, mi_row, mi_col);
         set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
-      } else if (sf->partition_search_type == VAR_BASED_PARTITION) {
+      } else if (sf->part_sf.partition_search_type == VAR_BASED_PARTITION) {
         set_offsets_without_segment_id(cpi, tile_info, x, mi_row, mi_col,
                                        sb_size);
         av1_choose_var_based_partitioning(cpi, tile_info, x, mi_row, mi_col);
       }
-      assert(sf->partition_search_type == FIXED_PARTITION || seg_skip ||
+      assert(sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip ||
              cpi->partition_search_skippable_frame ||
-             sf->partition_search_type == VAR_BASED_PARTITION);
+             sf->part_sf.partition_search_type == VAR_BASED_PARTITION);
       td->mb.cb_offset = 0;
       if (use_nonrd_mode) {
         nonrd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
@@ -4372,10 +4373,10 @@
       RD_STATS dummy_rdc;
       av1_invalid_rd_stats(&dummy_rdc);
       adjust_rdmult_tpl_model(cpi, x, mi_row, mi_col);
-      if (sf->partition_search_type == FIXED_PARTITION || seg_skip) {
+      if (sf->part_sf.partition_search_type == FIXED_PARTITION || seg_skip) {
         set_offsets(cpi, tile_info, x, mi_row, mi_col, sb_size);
         const BLOCK_SIZE bsize =
-            seg_skip ? sb_size : sf->always_this_block_size;
+            seg_skip ? sb_size : sf->part_sf.always_this_block_size;
         set_fixed_partitioning(cpi, tile_info, mi, mi_row, mi_col, bsize);
         rd_use_partition(cpi, td, tile_data, mi, tp, mi_row, mi_col, sb_size,
                          &dummy_rate, &dummy_dist, 1, pc_root);
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index f65b860..a9484a7 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -1965,9 +1965,10 @@
     if (bsize >= BLOCK_32X32) best_early_term = 0;
   }
 
-  if (best_rdc.rdcost == INT64_MAX || (perform_intra_pred && !best_early_term &&
-                                       best_rdc.rdcost > inter_mode_thresh &&
-                                       bsize <= cpi->sf.max_intra_bsize)) {
+  if (best_rdc.rdcost == INT64_MAX ||
+      (perform_intra_pred && !best_early_term &&
+       best_rdc.rdcost > inter_mode_thresh &&
+       bsize <= cpi->sf.part_sf.max_intra_bsize)) {
     int64_t this_sse = INT64_MAX;
     struct estimate_block_intra_args args = { cpi, x, DC_PRED, 1, 0 };
     PRED_BUFFER *const best_pred = best_pickmode.best_pred;
diff --git a/av1/encoder/partition_strategy.c b/av1/encoder/partition_strategy.c
index 7170fdd..8ea5891 100644
--- a/av1/encoder/partition_strategy.c
+++ b/av1/encoder/partition_strategy.c
@@ -264,7 +264,7 @@
   const float *ml_std = av1_simple_motion_search_split_std[bsize_idx];
   const NN_CONFIG *nn_config =
       av1_simple_motion_search_split_nn_config[bsize_idx];
-  const int agg = cpi->sf.simple_motion_search_prune_agg;
+  const int agg = cpi->sf.part_sf.simple_motion_search_prune_agg;
 
   const float split_only_thresh =
       av1_simple_motion_search_split_thresh[agg][res_idx][bsize_idx];
@@ -291,7 +291,8 @@
     *do_rectangular_split = 0;
   }
 
-  if (cpi->sf.simple_motion_search_split >= 2 && score < no_split_thresh) {
+  if (cpi->sf.part_sf.simple_motion_search_split >= 2 &&
+      score < no_split_thresh) {
     *do_square_split = 0;
   }
 }
@@ -511,7 +512,7 @@
   const float *ml_mean = av1_simple_motion_search_prune_rect_mean[bsize_idx],
               *ml_std = av1_simple_motion_search_prune_rect_std[bsize_idx];
 
-  const int agg = cpi->sf.simple_motion_search_prune_agg;
+  const int agg = cpi->sf.part_sf.simple_motion_search_prune_agg;
   const float prune_thresh =
       av1_simple_motion_search_prune_rect_thresh[agg][res_idx][bsize_idx];
 
@@ -542,7 +543,8 @@
   av1_nn_softmax(scores, probs, num_classes);
 
   // Determine if we should prune rectangular partitions.
-  if (cpi->sf.simple_motion_search_prune_rect && !frame_is_intra_only(cm) &&
+  if (cpi->sf.part_sf.simple_motion_search_prune_rect &&
+      !frame_is_intra_only(cm) &&
       (*partition_horz_allowed || *partition_vert_allowed) &&
       bsize >= BLOCK_8X8 && !av1_superres_scaled(cm)) {
     *prune_horz = probs[PARTITION_HORZ] <= prune_thresh;
@@ -717,14 +719,16 @@
         probs[MAX_NUM_CLASSES_MAX_MIN_PART_PRED] = { 0.0f };
   const NN_CONFIG *nn_config = &av1_max_part_pred_nn_config;
 
-  assert(cpi->sf.auto_max_partition_based_on_simple_motion != NOT_IN_USE);
+  assert(cpi->sf.part_sf.auto_max_partition_based_on_simple_motion !=
+         NOT_IN_USE);
 
   aom_clear_system_state();
   av1_nn_predict(features, nn_config, 1, scores);
   av1_nn_softmax(scores, probs, MAX_NUM_CLASSES_MAX_MIN_PART_PRED);
 
   int result = MAX_NUM_CLASSES_MAX_MIN_PART_PRED - 1;
-  if (cpi->sf.auto_max_partition_based_on_simple_motion == DIRECT_PRED) {
+  if (cpi->sf.part_sf.auto_max_partition_based_on_simple_motion ==
+      DIRECT_PRED) {
     result = 0;
     float max_prob = probs[0];
     for (int i = 1; i < MAX_NUM_CLASSES_MAX_MIN_PART_PRED; ++i) {
@@ -733,7 +737,7 @@
         result = i;
       }
     }
-  } else if (cpi->sf.auto_max_partition_based_on_simple_motion ==
+  } else if (cpi->sf.part_sf.auto_max_partition_based_on_simple_motion ==
              RELAXED_PRED) {
     for (result = MAX_NUM_CLASSES_MAX_MIN_PART_PRED - 1; result >= 0;
          --result) {
@@ -742,7 +746,8 @@
       }
       if (probs[result] > 0.2) break;
     }
-  } else if (cpi->sf.auto_max_partition_based_on_simple_motion == ADAPT_PRED) {
+  } else if (cpi->sf.part_sf.auto_max_partition_based_on_simple_motion ==
+             ADAPT_PRED) {
     const BLOCK_SIZE sb_size = cpi->common.seq_params.sb_size;
     MACROBLOCKD *const xd = &x->e_mbd;
     // TODO(debargha): x->source_variance is unavailable at this point,
@@ -848,7 +853,7 @@
   if (!nn_config) return;
 
   // Use more conservative threshold for level 1.
-  if (cpi->sf.ml_early_term_after_part_split_level < 2) thresh -= 0.3f;
+  if (cpi->sf.part_sf.ml_early_term_after_part_split_level < 2) thresh -= 0.3f;
 
   const MACROBLOCKD *const xd = &x->e_mbd;
   const int dc_q = av1_dc_quant_QTX(x->qindex, 0, xd->bd) >> (xd->bd - 8);
@@ -1227,23 +1232,23 @@
   switch (bsize) {
     case BLOCK_8X8:
       nn_config = &av1_partition_breakout_nnconfig_8;
-      thresh = cpi->sf.ml_partition_search_breakout_thresh[0];
+      thresh = cpi->sf.part_sf.ml_partition_search_breakout_thresh[0];
       break;
     case BLOCK_16X16:
       nn_config = &av1_partition_breakout_nnconfig_16;
-      thresh = cpi->sf.ml_partition_search_breakout_thresh[1];
+      thresh = cpi->sf.part_sf.ml_partition_search_breakout_thresh[1];
       break;
     case BLOCK_32X32:
       nn_config = &av1_partition_breakout_nnconfig_32;
-      thresh = cpi->sf.ml_partition_search_breakout_thresh[2];
+      thresh = cpi->sf.part_sf.ml_partition_search_breakout_thresh[2];
       break;
     case BLOCK_64X64:
       nn_config = &av1_partition_breakout_nnconfig_64;
-      thresh = cpi->sf.ml_partition_search_breakout_thresh[3];
+      thresh = cpi->sf.part_sf.ml_partition_search_breakout_thresh[3];
       break;
     case BLOCK_128X128:
       nn_config = &av1_partition_breakout_nnconfig_128;
-      thresh = cpi->sf.ml_partition_search_breakout_thresh[4];
+      thresh = cpi->sf.part_sf.ml_partition_search_breakout_thresh[4];
       break;
     default: assert(0 && "Unexpected bsize.");
   }
diff --git a/av1/encoder/partition_strategy.h b/av1/encoder/partition_strategy.h
index a4a266c..3b6c50a 100644
--- a/av1/encoder/partition_strategy.h
+++ b/av1/encoder/partition_strategy.h
@@ -204,7 +204,8 @@
                  cpi->gf_group.index < cpi->gf_group.size));
   AV1_COMMON *const cm = &cpi->common;
   return !frame_is_intra_only(cm) &&
-         cpi->sf.auto_max_partition_based_on_simple_motion != NOT_IN_USE &&
+         cpi->sf.part_sf.auto_max_partition_based_on_simple_motion !=
+             NOT_IN_USE &&
          sb_size == BLOCK_128X128 && is_full_sb(cm, mi_row, mi_col, sb_size) &&
          cpi->gf_group.update_type[cpi->gf_group.index] != OVERLAY_UPDATE &&
          cpi->gf_group.update_type[cpi->gf_group.index] != INTNL_OVERLAY_UPDATE;
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index 0f0a449..62285b6 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -1767,8 +1767,7 @@
 
       // Do the firstpass stats indicate that this frame is skippable for the
       // partition search?
-      if (cpi->sf.allow_partition_search_skip &&
-          is_stat_consumption_stage_twopass(cpi)) {
+      if (cpi->sf.part_sf.allow_partition_search_skip && cpi->oxcf.pass == 2) {
         cpi->partition_search_skippable_frame = is_skippable_frame(cpi);
       }
 
@@ -1860,8 +1859,7 @@
 
   // Do the firstpass stats indicate that this frame is skippable for the
   // partition search?
-  if (cpi->sf.allow_partition_search_skip &&
-      is_stat_consumption_stage_twopass(cpi)) {
+  if (cpi->sf.part_sf.allow_partition_search_skip && cpi->oxcf.pass == 2) {
     cpi->partition_search_skippable_frame = is_skippable_frame(cpi);
   }
 
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 4145f7c..f0e92f7 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -12340,7 +12340,7 @@
         mask->pred_modes[GOLDEN_FRAME] |= INTER_ALL;
   }
 
-  if (bsize > sf->max_intra_bsize) {
+  if (bsize > sf->part_sf.max_intra_bsize) {
     disable_reference(INTRA_FRAME, mask->ref_combo);
   }
 
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 1ff7003..19df934 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -139,64 +139,64 @@
   const int is_4k_or_larger = AOMMIN(cm->width, cm->height) >= 2160;
 
   if (is_480p_or_larger) {
-    sf->use_square_partition_only_threshold = BLOCK_128X128;
+    sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
     if (is_720p_or_larger)
-      sf->auto_max_partition_based_on_simple_motion = ADAPT_PRED;
+      sf->part_sf.auto_max_partition_based_on_simple_motion = ADAPT_PRED;
     else
-      sf->auto_max_partition_based_on_simple_motion = RELAXED_PRED;
+      sf->part_sf.auto_max_partition_based_on_simple_motion = RELAXED_PRED;
   } else {
-    sf->use_square_partition_only_threshold = BLOCK_64X64;
-    sf->auto_max_partition_based_on_simple_motion = DIRECT_PRED;
+    sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
+    sf->part_sf.auto_max_partition_based_on_simple_motion = DIRECT_PRED;
   }
 
   if (is_4k_or_larger) {
-    sf->default_min_partition_size = BLOCK_8X8;
+    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->ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
-    sf->ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
-    sf->ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
-    sf->ml_partition_search_breakout_thresh[3] = 500;  // BLOCK_64X64
-    sf->ml_partition_search_breakout_thresh[4] = -1;   // BLOCK_128X128
-    sf->ml_early_term_after_part_split_level = 1;
+    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 (speed >= 1) {
     if (is_720p_or_larger) {
-      sf->use_square_partition_only_threshold = BLOCK_128X128;
+      sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
     } else if (is_480p_or_larger) {
-      sf->use_square_partition_only_threshold = BLOCK_64X64;
+      sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
     } else {
-      sf->use_square_partition_only_threshold = BLOCK_32X32;
+      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
     }
 
     if (!is_720p_or_larger) {
-      sf->ml_partition_search_breakout_thresh[0] = 200;  // BLOCK_8X8
-      sf->ml_partition_search_breakout_thresh[1] = 250;  // BLOCK_16X16
-      sf->ml_partition_search_breakout_thresh[2] = 300;  // BLOCK_32X32
-      sf->ml_partition_search_breakout_thresh[3] = 300;  // BLOCK_64X64
-      sf->ml_partition_search_breakout_thresh[4] = -1;   // BLOCK_128X128
+      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->ml_early_term_after_part_split_level = 2;
+    sf->part_sf.ml_early_term_after_part_split_level = 2;
   }
 
   if (speed >= 2) {
     if (is_720p_or_larger) {
-      sf->use_square_partition_only_threshold = BLOCK_64X64;
+      sf->part_sf.use_square_partition_only_threshold = BLOCK_64X64;
     } else if (is_480p_or_larger) {
-      sf->use_square_partition_only_threshold = BLOCK_32X32;
+      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
     } else {
-      sf->use_square_partition_only_threshold = BLOCK_32X32;
+      sf->part_sf.use_square_partition_only_threshold = BLOCK_32X32;
     }
 
     if (is_720p_or_larger) {
-      sf->partition_search_breakout_dist_thr = (1 << 24);
-      sf->partition_search_breakout_rate_thr = 120;
+      sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
+      sf->part_sf.partition_search_breakout_rate_thr = 120;
     } else {
-      sf->partition_search_breakout_dist_thr = (1 << 22);
-      sf->partition_search_breakout_rate_thr = 100;
+      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_type_search.prune_tx_type_using_stats = 1;
@@ -208,22 +208,22 @@
   }
 
   if (speed >= 3) {
-    sf->ml_early_term_after_part_split_level = 0;
+    sf->part_sf.ml_early_term_after_part_split_level = 0;
     if (is_720p_or_larger) {
-      sf->partition_search_breakout_dist_thr = (1 << 25);
-      sf->partition_search_breakout_rate_thr = 200;
+      sf->part_sf.partition_search_breakout_dist_thr = (1 << 25);
+      sf->part_sf.partition_search_breakout_rate_thr = 200;
     } else {
-      sf->max_intra_bsize = BLOCK_32X32;
-      sf->partition_search_breakout_dist_thr = (1 << 23);
-      sf->partition_search_breakout_rate_thr = 120;
+      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 (speed >= 4) {
     if (is_720p_or_larger) {
-      sf->partition_search_breakout_dist_thr = (1 << 26);
+      sf->part_sf.partition_search_breakout_dist_thr = (1 << 26);
     } else {
-      sf->partition_search_breakout_dist_thr = (1 << 24);
+      sf->part_sf.partition_search_breakout_dist_thr = (1 << 24);
     }
 
     if (is_480p_or_larger) sf->tx_type_search.prune_tx_type_using_stats = 2;
@@ -267,11 +267,11 @@
 
   // Speed 0 for all speed features that give neutral coding performance change.
   sf->reduce_inter_modes = 1;
-  sf->prune_ext_partition_types_search_level = 1;
-  sf->ml_prune_rect_partition = 1;
-  sf->ml_prune_ab_partition = 1;
-  sf->ml_prune_4_partition = 1;
-  sf->simple_motion_search_prune_rect = 1;
+  sf->part_sf.prune_ext_partition_types_search_level = 1;
+  sf->part_sf.ml_prune_rect_partition = 1;
+  sf->part_sf.ml_prune_ab_partition = 1;
+  sf->part_sf.ml_prune_4_partition = 1;
+  sf->part_sf.simple_motion_search_prune_rect = 1;
   sf->adaptive_txb_search_level = 1;
   sf->use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;
   sf->model_based_prune_tx_search_level = 1;
@@ -288,7 +288,7 @@
       (boosted || (cm->allow_screen_content_tools))
           ? 0
           : (is_boosted_arf2_bwd_type ? 1 : 2);
-  sf->less_rectangular_check_level = 1;
+  sf->part_sf.less_rectangular_check_level = 1;
   sf->gm_search_type = GM_REDUCED_REF_SEARCH_SKIP_L2_L3;
   sf->gm_disable_recode = 1;
   sf->use_fast_interpolation_filter_search = 1;
@@ -325,8 +325,9 @@
     // TODO(Venkat): Clean-up frame type dependency for
     // simple_motion_search_split in partition search function and set the
     // speed feature accordingly
-    sf->simple_motion_search_split = cm->allow_screen_content_tools ? 1 : 2;
-    sf->simple_motion_search_early_term_none = 1;
+    sf->part_sf.simple_motion_search_split =
+        cm->allow_screen_content_tools ? 1 : 2;
+    sf->part_sf.simple_motion_search_early_term_none = 1;
 
     sf->disable_interinter_wedge_newmv_search = boosted ? 0 : 1;
     sf->prune_comp_type_by_comp_avg = 1;
@@ -370,7 +371,7 @@
     sf->disable_filter_search_var_thresh = 100;
     sf->comp_inter_joint_search_thresh = BLOCK_SIZES_ALL;
 
-    sf->allow_partition_search_skip = 1;
+    sf->part_sf.allow_partition_search_skip = 1;
     sf->disable_wedge_search_var_thresh = 100;
     sf->disable_wedge_search_edge_thresh = 0;
     sf->disable_interinter_wedge_newmv_search = 1;
@@ -389,7 +390,7 @@
   }
 
   if (speed >= 3) {
-    sf->less_rectangular_check_level = 2;
+    sf->part_sf.less_rectangular_check_level = 2;
     // adaptive_motion_search breaks encoder multi-thread tests.
     // The values in x->pred_mv[] differ for single and multi-thread cases.
     // See aomedia:1778.
@@ -418,7 +419,7 @@
     sf->reduce_wiener_window_size = is_boosted_arf2_bwd_type ? 0 : 1;
     sf->prune_sgr_based_on_wiener = cm->allow_screen_content_tools ? 0 : 2;
     sf->mv.subpel_search_method = SUBPEL_TREE_PRUNED;
-    sf->simple_motion_search_prune_agg = 1;
+    sf->part_sf.simple_motion_search_prune_agg = 1;
     sf->disable_sb_level_mv_cost_upd = 1;
     sf->motion_mode_for_winner_cand =
         boosted
@@ -483,7 +484,7 @@
     //     FLAG_EARLY_TERMINATE;
     // sf->tx_domain_dist_level = 2;
     sf->tx_domain_dist_thres_level = 2;
-    sf->simple_motion_search_prune_agg = 2;
+    sf->part_sf.simple_motion_search_prune_agg = 2;
     sf->use_interp_filter = 2;
     sf->prune_ref_mv_idx_search = 1;
   }
@@ -511,10 +512,10 @@
 
   // Speed 0 for all speed features that give neutral coding performance change.
   sf->reduce_inter_modes = 1;
-  sf->prune_ext_partition_types_search_level = 1;
-  sf->ml_prune_rect_partition = 1;
-  sf->ml_prune_ab_partition = 1;
-  sf->ml_prune_4_partition = 1;
+  sf->part_sf.prune_ext_partition_types_search_level = 1;
+  sf->part_sf.ml_prune_rect_partition = 1;
+  sf->part_sf.ml_prune_ab_partition = 1;
+  sf->part_sf.ml_prune_4_partition = 1;
   sf->adaptive_txb_search_level = 1;
   sf->use_dist_wtd_comp_flag = DIST_WTD_COMP_SKIP_MV_SEARCH;
   sf->model_based_prune_tx_search_level = 1;
@@ -526,7 +527,7 @@
   sf->prune_mode_search_simple_translation = 1;
 
   sf->prune_ref_frame_for_rect_partitions = !boosted;
-  sf->less_rectangular_check_level = 1;
+  sf->part_sf.less_rectangular_check_level = 1;
   sf->gm_search_type = GM_REDUCED_REF_SEARCH_SKIP_L2_L3;
   sf->gm_disable_recode = 1;
   sf->use_fast_interpolation_filter_search = 1;
@@ -557,7 +558,7 @@
 
     sf->intra_tx_size_search_init_depth_rect = 1;
     sf->tx_size_search_lgr_block = 1;
-    sf->prune_ext_partition_types_search_level = 2;
+    sf->part_sf.prune_ext_partition_types_search_level = 2;
     sf->use_interp_filter = 1;
     sf->tx_type_search.skip_tx_search = 1;
     sf->tx_type_search.ml_tx_split_thresh = 4000;
@@ -575,7 +576,7 @@
     // speed.
     sf->prune_single_motion_modes_by_simple_trans = 1;
 
-    sf->simple_motion_search_prune_rect = 1;
+    sf->part_sf.simple_motion_search_prune_rect = 1;
 
     sf->disable_wedge_search_var_thresh = 0;
     sf->disable_wedge_search_edge_thresh = 0;
@@ -601,8 +602,8 @@
     sf->disable_filter_search_var_thresh = 100;
     sf->comp_inter_joint_search_thresh = BLOCK_SIZES_ALL;
 
-    sf->partition_search_breakout_rate_thr = 80;
-    sf->allow_partition_search_skip = 1;
+    sf->part_sf.partition_search_breakout_rate_thr = 80;
+    sf->part_sf.allow_partition_search_skip = 1;
     sf->disable_wedge_search_var_thresh = 100;
     sf->disable_wedge_search_edge_thresh = 0;
     sf->fast_wedge_sign_estimate = 1;
@@ -617,7 +618,7 @@
   if (speed >= 3) {
     sf->selective_ref_frame = 4;
     sf->tx_size_search_level = boosted ? 0 : 2;
-    sf->less_rectangular_check_level = 2;
+    sf->part_sf.less_rectangular_check_level = 2;
     // adaptive_motion_search breaks encoder multi-thread tests.
     // The values in x->pred_mv[] differ for single and multi-thread cases.
     // See aomedia:1778.
@@ -669,7 +670,7 @@
                   FLAG_EARLY_TERMINATE;
     sf->disable_filter_search_var_thresh = 200;
     sf->use_fast_coef_costing = 1;
-    sf->partition_search_breakout_rate_thr = 300;
+    sf->part_sf.partition_search_breakout_rate_thr = 300;
     sf->tx_domain_dist_level = 2;
     sf->tx_domain_dist_thres_level = 2;
   }
@@ -680,15 +681,15 @@
       sf->intra_y_mode_mask[i] = INTRA_DC;
       sf->intra_uv_mode_mask[i] = UV_INTRA_DC_CFL;
     }
-    sf->partition_search_breakout_rate_thr = 500;
+    sf->part_sf.partition_search_breakout_rate_thr = 500;
     sf->simple_model_rd_from_var = 1;
     sf->lpf_pick = LPF_PICK_FROM_Q;
     sf->mv.subpel_force_stop = QUARTER_PEL;
-    sf->default_max_partition_size = BLOCK_128X128;
-    sf->default_min_partition_size = BLOCK_8X8;
+    sf->part_sf.default_max_partition_size = BLOCK_128X128;
+    sf->part_sf.default_min_partition_size = BLOCK_8X8;
     sf->frame_parameter_update = 0;
     sf->mv.search_method = FAST_DIAMOND;
-    sf->partition_search_type = VAR_BASED_PARTITION;
+    sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
     sf->mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
     sf->use_real_time_ref_set = 1;
     sf->tx_type_search.prune_mode = PRUNE_2D_MORE;
@@ -696,7 +697,7 @@
     sf->use_comp_ref_nonrd = 0;
     sf->inter_mode_rd_model_estimation = 2;
     sf->cdef_pick_method = CDEF_PICK_FROM_Q;
-    sf->max_intra_bsize = BLOCK_32X32;
+    sf->part_sf.max_intra_bsize = BLOCK_32X32;
     sf->use_inter_txb_hash = 0;
     sf->skip_interp_filter_search = 1;
     sf->adaptive_mode_search = 2;
@@ -707,11 +708,11 @@
   if (speed >= 7) {
     sf->lpf_pick = LPF_PICK_FROM_Q;
     sf->mv.subpel_force_stop = QUARTER_PEL;
-    sf->default_max_partition_size = BLOCK_128X128;
-    sf->default_min_partition_size = BLOCK_8X8;
+    sf->part_sf.default_max_partition_size = BLOCK_128X128;
+    sf->part_sf.default_min_partition_size = BLOCK_8X8;
     sf->frame_parameter_update = 0;
     sf->mv.search_method = FAST_DIAMOND;
-    sf->partition_search_type = VAR_BASED_PARTITION;
+    sf->part_sf.partition_search_type = VAR_BASED_PARTITION;
     sf->mode_search_skip_flags |= FLAG_SKIP_INTRA_DIRMISMATCH;
     sf->use_nonrd_pick_mode = 1;
     sf->use_comp_ref_nonrd = 0;
@@ -744,6 +745,38 @@
   }
 }
 
+static AOM_INLINE void init_part_sfs(PARTITION_SPEED_FEATURES *part_sf) {
+  part_sf->partition_search_type = SEARCH_PARTITION;
+  part_sf->less_rectangular_check_level = 0;
+  part_sf->use_square_partition_only_threshold = BLOCK_128X128;
+  part_sf->auto_max_partition_based_on_simple_motion = NOT_IN_USE;
+  part_sf->auto_min_partition_based_on_simple_motion = 0;
+  part_sf->default_max_partition_size = BLOCK_LARGEST;
+  part_sf->default_min_partition_size = BLOCK_4X4;
+  part_sf->adjust_partitioning_from_last_frame = 0;
+  part_sf->allow_partition_search_skip = 0;
+  part_sf->max_intra_bsize = BLOCK_LARGEST;
+  // This setting only takes effect when partition_search_type is set
+  // to FIXED_PARTITION.
+  part_sf->always_this_block_size = BLOCK_16X16;
+  // Recode loop tolerance %.
+  part_sf->partition_search_breakout_dist_thr = 0;
+  part_sf->partition_search_breakout_rate_thr = 0;
+  part_sf->prune_ext_partition_types_search_level = 0;
+  part_sf->ml_prune_rect_partition = 0;
+  part_sf->ml_prune_ab_partition = 0;
+  part_sf->ml_prune_4_partition = 0;
+  part_sf->ml_early_term_after_part_split_level = 0;
+  for (int i = 0; i < PARTITION_BLOCK_SIZES; ++i) {
+    part_sf->ml_partition_search_breakout_thresh[i] =
+        -1;  // -1 means not enabled.
+  }
+  part_sf->simple_motion_search_prune_agg = 0;
+  part_sf->simple_motion_search_split = 0;
+  part_sf->simple_motion_search_prune_rect = 0;
+  part_sf->simple_motion_search_early_term_none = 0;
+}
+
 void av1_set_speed_features_framesize_dependent(AV1_COMP *cpi, int speed) {
   SPEED_FEATURES *const sf = &cpi->sf;
   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
@@ -762,14 +795,13 @@
 
   MACROBLOCK *const x = &cpi->td.mb;
   AV1_COMMON *const cm = &cpi->common;
-  x->min_partition_size = AOMMAX(sf->default_min_partition_size,
+  x->min_partition_size = AOMMAX(sf->part_sf.default_min_partition_size,
                                  dim_to_size(cpi->oxcf.min_partition_size));
-  x->max_partition_size = AOMMIN(sf->default_max_partition_size,
+  x->max_partition_size = AOMMIN(sf->part_sf.default_max_partition_size,
                                  dim_to_size(cpi->oxcf.max_partition_size));
   x->min_partition_size = AOMMIN(x->min_partition_size, cm->seq_params.sb_size);
   x->max_partition_size = AOMMIN(x->max_partition_size, cm->seq_params.sb_size);
 }
-
 void av1_set_speed_features_framesize_independent(AV1_COMP *cpi, int speed) {
   AV1_COMMON *const cm = &cpi->common;
   SPEED_FEATURES *const sf = &cpi->sf;
@@ -821,7 +853,7 @@
   sf->adaptive_motion_search = 0;
   sf->adaptive_mode_search = 0;
   sf->alt_ref_search_fp = 0;
-  sf->partition_search_type = SEARCH_PARTITION;
+  sf->part_sf.partition_search_type = SEARCH_PARTITION;
   sf->tx_type_search.prune_mode = PRUNE_2D_ACCURATE;
   sf->tx_type_search.ml_tx_split_thresh = 8500;
   sf->tx_type_search.use_skip_flag_prediction = 1;
@@ -832,17 +864,17 @@
   sf->tx_type_search.prune_tx_type_using_stats = 0;
   sf->tx_type_search.enable_winner_mode_tx_type_pruning = 0;
   sf->selective_ref_frame = 0;
-  sf->less_rectangular_check_level = 0;
-  sf->use_square_partition_only_threshold = BLOCK_128X128;
+  sf->part_sf.less_rectangular_check_level = 0;
+  sf->part_sf.use_square_partition_only_threshold = BLOCK_128X128;
   sf->prune_ref_frame_for_rect_partitions = 0;
-  sf->auto_max_partition_based_on_simple_motion = NOT_IN_USE;
-  sf->auto_min_partition_based_on_simple_motion = 0;
-  sf->default_max_partition_size = BLOCK_LARGEST;
-  sf->default_min_partition_size = BLOCK_4X4;
-  sf->adjust_partitioning_from_last_frame = 0;
+  sf->part_sf.auto_max_partition_based_on_simple_motion = NOT_IN_USE;
+  sf->part_sf.auto_min_partition_based_on_simple_motion = 0;
+  sf->part_sf.default_max_partition_size = BLOCK_LARGEST;
+  sf->part_sf.default_min_partition_size = BLOCK_4X4;
+  sf->part_sf.adjust_partitioning_from_last_frame = 0;
   sf->mode_search_skip_flags = 0;
   sf->disable_filter_search_var_thresh = 0;
-  sf->allow_partition_search_skip = 0;
+  sf->part_sf.allow_partition_search_skip = 0;
   sf->use_accurate_subpel_search = USE_8_TAPS;
   sf->disable_wedge_search_edge_thresh = 0;
   sf->disable_wedge_search_var_thresh = 0;
@@ -885,27 +917,28 @@
   sf->lpf_pick = LPF_PICK_FROM_FULL_IMAGE;
   sf->cdef_pick_method = CDEF_FULL_SEARCH;
   sf->use_fast_coef_costing = 0;
-  sf->max_intra_bsize = BLOCK_LARGEST;
+  sf->part_sf.max_intra_bsize = BLOCK_LARGEST;
   // This setting only takes effect when partition_search_type is set
   // to FIXED_PARTITION.
-  sf->always_this_block_size = BLOCK_16X16;
+  sf->part_sf.always_this_block_size = BLOCK_16X16;
   // Recode loop tolerance %.
   sf->recode_tolerance = 25;
-  sf->partition_search_breakout_dist_thr = 0;
-  sf->partition_search_breakout_rate_thr = 0;
+  sf->part_sf.partition_search_breakout_dist_thr = 0;
+  sf->part_sf.partition_search_breakout_rate_thr = 0;
   sf->simple_model_rd_from_var = 0;
-  sf->prune_ext_partition_types_search_level = 0;
-  sf->ml_prune_rect_partition = 0;
-  sf->ml_prune_ab_partition = 0;
-  sf->ml_prune_4_partition = 0;
-  sf->ml_early_term_after_part_split_level = 0;
+  sf->part_sf.prune_ext_partition_types_search_level = 0;
+  sf->part_sf.ml_prune_rect_partition = 0;
+  sf->part_sf.ml_prune_ab_partition = 0;
+  sf->part_sf.ml_prune_4_partition = 0;
+  sf->part_sf.ml_early_term_after_part_split_level = 0;
   for (i = 0; i < PARTITION_BLOCK_SIZES; ++i) {
-    sf->ml_partition_search_breakout_thresh[i] = -1;  // -1 means not enabled.
+    sf->part_sf.ml_partition_search_breakout_thresh[i] =
+        -1;  // -1 means not enabled.
   }
-  sf->simple_motion_search_prune_agg = 0;
-  sf->simple_motion_search_split = 0;
-  sf->simple_motion_search_prune_rect = 0;
-  sf->simple_motion_search_early_term_none = 0;
+  sf->part_sf.simple_motion_search_prune_agg = 0;
+  sf->part_sf.simple_motion_search_split = 0;
+  sf->part_sf.simple_motion_search_prune_rect = 0;
+  sf->part_sf.simple_motion_search_early_term_none = 0;
   sf->intra_cnn_split = 0;
 
   // Set this at the appropriate speed levels
@@ -957,6 +990,8 @@
   sf->prune_ref_mv_idx_search = 0;
   sf->prune_warped_prob_thresh = 0;
 
+  init_part_sfs(&sf->part_sf);
+
   if (oxcf->mode == GOOD)
     set_good_speed_features_framesize_independent(cpi, sf, speed);
   else if (oxcf->mode == REALTIME)
@@ -967,10 +1002,11 @@
     cpi->common.seq_params.enable_restoration &= !sf->disable_lr_filter;
   }
 
-  // sf->partition_search_breakout_dist_thr is set assuming max 64x64
+  // sf->part_sf.partition_search_breakout_dist_thr is set assuming max 64x64
   // blocks. Normalise this if the blocks are bigger.
   if (MAX_SB_SIZE_LOG2 > 6) {
-    sf->partition_search_breakout_dist_thr <<= 2 * (MAX_SB_SIZE_LOG2 - 6);
+    sf->part_sf.partition_search_breakout_dist_thr <<=
+        2 * (MAX_SB_SIZE_LOG2 - 6);
   }
 
   sf->allow_exhaustive_searches = 1;
@@ -1019,9 +1055,9 @@
     cpi->find_fractional_mv_step = av1_find_best_sub_pixel_tree_pruned_evenmore;
   }
 
-  x->min_partition_size = AOMMAX(sf->default_min_partition_size,
+  x->min_partition_size = AOMMAX(sf->part_sf.default_min_partition_size,
                                  dim_to_size(cpi->oxcf.min_partition_size));
-  x->max_partition_size = AOMMIN(sf->default_max_partition_size,
+  x->max_partition_size = AOMMIN(sf->part_sf.default_max_partition_size,
                                  dim_to_size(cpi->oxcf.max_partition_size));
   x->min_partition_size = AOMMIN(x->min_partition_size, cm->seq_params.sb_size);
   x->max_partition_size = AOMMIN(x->max_partition_size, cm->seq_params.sb_size);
diff --git a/av1/encoder/speed_features.h b/av1/encoder/speed_features.h
index a25274b..b23d60c 100644
--- a/av1/encoder/speed_features.h
+++ b/av1/encoder/speed_features.h
@@ -253,6 +253,89 @@
   int reduce_first_step_size;
 } TPL_SPEED_FEATURES;
 
+typedef struct PARTITION_SPEED_FEATURES {
+  PARTITION_SEARCH_TYPE partition_search_type;
+
+  // Used if partition_search_type = FIXED_SIZE_PARTITION
+  BLOCK_SIZE always_this_block_size;
+
+  // Prune extended partition types search
+  // Can take values 0 - 2, 0 referring to no pruning, and 1 - 2 increasing
+  // aggressiveness of pruning in order.
+  int prune_ext_partition_types_search_level;
+
+  // Use a ML model to prune horz and vert partitions
+  int ml_prune_rect_partition;
+
+  // Use a ML model to prune horz_a, horz_b, vert_a and vert_b partitions.
+  int ml_prune_ab_partition;
+
+  // Use a ML model to prune horz4 and vert4 partitions.
+  int ml_prune_4_partition;
+
+  // Use a ML model to adaptively terminate partition search after trying
+  // PARTITION_SPLIT. Can take values 0 - 2, 0 meaning not being enabled, and
+  // 1 - 2 increasing aggressiveness in order.
+  int ml_early_term_after_part_split_level;
+
+  // Skip rectangular partition test when partition type none gives better
+  // rd than partition type split. Can take values 0 - 2, 0 referring to no
+  // skipping, and 1 - 2 increasing aggressiveness of skipping in order.
+  int less_rectangular_check_level;
+
+  // Use square partition only beyond this block size.
+  BLOCK_SIZE use_square_partition_only_threshold;
+
+  // Sets min and max square partition levels for this superblock based on
+  // motion vector and prediction error distribution produced from 16x16
+  // simple motion search
+  MAX_PART_PRED_MODE auto_max_partition_based_on_simple_motion;
+  int auto_min_partition_based_on_simple_motion;
+
+  // Min and max square partition size we enable (block_size) as per auto
+  // min max, but also used by adjust partitioning, and pick_partitioning.
+  BLOCK_SIZE default_min_partition_size;
+  BLOCK_SIZE default_max_partition_size;
+
+  // Whether or not we allow partitions one smaller or one greater than the last
+  // frame's partitioning. Only used if use_lastframe_partitioning is set.
+  int adjust_partitioning_from_last_frame;
+
+  // Partition search early breakout thresholds.
+  int64_t partition_search_breakout_dist_thr;
+  int partition_search_breakout_rate_thr;
+
+  // Thresholds for ML based partition search breakout.
+  int ml_partition_search_breakout_thresh[PARTITION_BLOCK_SIZES];
+
+  // Allow skipping partition search for still image frame
+  int allow_partition_search_skip;
+
+  // The aggresiveness of pruning with simple_motion_search.
+  // Currently 0 is the lowest, and 2 the highest.
+  int simple_motion_search_prune_agg;
+
+  // Perform simple_motion_search on each possible subblock and use it to prune
+  // PARTITION_HORZ and PARTITION_VERT.
+  int simple_motion_search_prune_rect;
+
+  // Perform simple motion search before none_partition to decide if we
+  // want to remove all partitions other than PARTITION_SPLIT. If set to 0, this
+  // model is disabled. If set to 1, the model attempts to perform
+  // PARTITION_SPLIT only. If set to 2, the model also attempts to prune
+  // PARTITION_SPLIT.
+  int simple_motion_search_split;
+
+  // Use features from simple_motion_search to terminate prediction block
+  // partition after PARTITION_NONE
+  int simple_motion_search_early_term_none;
+
+  // This variable controls the maximum block size where intra blocks can be
+  // used in inter frames.
+  // TODO(aconverse): Fold this into one of the other many mode skips
+  BLOCK_SIZE max_intra_bsize;
+} PARTITION_SPEED_FEATURES;
+
 #define MAX_MESH_STEP 4
 
 typedef struct MESH_PATTERN {
@@ -356,81 +439,7 @@
   /*
    * Partition search speed features:
    */
-  PARTITION_SEARCH_TYPE partition_search_type;
-
-  // Used if partition_search_type = FIXED_SIZE_PARTITION
-  BLOCK_SIZE always_this_block_size;
-
-  // Prune extended partition types search
-  // Can take values 0 - 2, 0 referring to no pruning, and 1 - 2 increasing
-  // aggressiveness of pruning in order.
-  int prune_ext_partition_types_search_level;
-
-  // Use a ML model to prune horz and vert partitions
-  int ml_prune_rect_partition;
-
-  // Use a ML model to prune horz_a, horz_b, vert_a and vert_b partitions.
-  int ml_prune_ab_partition;
-
-  // Use a ML model to prune horz4 and vert4 partitions.
-  int ml_prune_4_partition;
-
-  // Use a ML model to adaptively terminate partition search after trying
-  // PARTITION_SPLIT. Can take values 0 - 2, 0 meaning not being enabled, and
-  // 1 - 2 increasing aggressiveness in order.
-  int ml_early_term_after_part_split_level;
-
-  // Skip rectangular partition test when partition type none gives better
-  // rd than partition type split. Can take values 0 - 2, 0 referring to no
-  // skipping, and 1 - 2 increasing aggressiveness of skipping in order.
-  int less_rectangular_check_level;
-
-  // Use square partition only beyond this block size.
-  BLOCK_SIZE use_square_partition_only_threshold;
-
-  // Sets min and max square partition levels for this superblock based on
-  // motion vector and prediction error distribution produced from 16x16
-  // simple motion search
-  MAX_PART_PRED_MODE auto_max_partition_based_on_simple_motion;
-  int auto_min_partition_based_on_simple_motion;
-
-  // Min and max square partition size we enable (block_size) as per auto
-  // min max, but also used by adjust partitioning, and pick_partitioning.
-  BLOCK_SIZE default_min_partition_size;
-  BLOCK_SIZE default_max_partition_size;
-
-  // Whether or not we allow partitions one smaller or one greater than the last
-  // frame's partitioning. Only used if use_lastframe_partitioning is set.
-  int adjust_partitioning_from_last_frame;
-
-  // Partition search early breakout thresholds.
-  int64_t partition_search_breakout_dist_thr;
-  int partition_search_breakout_rate_thr;
-
-  // Thresholds for ML based partition search breakout.
-  int ml_partition_search_breakout_thresh[PARTITION_BLOCK_SIZES];
-
-  // Allow skipping partition search for still image frame
-  int allow_partition_search_skip;
-
-  // The aggresiveness of pruning with simple_motion_search.
-  // Currently 0 is the lowest, and 2 the highest.
-  int simple_motion_search_prune_agg;
-
-  // Perform simple_motion_search on each possible subblock and use it to prune
-  // PARTITION_HORZ and PARTITION_VERT.
-  int simple_motion_search_prune_rect;
-
-  // Perform simple motion search before none_partition to decide if we
-  // want to remove all partitions other than PARTITION_SPLIT. If set to 0, this
-  // model is disabled. If set to 1, the model attempts to perform
-  // PARTITION_SPLIT only. If set to 2, the model also attempts to prune
-  // PARTITION_SPLIT.
-  int simple_motion_search_split;
-
-  // Use features from simple_motion_search to terminate prediction block
-  // partition after PARTITION_NONE
-  int simple_motion_search_early_term_none;
+  PARTITION_SPEED_FEATURES part_sf;
 
   /*
    * Motion search speed features:
@@ -659,11 +668,6 @@
   int intra_y_mode_mask[TX_SIZES];
   int intra_uv_mode_mask[TX_SIZES];
 
-  // This variable controls the maximum block size where intra blocks can be
-  // used in inter frames.
-  // TODO(aconverse): Fold this into one of the other many mode skips
-  BLOCK_SIZE max_intra_bsize;
-
   // flag to allow skipping intra mode for inter frame prediction
   int skip_intra_in_interframe;
 
diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index 5f76193..03923f5 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -539,7 +539,7 @@
   AV1_COMMON *const cm = &cpi->common;
   SPEED_FEATURES *const sf = &cpi->sf;
   const int is_key_frame = frame_is_intra_only(cm);
-  if (sf->partition_search_type != VAR_BASED_PARTITION) {
+  if (sf->part_sf.partition_search_type != VAR_BASED_PARTITION) {
     return;
   } else {
     set_vbp_thresholds(cpi, cpi->vbp_thresholds, q, content_state);