Refactor FeatureFlags from AV1_COMMON

Also, refactor local variables/args for features when we can.

BUG=aomedia:2610

Change-Id: Ie2ccc0dc24bfffbc764c35bb9e3aacc82d82d8d1
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h
index c2efe4b..ac98b34 100644
--- a/av1/common/av1_common_int.h
+++ b/av1/common/av1_common_int.h
@@ -319,6 +319,23 @@
   int frame_refs_short_signaling;
 } CurrentFrame;
 
+// Struct containing some boolean flags indicating whether some features are
+// allowed/used or not.
+typedef struct {
+  uint8_t disable_cdf_update;
+  int allow_high_precision_mv;
+  uint8_t cur_frame_force_integer_mv;  // 0 the default in AOM, 1 only integer
+  uint8_t allow_screen_content_tools;
+  int allow_intrabc;
+  int allow_warped_motion;
+  // Whether to use previous frames' motion vectors for prediction.
+  int allow_ref_frame_mvs;
+  int coded_lossless;  // frame is fully lossless at the coded resolution.
+  int all_lossless;    // frame is fully lossless at the upscaled resolution.
+  int reduced_tx_set_used;
+  int error_resilient_mode;
+} FeatureFlags;
+
 typedef struct AV1Common {
   // Information about the current frame that is being coded.
   CurrentFrame current_frame;
@@ -426,13 +443,8 @@
   // as signaled in the bitstream.
   int show_existing_frame;
 
-  uint8_t disable_cdf_update;
-  int allow_high_precision_mv;
-  uint8_t cur_frame_force_integer_mv;  // 0 the default in AOM, 1 only integer
-
-  uint8_t allow_screen_content_tools;
-  int allow_intrabc;
-  int allow_warped_motion;
+  // Whether some features are allowed or not.
+  FeatureFlags features;
 
   // MBs, mb_rows/cols is in 16-pixel units; mi_rows/cols is in
   // MB_MODE_INFO (4-pixel) units.
@@ -499,9 +511,6 @@
   // area will be NULL.
   MB_MODE_INFO **mi_grid_base;
 
-  // Whether to use previous frames' motion vectors for prediction.
-  int allow_ref_frame_mvs;
-
   uint8_t *last_frame_seg_map;
 
   InterpFilter interp_filter;
@@ -526,17 +535,11 @@
 
   struct loopfilter lf;
   struct segmentation seg;
-  int coded_lossless;  // frame is fully lossless at the coded resolution.
-  int all_lossless;    // frame is fully lossless at the upscaled resolution.
-
-  int reduced_tx_set_used;
 
   FRAME_CONTEXT *fc; /* this frame entropy */
   FRAME_CONTEXT *default_frame_context;
   int primary_ref_frame;
 
-  int error_resilient_mode;
-
   int tile_cols, tile_rows;
 
   int max_tile_width_sb;
@@ -742,7 +745,7 @@
 
 // Returns 1 if this frame might allow mvs from some reference frame.
 static INLINE int frame_might_allow_ref_frame_mvs(const AV1_COMMON *cm) {
-  return !cm->error_resilient_mode &&
+  return !cm->features.error_resilient_mode &&
          cm->seq_params.order_hint_info.enable_ref_frame_mvs &&
          cm->seq_params.order_hint_info.enable_order_hint &&
          !frame_is_intra_only(cm);
@@ -750,7 +753,7 @@
 
 // Returns 1 if this frame might use warped_motion
 static INLINE int frame_might_allow_warped_motion(const AV1_COMMON *cm) {
-  return !cm->error_resilient_mode && !frame_is_intra_only(cm) &&
+  return !cm->features.error_resilient_mode && !frame_is_intra_only(cm) &&
          cm->seq_params.enable_warped_motion;
 }
 
diff --git a/av1/common/mv.h b/av1/common/mv.h
index dac13d7..c2235b5 100644
--- a/av1/common/mv.h
+++ b/av1/common/mv.h
@@ -270,7 +270,8 @@
     // All global motion vectors are stored with WARPEDMODEL_PREC_BITS (16)
     // bits of fractional precision. The offset for a translation is stored in
     // entries 0 and 1. For translations, all but the top three (two if
-    // cm->allow_high_precision_mv is false) fractional bits are always zero.
+    // cm->features.allow_high_precision_mv is false) fractional bits are always
+    // zero.
     //
     // After the right shifts, there are 3 fractional bits of precision. If
     // allow_hp is false, the bottom bit is always zero (so we don't need a
diff --git a/av1/common/mvref_common.c b/av1/common/mvref_common.c
index 7388f93..020e881 100644
--- a/av1/common/mvref_common.c
+++ b/av1/common/mvref_common.c
@@ -348,12 +348,14 @@
   const int cur_offset_0 = get_relative_dist(&cm->seq_params.order_hint_info,
                                              cur_frame_index, frame0_index);
   int idx;
+  const int allow_high_precision_mv = cm->features.allow_high_precision_mv;
+  const int force_integer_mv = cm->features.cur_frame_force_integer_mv;
 
   int_mv this_refmv;
   get_mv_projection(&this_refmv.as_mv, prev_frame_mvs->mfmv0.as_mv,
                     cur_offset_0, prev_frame_mvs->ref_frame_offset);
-  lower_mv_precision(&this_refmv.as_mv, cm->allow_high_precision_mv,
-                     cm->cur_frame_force_integer_mv);
+  lower_mv_precision(&this_refmv.as_mv, allow_high_precision_mv,
+                     force_integer_mv);
 
   if (rf[1] == NONE_FRAME) {
     if (blk_row == 0 && blk_col == 0) {
@@ -381,8 +383,8 @@
     int_mv comp_refmv;
     get_mv_projection(&comp_refmv.as_mv, prev_frame_mvs->mfmv0.as_mv,
                       cur_offset_1, prev_frame_mvs->ref_frame_offset);
-    lower_mv_precision(&comp_refmv.as_mv, cm->allow_high_precision_mv,
-                       cm->cur_frame_force_integer_mv);
+    lower_mv_precision(&comp_refmv.as_mv, allow_high_precision_mv,
+                       force_integer_mv);
 
     if (blk_row == 0 && blk_col == 0) {
       if (abs(this_refmv.as_mv.row - gm_mv_candidates[0].as_mv.row) >= 16 ||
@@ -535,7 +537,7 @@
   for (int idx = 0; idx < nearest_refmv_count; ++idx)
     ref_mv_weight[idx] += REF_CAT_LEVEL;
 
-  if (cm->allow_ref_frame_mvs) {
+  if (cm->features.allow_ref_frame_mvs) {
     int is_available = 0;
     const int voffset = AOMMAX(mi_size_high[BLOCK_8X8], xd->n4_h);
     const int hoffset = AOMMAX(mi_size_wide[BLOCK_8X8], xd->n4_w);
@@ -794,21 +796,23 @@
     }
   } else {
     const BLOCK_SIZE bsize = mi->sb_type;
+    const int allow_high_precision_mv = cm->features.allow_high_precision_mv;
+    const int force_integer_mv = cm->features.cur_frame_force_integer_mv;
     if (ref_frame < REF_FRAMES) {
-      gm_mv[0] = gm_get_motion_vector(
-          &cm->global_motion[ref_frame], cm->allow_high_precision_mv, bsize,
-          mi_col, mi_row, cm->cur_frame_force_integer_mv);
+      gm_mv[0] = gm_get_motion_vector(&cm->global_motion[ref_frame],
+                                      allow_high_precision_mv, bsize, mi_col,
+                                      mi_row, force_integer_mv);
       gm_mv[1].as_int = 0;
       if (global_mvs != NULL) global_mvs[ref_frame] = gm_mv[0];
     } else {
       MV_REFERENCE_FRAME rf[2];
       av1_set_ref_frame(rf, ref_frame);
-      gm_mv[0] = gm_get_motion_vector(
-          &cm->global_motion[rf[0]], cm->allow_high_precision_mv, bsize, mi_col,
-          mi_row, cm->cur_frame_force_integer_mv);
-      gm_mv[1] = gm_get_motion_vector(
-          &cm->global_motion[rf[1]], cm->allow_high_precision_mv, bsize, mi_col,
-          mi_row, cm->cur_frame_force_integer_mv);
+      gm_mv[0] = gm_get_motion_vector(&cm->global_motion[rf[0]],
+                                      allow_high_precision_mv, bsize, mi_col,
+                                      mi_row, force_integer_mv);
+      gm_mv[1] = gm_get_motion_vector(&cm->global_motion[rf[1]],
+                                      allow_high_precision_mv, bsize, mi_col,
+                                      mi_row, force_integer_mv);
     }
   }
 
diff --git a/av1/common/reconintra.h b/av1/common/reconintra.h
index 5a2196f..9d20356 100644
--- a/av1/common/reconintra.h
+++ b/av1/common/reconintra.h
@@ -54,8 +54,8 @@
 }
 
 static INLINE int av1_allow_intrabc(const AV1_COMMON *const cm) {
-  return frame_is_intra_only(cm) && cm->allow_screen_content_tools &&
-         cm->allow_intrabc;
+  return frame_is_intra_only(cm) && cm->features.allow_screen_content_tools &&
+         cm->features.allow_intrabc;
 }
 
 static INLINE int av1_filter_intra_allowed_bsize(const AV1_COMMON *const cm,
diff --git a/av1/common/restoration.c b/av1/common/restoration.c
index bf3720a..645b92b 100644
--- a/av1/common/restoration.c
+++ b/av1/common/restoration.c
@@ -1190,7 +1190,7 @@
 void av1_loop_restoration_filter_frame(YV12_BUFFER_CONFIG *frame,
                                        AV1_COMMON *cm, int optimized_lr,
                                        void *lr_ctxt) {
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
   const int num_planes = av1_num_planes(cm);
 
   AV1LrStruct *loop_rest_ctxt = (AV1LrStruct *)lr_ctxt;
@@ -1318,7 +1318,7 @@
   if (bsize != cm->seq_params.sb_size) return 0;
   if (cm->rst_info[plane].frame_restoration_type == RESTORE_NONE) return 0;
 
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   const int is_uv = plane > 0;
 
diff --git a/av1/common/thread_common.c b/av1/common/thread_common.c
index 82ae952..b656e68 100644
--- a/av1/common/thread_common.c
+++ b/av1/common/thread_common.c
@@ -909,7 +909,7 @@
                                           AV1_COMMON *cm, int optimized_lr,
                                           AVxWorker *workers, int num_workers,
                                           AV1LrSync *lr_sync, void *lr_ctxt) {
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   const int num_planes = av1_num_planes(cm);
 
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 0d044dc..a37fc99 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -126,7 +126,7 @@
 }
 
 static TX_MODE read_tx_mode(AV1_COMMON *cm, struct aom_read_bit_buffer *rb) {
-  if (cm->coded_lossless) return ONLY_4X4;
+  if (cm->features.coded_lossless) return ONLY_4X4;
   return aom_rb_read_bit(rb) ? TX_MODE_SELECT : TX_MODE_LARGEST;
 }
 
@@ -216,10 +216,10 @@
     if (eob_data->eob) {
       // tx_type was read out in av1_read_coeffs_txb.
       const TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, row, col, tx_size,
-                                              cm->reduced_tx_set_used);
+                                              cm->features.reduced_tx_set_used);
       uint8_t *dst = &pd->dst.buf[(row * pd->dst.stride + col) << MI_SIZE_LOG2];
       inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
-                              cm->reduced_tx_set_used);
+                              cm->features.reduced_tx_set_used);
     }
   }
   if (plane == AOM_PLANE_Y && store_cfl_required(cm, xd)) {
@@ -236,13 +236,14 @@
   const struct macroblockd_plane *const pd = &xd->plane[plane];
 
   // tx_type was read out in av1_read_coeffs_txb.
-  const TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col,
-                                          tx_size, cm->reduced_tx_set_used);
+  const TX_TYPE tx_type =
+      av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
+                      cm->features.reduced_tx_set_used);
 
   uint8_t *dst =
       &pd->dst.buf[(blk_row * pd->dst.stride + blk_col) << MI_SIZE_LOG2];
   inverse_transform_block(xd, plane, tx_type, tx_size, dst, pd->dst.stride,
-                          cm->reduced_tx_set_used);
+                          cm->features.reduced_tx_set_used);
 #if CONFIG_MISMATCH_DEBUG
   int pixel_c, pixel_r;
   BLOCK_SIZE bsize = txsize_to_bsize[tx_size];
@@ -1763,9 +1764,9 @@
 
 static AOM_INLINE void decode_restoration_mode(AV1_COMMON *cm,
                                                struct aom_read_bit_buffer *rb) {
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
   const int num_planes = av1_num_planes(cm);
-  if (cm->allow_intrabc) return;
+  if (cm->features.allow_intrabc) return;
   int all_none = 1, chroma_none = 1;
   for (int p = 0; p < num_planes; ++p) {
     RestorationInfo *rsi = &cm->rst_info[p];
@@ -1922,7 +1923,7 @@
   RestorationUnitInfo *rui = &rsi->unit_info[runit_idx];
   if (rsi->frame_restoration_type == RESTORE_NONE) return;
 
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   const int wiener_win = (plane > 0) ? WIENER_WIN_CHROMA : WIENER_WIN;
   WienerInfo *wiener_info = xd->wiener_info + plane;
@@ -1962,13 +1963,13 @@
                                         struct aom_read_bit_buffer *rb) {
   const int num_planes = av1_num_planes(cm);
   struct loopfilter *lf = &cm->lf;
-  if (cm->allow_intrabc || cm->coded_lossless) {
+  if (cm->features.allow_intrabc || cm->features.coded_lossless) {
     // write default deltas to frame buffer
     av1_set_default_ref_deltas(cm->cur_frame->ref_deltas);
     av1_set_default_mode_deltas(cm->cur_frame->mode_deltas);
     return;
   }
-  assert(!cm->coded_lossless);
+  assert(!cm->features.coded_lossless);
   if (cm->prev_frame) {
     // write deltas to frame buffer
     memcpy(lf->ref_deltas, cm->prev_frame->ref_deltas, REF_FRAMES);
@@ -2015,7 +2016,7 @@
   const int num_planes = av1_num_planes(cm);
   CdefInfo *const cdef_info = &cm->cdef_info;
 
-  if (cm->allow_intrabc) return;
+  if (cm->features.allow_intrabc) return;
   cdef_info->cdef_damping = aom_rb_read_literal(rb, 2) + 3;
   cdef_info->cdef_bits = aom_rb_read_literal(rb, 2);
   cdef_info->nb_cdef_strengths = 1 << cdef_info->cdef_bits;
@@ -2407,8 +2408,8 @@
         rst_info[0].frame_restoration_type == RESTORE_NONE &&
         rst_info[1].frame_restoration_type == RESTORE_NONE &&
         rst_info[2].frame_restoration_type == RESTORE_NONE;
-    assert(IMPLIES(cm->coded_lossless, no_loopfilter && no_cdef));
-    assert(IMPLIES(cm->all_lossless, no_restoration));
+    assert(IMPLIES(cm->features.coded_lossless, no_loopfilter && no_cdef));
+    assert(IMPLIES(cm->features.all_lossless, no_restoration));
     cm->single_tile_decoding = no_loopfilter && no_cdef && no_restoration;
   }
 }
@@ -2991,7 +2992,7 @@
       (tile_rows_end - 1) * cm->tile_cols + tile_cols_end - 1 < start_tile)
     return data;
 
-  allow_update_cdf = allow_update_cdf && !cm->disable_cdf_update;
+  allow_update_cdf = allow_update_cdf && !cm->features.disable_cdf_update;
 
   assert(tile_rows <= MAX_TILE_ROWS);
   assert(tile_cols <= MAX_TILE_COLS);
@@ -3157,7 +3158,7 @@
   thread_data->error_info.setjmp = 1;
 
   allow_update_cdf = cm->large_scale_tile ? 0 : 1;
-  allow_update_cdf = allow_update_cdf && !cm->disable_cdf_update;
+  allow_update_cdf = allow_update_cdf && !cm->features.disable_cdf_update;
 
   set_decode_func_pointers(td, 0x3);
 
@@ -3402,7 +3403,7 @@
   thread_data->error_info.setjmp = 1;
 
   allow_update_cdf = cm->large_scale_tile ? 0 : 1;
-  allow_update_cdf = allow_update_cdf && !cm->disable_cdf_update;
+  allow_update_cdf = allow_update_cdf && !cm->features.disable_cdf_update;
 
   set_decode_func_pointers(td, 0x1);
 
@@ -4524,8 +4525,9 @@
     const WarpedMotionParams *ref_params =
         cm->prev_frame ? &cm->prev_frame->global_motion[frame]
                        : &default_warp_params;
-    int good_params = read_global_motion_params(
-        &cm->global_motion[frame], ref_params, rb, cm->allow_high_precision_mv);
+    int good_params =
+        read_global_motion_params(&cm->global_motion[frame], ref_params, rb,
+                                  cm->features.allow_high_precision_mv);
     if (!good_params) {
 #if WARPED_MOTION_DEBUG
       printf("Warning: unexpected global motion shear params from aomenc\n");
@@ -4542,7 +4544,7 @@
         cm->height == ref_buf->y_crop_height) {
       read_global_motion_params(&cm->global_motion[frame],
                                 &cm->prev_frame->global_motion[frame], rb,
-                                cm->allow_high_precision_mv);
+                                cm->features.allow_high_precision_mv);
     } else {
       cm->global_motion[frame] = default_warp_params;
     }
@@ -4638,6 +4640,7 @@
   AV1_COMMON *const cm = &pbi->common;
   const SequenceHeader *const seq_params = &cm->seq_params;
   CurrentFrame *const current_frame = &cm->current_frame;
+  FeatureFlags *const features = &cm->features;
   MACROBLOCKD *const xd = &pbi->mb;
   BufferPool *const pool = cm->buffer_pool;
   RefCntBuffer *const frame_bufs = pool->frame_bufs;
@@ -4657,7 +4660,7 @@
       pbi->decoding_first_frame = 1;
       reset_frame_buffers(cm);
     }
-    cm->error_resilient_mode = 1;
+    features->error_resilient_mode = 1;
   } else {
     cm->show_existing_frame = aom_rb_read_bit(rb);
     pbi->reset_decoder_state = 0;
@@ -4761,7 +4764,7 @@
       cm->showable_frame = aom_rb_read_bit(rb);
     }
     cm->cur_frame->showable_frame = cm->showable_frame;
-    cm->error_resilient_mode =
+    features->error_resilient_mode =
         frame_is_sframe(cm) ||
                 (current_frame->frame_type == KEY_FRAME && cm->show_frame)
             ? 1
@@ -4774,25 +4777,26 @@
       pbi->valid_for_referencing[i] = 0;
     }
   }
-  cm->disable_cdf_update = aom_rb_read_bit(rb);
+  features->disable_cdf_update = aom_rb_read_bit(rb);
   if (seq_params->force_screen_content_tools == 2) {
-    cm->allow_screen_content_tools = aom_rb_read_bit(rb);
+    features->allow_screen_content_tools = aom_rb_read_bit(rb);
   } else {
-    cm->allow_screen_content_tools = seq_params->force_screen_content_tools;
+    features->allow_screen_content_tools =
+        seq_params->force_screen_content_tools;
   }
 
-  if (cm->allow_screen_content_tools) {
+  if (features->allow_screen_content_tools) {
     if (seq_params->force_integer_mv == 2) {
-      cm->cur_frame_force_integer_mv = aom_rb_read_bit(rb);
+      features->cur_frame_force_integer_mv = aom_rb_read_bit(rb);
     } else {
-      cm->cur_frame_force_integer_mv = seq_params->force_integer_mv;
+      features->cur_frame_force_integer_mv = seq_params->force_integer_mv;
     }
   } else {
-    cm->cur_frame_force_integer_mv = 0;
+    features->cur_frame_force_integer_mv = 0;
   }
 
   int frame_size_override_flag = 0;
-  cm->allow_intrabc = 0;
+  features->allow_intrabc = 0;
   cm->primary_ref_frame = PRIMARY_REF_NONE;
 
   if (!seq_params->reduced_still_picture_hdr) {
@@ -4844,7 +4848,7 @@
         rb, seq_params->order_hint_info.order_hint_bits_minus_1 + 1);
     current_frame->frame_number = current_frame->order_hint;
 
-    if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) {
+    if (!features->error_resilient_mode && !frame_is_intra_only(cm)) {
       cm->primary_ref_frame = aom_rb_read_literal(rb, PRIMARY_REF_BITS);
     }
   }
@@ -4907,7 +4911,7 @@
 
   if (!frame_is_intra_only(cm) || current_frame->refresh_frame_flags != 0xFF) {
     // Read all ref frame order hints if error_resilient_mode == 1
-    if (cm->error_resilient_mode &&
+    if (features->error_resilient_mode &&
         seq_params->order_hint_info.enable_order_hint) {
       for (int ref_idx = 0; ref_idx < REF_FRAMES; ref_idx++) {
         // Read order hint from bit stream
@@ -4957,19 +4961,19 @@
   if (current_frame->frame_type == KEY_FRAME) {
     setup_frame_size(cm, frame_size_override_flag, rb);
 
-    if (cm->allow_screen_content_tools && !av1_superres_scaled(cm))
-      cm->allow_intrabc = aom_rb_read_bit(rb);
-    cm->allow_ref_frame_mvs = 0;
+    if (features->allow_screen_content_tools && !av1_superres_scaled(cm))
+      features->allow_intrabc = aom_rb_read_bit(rb);
+    features->allow_ref_frame_mvs = 0;
     cm->prev_frame = NULL;
   } else {
-    cm->allow_ref_frame_mvs = 0;
+    features->allow_ref_frame_mvs = 0;
 
     if (current_frame->frame_type == INTRA_ONLY_FRAME) {
       cm->cur_frame->film_grain_params_present =
           seq_params->film_grain_params_present;
       setup_frame_size(cm, frame_size_override_flag, rb);
-      if (cm->allow_screen_content_tools && !av1_superres_scaled(cm))
-        cm->allow_intrabc = aom_rb_read_bit(rb);
+      if (features->allow_screen_content_tools && !av1_superres_scaled(cm))
+        features->allow_intrabc = aom_rb_read_bit(rb);
 
     } else if (pbi->need_resync != 1) { /* Skip if need resync */
       int frame_refs_short_signaling = 0;
@@ -5043,16 +5047,16 @@
         }
       }
 
-      if (!cm->error_resilient_mode && frame_size_override_flag) {
+      if (!features->error_resilient_mode && frame_size_override_flag) {
         setup_frame_size_with_refs(cm, rb);
       } else {
         setup_frame_size(cm, frame_size_override_flag, rb);
       }
 
-      if (cm->cur_frame_force_integer_mv) {
-        cm->allow_high_precision_mv = 0;
+      if (features->cur_frame_force_integer_mv) {
+        features->allow_high_precision_mv = 0;
       } else {
-        cm->allow_high_precision_mv = aom_rb_read_bit(rb);
+        features->allow_high_precision_mv = aom_rb_read_bit(rb);
       }
       cm->interp_filter = read_frame_interp_filter(rb);
       cm->switchable_motion_mode = aom_rb_read_bit(rb);
@@ -5069,9 +5073,9 @@
     if (!(current_frame->frame_type == INTRA_ONLY_FRAME) &&
         pbi->need_resync != 1) {
       if (frame_might_allow_ref_frame_mvs(cm))
-        cm->allow_ref_frame_mvs = aom_rb_read_bit(rb);
+        features->allow_ref_frame_mvs = aom_rb_read_bit(rb);
       else
-        cm->allow_ref_frame_mvs = 0;
+        features->allow_ref_frame_mvs = 0;
 
       for (int i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
         const RefCntBuffer *const ref_buf = get_ref_frame_buf(cm, i);
@@ -5095,8 +5099,8 @@
 
   update_ref_frame_id(pbi);
 
-  const int might_bwd_adapt =
-      !(seq_params->reduced_still_picture_hdr) && !(cm->disable_cdf_update);
+  const int might_bwd_adapt = !(seq_params->reduced_still_picture_hdr) &&
+                              !(features->disable_cdf_update);
   if (might_bwd_adapt) {
     cm->refresh_frame_context = aom_rb_read_bit(rb)
                                     ? REFRESH_FRAME_CONTEXT_DISABLED
@@ -5123,7 +5127,7 @@
                        " state");
   }
 
-  if (cm->allow_intrabc) {
+  if (features->allow_intrabc) {
     // Set parameters corresponding to no filtering.
     struct loopfilter *lf = &cm->lf;
     lf->filter_level[0] = 0;
@@ -5170,7 +5174,7 @@
   if (cm->delta_q_info.delta_q_present_flag) {
     xd->current_qindex = cm->base_qindex;
     cm->delta_q_info.delta_q_res = 1 << aom_rb_read_literal(rb, 2);
-    if (!cm->allow_intrabc)
+    if (!features->allow_intrabc)
       cm->delta_q_info.delta_lf_present_flag = aom_rb_read_bit(rb);
     if (cm->delta_q_info.delta_lf_present_flag) {
       cm->delta_q_info.delta_lf_res = 1 << aom_rb_read_literal(rb, 2);
@@ -5179,7 +5183,7 @@
     }
   }
 
-  xd->cur_frame_force_integer_mv = cm->cur_frame_force_integer_mv;
+  xd->cur_frame_force_integer_mv = features->cur_frame_force_integer_mv;
 
   for (int i = 0; i < MAX_SEGMENTS; ++i) {
     const int qindex = av1_get_qindex(&cm->seg, i, cm->base_qindex);
@@ -5188,29 +5192,29 @@
                       cm->v_dc_delta_q == 0 && cm->v_ac_delta_q == 0;
     xd->qindex[i] = qindex;
   }
-  cm->coded_lossless = is_coded_lossless(cm, xd);
-  cm->all_lossless = cm->coded_lossless && !av1_superres_scaled(cm);
+  features->coded_lossless = is_coded_lossless(cm, xd);
+  features->all_lossless = features->coded_lossless && !av1_superres_scaled(cm);
   setup_segmentation_dequant(cm, xd);
-  if (cm->coded_lossless) {
+  if (features->coded_lossless) {
     cm->lf.filter_level[0] = 0;
     cm->lf.filter_level[1] = 0;
   }
-  if (cm->coded_lossless || !seq_params->enable_cdef) {
+  if (features->coded_lossless || !seq_params->enable_cdef) {
     cm->cdef_info.cdef_bits = 0;
     cm->cdef_info.cdef_strengths[0] = 0;
     cm->cdef_info.cdef_uv_strengths[0] = 0;
   }
-  if (cm->all_lossless || !seq_params->enable_restoration) {
+  if (features->all_lossless || !seq_params->enable_restoration) {
     cm->rst_info[0].frame_restoration_type = RESTORE_NONE;
     cm->rst_info[1].frame_restoration_type = RESTORE_NONE;
     cm->rst_info[2].frame_restoration_type = RESTORE_NONE;
   }
   setup_loopfilter(cm, rb);
 
-  if (!cm->coded_lossless && seq_params->enable_cdef) {
+  if (!features->coded_lossless && seq_params->enable_cdef) {
     setup_cdef(cm, rb);
   }
-  if (!cm->all_lossless && seq_params->enable_restoration) {
+  if (!features->all_lossless && seq_params->enable_restoration) {
     decode_restoration_mode(cm, rb);
   }
 
@@ -5222,13 +5226,13 @@
       current_frame->skip_mode_info.skip_mode_allowed ? aom_rb_read_bit(rb) : 0;
 
   if (frame_might_allow_warped_motion(cm))
-    cm->allow_warped_motion = aom_rb_read_bit(rb);
+    features->allow_warped_motion = aom_rb_read_bit(rb);
   else
-    cm->allow_warped_motion = 0;
+    features->allow_warped_motion = 0;
 
-  cm->reduced_tx_set_used = aom_rb_read_bit(rb);
+  features->reduced_tx_set_used = aom_rb_read_bit(rb);
 
-  if (cm->allow_ref_frame_mvs && !frame_might_allow_ref_frame_mvs(cm)) {
+  if (features->allow_ref_frame_mvs && !frame_might_allow_ref_frame_mvs(cm)) {
     aom_internal_error(&cm->error, AOM_CODEC_CORRUPT_FRAME,
                        "Frame wrongly requests reference frame MVs");
   }
@@ -5275,7 +5279,7 @@
   BufferPool *const pool = cm->buffer_pool;
 
   if (!av1_superres_scaled(cm)) return;
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   av1_superres_upscale(cm, pool);
 }
@@ -5408,7 +5412,7 @@
     return;
   }
 
-  if (!cm->allow_intrabc && !cm->single_tile_decoding) {
+  if (!cm->features.allow_intrabc && !cm->single_tile_decoding) {
     if (cm->lf.filter_level[0] || cm->lf.filter_level[1]) {
       if (pbi->num_workers > 1) {
         av1_loop_filter_frame_mt(
@@ -5431,7 +5435,7 @@
         cm->rst_info[1].frame_restoration_type != RESTORE_NONE ||
         cm->rst_info[2].frame_restoration_type != RESTORE_NONE;
     const int do_cdef =
-        !pbi->skip_loop_filter && !cm->coded_lossless &&
+        !pbi->skip_loop_filter && !cm->features.coded_lossless &&
         (cm->cdef_info.cdef_bits || cm->cdef_info.cdef_strengths[0] ||
          cm->cdef_info.cdef_uv_strengths[0]);
     const int do_superres = av1_superres_scaled(cm);
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index c194d47..fd122e3 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -38,8 +38,8 @@
 
 static void read_cdef(AV1_COMMON *cm, aom_reader *r, MACROBLOCKD *const xd) {
   MB_MODE_INFO *const mbmi = xd->mi[0];
-  if (cm->coded_lossless) return;
-  if (cm->allow_intrabc) {
+  if (cm->features.coded_lossless) return;
+  if (cm->features.allow_intrabc) {
     assert(cm->cdef_info.cdef_bits == 0);
     return;
   }
@@ -210,8 +210,8 @@
   if (cm->switchable_motion_mode == 0) return SIMPLE_TRANSLATION;
   if (mbmi->skip_mode) return SIMPLE_TRANSLATION;
 
-  const MOTION_MODE last_motion_mode_allowed =
-      motion_mode_allowed(xd->global_motion, xd, mbmi, cm->allow_warped_motion);
+  const MOTION_MODE last_motion_mode_allowed = motion_mode_allowed(
+      xd->global_motion, xd, mbmi, cm->features.allow_warped_motion);
   int motion_mode;
 
   if (last_motion_mode_allowed == SIMPLE_TRANSLATION) return SIMPLE_TRANSLATION;
@@ -544,7 +544,7 @@
   const int num_planes = av1_num_planes(cm);
   MB_MODE_INFO *const mbmi = xd->mi[0];
   const BLOCK_SIZE bsize = mbmi->sb_type;
-  assert(av1_allow_palette(cm->allow_screen_content_tools, bsize));
+  assert(av1_allow_palette(cm->features.allow_screen_content_tools, bsize));
   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
   const int bsize_ctx = av1_get_palette_bsize_ctx(bsize);
 
@@ -614,11 +614,12 @@
   if (qindex == 0) return;
 
   const int inter_block = is_inter_block(mbmi);
-  if (get_ext_tx_types(tx_size, inter_block, cm->reduced_tx_set_used) > 1) {
-    const TxSetType tx_set_type =
-        av1_get_ext_tx_set_type(tx_size, inter_block, cm->reduced_tx_set_used);
+  if (get_ext_tx_types(tx_size, inter_block, cm->features.reduced_tx_set_used) >
+      1) {
+    const TxSetType tx_set_type = av1_get_ext_tx_set_type(
+        tx_size, inter_block, cm->features.reduced_tx_set_used);
     const int eset =
-        get_ext_tx_set(tx_size, inter_block, cm->reduced_tx_set_used);
+        get_ext_tx_set(tx_size, inter_block, cm->features.reduced_tx_set_used);
     // eset == 0 should correspond to a set with only DCT_DCT and
     // there is no need to read the tx_type
     assert(eset != 0);
@@ -808,7 +809,7 @@
   }
   xd->cfl.store_y = store_cfl_required(cm, xd);
 
-  if (av1_allow_palette(cm->allow_screen_content_tools, bsize))
+  if (av1_allow_palette(cm->features.allow_screen_content_tools, bsize))
     read_palette_mode_info(cm, xd, r);
 
   read_filter_intra_mode_info(cm, xd, r);
@@ -1070,7 +1071,7 @@
 
   mbmi->palette_mode_info.palette_size[0] = 0;
   mbmi->palette_mode_info.palette_size[1] = 0;
-  if (av1_allow_palette(cm->allow_screen_content_tools, bsize))
+  if (av1_allow_palette(cm->features.allow_screen_content_tools, bsize))
     read_palette_mode_info(cm, xd, r);
 
   read_filter_intra_mode_info(cm, xd, r);
@@ -1090,7 +1091,8 @@
   FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
   MB_MODE_INFO *mbmi = xd->mi[0];
   BLOCK_SIZE bsize = mbmi->sb_type;
-  if (cm->cur_frame_force_integer_mv) {
+  FeatureFlags *const features = &cm->features;
+  if (features->cur_frame_force_integer_mv) {
     allow_hp = MV_SUBPEL_NONE;
   }
   switch (mode) {
@@ -1108,11 +1110,11 @@
       break;
     }
     case GLOBALMV: {
-      mv[0].as_int =
-          gm_get_motion_vector(&cm->global_motion[ref_frame[0]],
-                               cm->allow_high_precision_mv, bsize, xd->mi_col,
-                               xd->mi_row, cm->cur_frame_force_integer_mv)
-              .as_int;
+      mv[0].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[0]],
+                                          features->allow_high_precision_mv,
+                                          bsize, xd->mi_col, xd->mi_row,
+                                          features->cur_frame_force_integer_mv)
+                         .as_int;
       break;
     }
     case NEW_NEWMV: {
@@ -1165,16 +1167,16 @@
     }
     case GLOBAL_GLOBALMV: {
       assert(is_compound);
-      mv[0].as_int =
-          gm_get_motion_vector(&cm->global_motion[ref_frame[0]],
-                               cm->allow_high_precision_mv, bsize, xd->mi_col,
-                               xd->mi_row, cm->cur_frame_force_integer_mv)
-              .as_int;
-      mv[1].as_int =
-          gm_get_motion_vector(&cm->global_motion[ref_frame[1]],
-                               cm->allow_high_precision_mv, bsize, xd->mi_col,
-                               xd->mi_row, cm->cur_frame_force_integer_mv)
-              .as_int;
+      mv[0].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[0]],
+                                          features->allow_high_precision_mv,
+                                          bsize, xd->mi_col, xd->mi_row,
+                                          features->cur_frame_force_integer_mv)
+                         .as_int;
+      mv[1].as_int = gm_get_motion_vector(&cm->global_motion[ref_frame[1]],
+                                          features->allow_high_precision_mv,
+                                          bsize, xd->mi_col, xd->mi_row,
+                                          features->cur_frame_force_integer_mv)
+                         .as_int;
       break;
     }
     default: { return 0; }
@@ -1242,8 +1244,9 @@
                                        MB_MODE_INFO *const mbmi,
                                        aom_reader *r) {
   AV1_COMMON *const cm = &pbi->common;
+  FeatureFlags *const features = &cm->features;
   const BLOCK_SIZE bsize = mbmi->sb_type;
-  const int allow_hp = cm->allow_high_precision_mv;
+  const int allow_hp = features->allow_high_precision_mv;
   int_mv nearestmv[2], nearmv[2];
   int_mv ref_mvs[MODE_CTX_REF_FRAMES][MAX_MV_REF_CANDIDATES] = { { { 0 } } };
   int16_t inter_mode_ctx[MODE_CTX_REF_FRAMES];
@@ -1293,7 +1296,7 @@
 
   if (!is_compound && mbmi->mode != GLOBALMV) {
     av1_find_best_ref_mvs(allow_hp, ref_mvs[mbmi->ref_frame[0]], &nearestmv[0],
-                          &nearmv[0], cm->cur_frame_force_integer_mv);
+                          &nearmv[0], features->cur_frame_force_integer_mv);
   }
 
   if (is_compound && mbmi->mode != GLOBAL_GLOBALMV) {
@@ -1303,13 +1306,13 @@
     nearmv[0] = xd->ref_mv_stack[ref_frame][ref_mv_idx].this_mv;
     nearmv[1] = xd->ref_mv_stack[ref_frame][ref_mv_idx].comp_mv;
     lower_mv_precision(&nearestmv[0].as_mv, allow_hp,
-                       cm->cur_frame_force_integer_mv);
+                       features->cur_frame_force_integer_mv);
     lower_mv_precision(&nearestmv[1].as_mv, allow_hp,
-                       cm->cur_frame_force_integer_mv);
+                       features->cur_frame_force_integer_mv);
     lower_mv_precision(&nearmv[0].as_mv, allow_hp,
-                       cm->cur_frame_force_integer_mv);
+                       features->cur_frame_force_integer_mv);
     lower_mv_precision(&nearmv[1].as_mv, allow_hp,
-                       cm->cur_frame_force_integer_mv);
+                       features->cur_frame_force_integer_mv);
   } else if (mbmi->ref_mv_idx > 0 && mbmi->mode == NEARMV) {
     nearmv[0] =
         xd->ref_mv_stack[mbmi->ref_frame[0]][1 + mbmi->ref_mv_idx].this_mv;
diff --git a/av1/decoder/decodetxb.c b/av1/decoder/decodetxb.c
index dd69dd2..116b64c 100644
--- a/av1/decoder/decodetxb.c
+++ b/av1/decoder/decodetxb.c
@@ -157,8 +157,9 @@
     // only y plane's tx_type is transmitted
     av1_read_tx_type(cm, xd, blk_row, blk_col, tx_size, r);
   }
-  const TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col,
-                                          tx_size, cm->reduced_tx_set_used);
+  const TX_TYPE tx_type =
+      av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
+                      cm->features.reduced_tx_set_used);
   const TX_CLASS tx_class = tx_type_to_class[tx_type];
   const TX_SIZE qm_tx_size = av1_get_adjusted_tx_size(tx_size);
   const qm_val_t *iqmatrix =
@@ -349,7 +350,7 @@
     const PLANE_TYPE plane_type = get_plane_type(plane);
     // tx_type will be read out in av1_read_coeffs_txb_facade
     const TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, row, col, tx_size,
-                                            cm->reduced_tx_set_used);
+                                            cm->features.reduced_tx_set_used);
 
     if (plane == 0) {
       const int txw = tx_size_wide_unit[tx_size];
diff --git a/av1/encoder/aq_complexity.c b/av1/encoder/aq_complexity.c
index 8696fcf..70740c7 100644
--- a/av1/encoder/aq_complexity.c
+++ b/av1/encoder/aq_complexity.c
@@ -48,7 +48,7 @@
 static bool is_frame_aq_enabled(const AV1_COMP *const cpi) {
   const AV1_COMMON *const cm = &cpi->common;
 
-  return frame_is_intra_only(cm) || cm->error_resilient_mode ||
+  return frame_is_intra_only(cm) || cm->features.error_resilient_mode ||
          cpi->refresh_alt_ref_frame ||
          (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref);
 }
diff --git a/av1/encoder/aq_cyclicrefresh.c b/av1/encoder/aq_cyclicrefresh.c
index a5e1953..c3b266a 100644
--- a/av1/encoder/aq_cyclicrefresh.c
+++ b/av1/encoder/aq_cyclicrefresh.c
@@ -286,8 +286,8 @@
     int mi_row = sb_row_index * cm->seq_params.mib_size;
     int mi_col = sb_col_index * cm->seq_params.mib_size;
     // TODO(any): Ensure the population of
-    // cpi->common.allow_screen_content_tools and use the same instead of
-    // cpi->oxcf.content == AOM_CONTENT_SCREEN
+    // cpi->common.features.allow_screen_content_tools and use the same instead
+    // of cpi->oxcf.content == AOM_CONTENT_SCREEN
     int qindex_thresh =
         cpi->oxcf.content == AOM_CONTENT_SCREEN
             ? av1_get_qindex(&cm->seg, CR_SEGMENT_ID_BOOST2, cm->base_qindex)
diff --git a/av1/encoder/aq_variance.c b/av1/encoder/aq_variance.c
index fcd0e4f..07b1dac 100644
--- a/av1/encoder/aq_variance.c
+++ b/av1/encoder/aq_variance.c
@@ -63,7 +63,7 @@
     av1_disable_segmentation(seg);
     return;
   }
-  if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
+  if (frame_is_intra_only(cm) || cm->features.error_resilient_mode ||
       cpi->refresh_alt_ref_frame ||
       (cpi->refresh_golden_frame && !cpi->rc.is_src_frame_alt_ref)) {
     cpi->vaq_refresh = 1;
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index 338ce70..841f9b4 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -271,7 +271,7 @@
   MOTION_MODE last_motion_mode_allowed =
       cm->switchable_motion_mode
           ? motion_mode_allowed(cm->global_motion, xd, mbmi,
-                                cm->allow_warped_motion)
+                                cm->features.allow_warped_motion)
           : SIMPLE_TRANSLATION;
   assert(mbmi->motion_mode <= last_motion_mode_allowed);
   switch (last_motion_mode_allowed) {
@@ -755,7 +755,7 @@
                                                aom_writer *w) {
   const int num_planes = av1_num_planes(cm);
   const BLOCK_SIZE bsize = mbmi->sb_type;
-  assert(av1_allow_palette(cm->allow_screen_content_tools, bsize));
+  assert(av1_allow_palette(cm->features.allow_screen_content_tools, bsize));
   const PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
   const int bsize_ctx = av1_get_palette_bsize_ctx(bsize);
 
@@ -792,17 +792,19 @@
 void av1_write_tx_type(const AV1_COMMON *const cm, const MACROBLOCKD *xd,
                        TX_TYPE tx_type, TX_SIZE tx_size, aom_writer *w) {
   MB_MODE_INFO *mbmi = xd->mi[0];
+  const FeatureFlags *const features = &cm->features;
   const int is_inter = is_inter_block(mbmi);
-  if (get_ext_tx_types(tx_size, is_inter, cm->reduced_tx_set_used) > 1 &&
+  if (get_ext_tx_types(tx_size, is_inter, features->reduced_tx_set_used) > 1 &&
       ((!cm->seg.enabled && cm->base_qindex > 0) ||
        (cm->seg.enabled && xd->qindex[mbmi->segment_id] > 0)) &&
       !mbmi->skip &&
       !segfeature_active(&cm->seg, mbmi->segment_id, SEG_LVL_SKIP)) {
     FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
     const TX_SIZE square_tx_size = txsize_sqr_map[tx_size];
-    const TxSetType tx_set_type =
-        av1_get_ext_tx_set_type(tx_size, is_inter, cm->reduced_tx_set_used);
-    const int eset = get_ext_tx_set(tx_size, is_inter, cm->reduced_tx_set_used);
+    const TxSetType tx_set_type = av1_get_ext_tx_set_type(
+        tx_size, is_inter, features->reduced_tx_set_used);
+    const int eset =
+        get_ext_tx_set(tx_size, is_inter, features->reduced_tx_set_used);
     // eset == 0 should correspond to a set with only DCT_DCT and there
     // is no need to send the tx_type
     assert(eset > 0);
@@ -860,7 +862,7 @@
 
 static AOM_INLINE void write_cdef(AV1_COMMON *cm, MACROBLOCKD *const xd,
                                   aom_writer *w, int skip) {
-  if (cm->coded_lossless || cm->allow_intrabc) return;
+  if (cm->features.coded_lossless || cm->features.allow_intrabc) return;
 
   const int m = ~((1 << (6 - MI_SIZE_LOG2)) - 1);
   const int mi_row = xd->mi_row;
@@ -1009,7 +1011,7 @@
   }
 
   // Palette.
-  if (av1_allow_palette(cm->allow_screen_content_tools, bsize)) {
+  if (av1_allow_palette(cm->features.allow_screen_content_tools, bsize)) {
     write_palette_mode_info(cm, xd, mbmi, w);
   }
 
@@ -1071,7 +1073,7 @@
   const PREDICTION_MODE mode = mbmi->mode;
   const int segment_id = mbmi->segment_id;
   const BLOCK_SIZE bsize = mbmi->sb_type;
-  const int allow_hp = cm->allow_high_precision_mv;
+  const int allow_hp = cm->features.allow_high_precision_mv;
   const int is_inter = is_inter_block(mbmi);
   const int is_compound = has_second_ref(mbmi);
   int ref;
@@ -1495,7 +1497,8 @@
     assert(!mbmi->skip_mode || !palette_size_plane);
     if (palette_size_plane > 0) {
       assert(mbmi->use_intrabc == 0);
-      assert(av1_allow_palette(cm->allow_screen_content_tools, mbmi->sb_type));
+      assert(av1_allow_palette(cm->features.allow_screen_content_tools,
+                               mbmi->sb_type));
       assert(!plane || xd->is_chroma_ref);
       int rows, cols;
       av1_get_block_dimensions(mbmi->sb_type, plane, xd, NULL, NULL, &rows,
@@ -1714,9 +1717,9 @@
 
 static AOM_INLINE void encode_restoration_mode(
     AV1_COMMON *cm, struct aom_write_bit_buffer *wb) {
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
   if (!cm->seq_params.enable_restoration) return;
-  if (cm->allow_intrabc) return;
+  if (cm->features.allow_intrabc) return;
   const int num_planes = av1_num_planes(cm);
   int all_none = 1, chroma_none = 1;
   for (int p = 0; p < num_planes; ++p) {
@@ -1867,7 +1870,7 @@
   if (frame_rtype == RESTORE_NONE) return;
 
   (void)counts;
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   const int wiener_win = (plane > 0) ? WIENER_WIN_CHROMA : WIENER_WIN;
   WienerInfo *ref_wiener_info = &xd->wiener_info[plane];
@@ -1942,8 +1945,8 @@
 
 static AOM_INLINE void encode_loopfilter(AV1_COMMON *cm,
                                          struct aom_write_bit_buffer *wb) {
-  assert(!cm->coded_lossless);
-  if (cm->allow_intrabc) return;
+  assert(!cm->features.coded_lossless);
+  if (cm->features.allow_intrabc) return;
   const int num_planes = av1_num_planes(cm);
   struct loopfilter *lf = &cm->lf;
 
@@ -1994,9 +1997,9 @@
 
 static AOM_INLINE void encode_cdef(const AV1_COMMON *cm,
                                    struct aom_write_bit_buffer *wb) {
-  assert(!cm->coded_lossless);
+  assert(!cm->features.coded_lossless);
   if (!cm->seq_params.enable_cdef) return;
-  if (cm->allow_intrabc) return;
+  if (cm->features.allow_intrabc) return;
   const int num_planes = av1_num_planes(cm);
   int i;
   aom_wb_write_literal(wb, cm->cdef_info.cdef_damping - 3, 2);
@@ -2718,7 +2721,7 @@
         cm->prev_frame ? &cm->prev_frame->global_motion[frame]
                        : &default_warp_params;
     write_global_motion_params(&cm->global_motion[frame], ref_params, wb,
-                               cm->allow_high_precision_mv);
+                               cm->features.allow_high_precision_mv);
     // TODO(sarahparker, debargha): The logic in the commented out code below
     // does not work currently and causes mismatches when resize is on.
     // Fix it before turning the optimization back on.
@@ -2728,7 +2731,7 @@
         cpi->source->y_crop_height == ref_buf->y_crop_height) {
       write_global_motion_params(&cm->global_motion[frame],
                                  &cm->prev_frame->global_motion[frame], wb,
-                                 cm->allow_high_precision_mv);
+                                 cm->features.allow_high_precision_mv);
     } else {
       assert(cm->global_motion[frame].wmtype == IDENTITY &&
              "Invalid warp type for frames of different resolutions");
@@ -2820,6 +2823,7 @@
   const SequenceHeader *const seq_params = &cm->seq_params;
   MACROBLOCKD *const xd = &cpi->td.mb.e_mbd;
   CurrentFrame *const current_frame = &cm->current_frame;
+  FeatureFlags *const features = &cm->features;
 
   current_frame->frame_refs_short_signaling = 0;
 
@@ -2858,28 +2862,29 @@
       aom_wb_write_bit(wb, cm->showable_frame);
     }
     if (frame_is_sframe(cm)) {
-      assert(cm->error_resilient_mode);
+      assert(features->error_resilient_mode);
     } else if (!(current_frame->frame_type == KEY_FRAME && cm->show_frame)) {
-      aom_wb_write_bit(wb, cm->error_resilient_mode);
+      aom_wb_write_bit(wb, features->error_resilient_mode);
     }
   }
-  aom_wb_write_bit(wb, cm->disable_cdf_update);
+  aom_wb_write_bit(wb, features->disable_cdf_update);
 
   if (seq_params->force_screen_content_tools == 2) {
-    aom_wb_write_bit(wb, cm->allow_screen_content_tools);
+    aom_wb_write_bit(wb, features->allow_screen_content_tools);
   } else {
-    assert(cm->allow_screen_content_tools ==
+    assert(features->allow_screen_content_tools ==
            seq_params->force_screen_content_tools);
   }
 
-  if (cm->allow_screen_content_tools) {
+  if (features->allow_screen_content_tools) {
     if (seq_params->force_integer_mv == 2) {
-      aom_wb_write_bit(wb, cm->cur_frame_force_integer_mv);
+      aom_wb_write_bit(wb, features->cur_frame_force_integer_mv);
     } else {
-      assert(cm->cur_frame_force_integer_mv == seq_params->force_integer_mv);
+      assert(features->cur_frame_force_integer_mv ==
+             seq_params->force_integer_mv);
     }
   } else {
-    assert(cm->cur_frame_force_integer_mv == 0);
+    assert(features->cur_frame_force_integer_mv == 0);
   }
 
   int frame_size_override_flag = 0;
@@ -2911,7 +2916,7 @@
           wb, current_frame->order_hint,
           seq_params->order_hint_info.order_hint_bits_minus_1 + 1);
 
-    if (!cm->error_resilient_mode && !frame_is_intra_only(cm)) {
+    if (!features->error_resilient_mode && !frame_is_intra_only(cm)) {
       aom_wb_write_literal(wb, cm->primary_ref_frame, PRIMARY_REF_BITS);
     }
   }
@@ -2952,7 +2957,7 @@
 
   if (!frame_is_intra_only(cm) || current_frame->refresh_frame_flags != 0xff) {
     // Write all ref frame order hints if error_resilient_mode == 1
-    if (cm->error_resilient_mode &&
+    if (features->error_resilient_mode &&
         seq_params->order_hint_info.enable_order_hint) {
       for (int ref_idx = 0; ref_idx < REF_FRAMES; ref_idx++) {
         aom_wb_write_literal(
@@ -2964,15 +2969,15 @@
 
   if (current_frame->frame_type == KEY_FRAME) {
     write_frame_size(cm, frame_size_override_flag, wb);
-    assert(!av1_superres_scaled(cm) || !cm->allow_intrabc);
-    if (cm->allow_screen_content_tools && !av1_superres_scaled(cm))
-      aom_wb_write_bit(wb, cm->allow_intrabc);
+    assert(!av1_superres_scaled(cm) || !features->allow_intrabc);
+    if (features->allow_screen_content_tools && !av1_superres_scaled(cm))
+      aom_wb_write_bit(wb, features->allow_intrabc);
   } else {
     if (current_frame->frame_type == INTRA_ONLY_FRAME) {
       write_frame_size(cm, frame_size_override_flag, wb);
-      assert(!av1_superres_scaled(cm) || !cm->allow_intrabc);
-      if (cm->allow_screen_content_tools && !av1_superres_scaled(cm))
-        aom_wb_write_bit(wb, cm->allow_intrabc);
+      assert(!av1_superres_scaled(cm) || !features->allow_intrabc);
+      if (features->allow_screen_content_tools && !av1_superres_scaled(cm))
+        aom_wb_write_bit(wb, features->allow_intrabc);
     } else if (current_frame->frame_type == INTER_FRAME ||
                frame_is_sframe(cm)) {
       MV_REFERENCE_FRAME ref_frame;
@@ -3028,26 +3033,26 @@
         }
       }
 
-      if (!cm->error_resilient_mode && frame_size_override_flag) {
+      if (!features->error_resilient_mode && frame_size_override_flag) {
         write_frame_size_with_refs(cm, wb);
       } else {
         write_frame_size(cm, frame_size_override_flag, wb);
       }
 
-      if (!cm->cur_frame_force_integer_mv)
-        aom_wb_write_bit(wb, cm->allow_high_precision_mv);
+      if (!features->cur_frame_force_integer_mv)
+        aom_wb_write_bit(wb, features->allow_high_precision_mv);
       write_frame_interp_filter(cm->interp_filter, wb);
       aom_wb_write_bit(wb, cm->switchable_motion_mode);
       if (frame_might_allow_ref_frame_mvs(cm)) {
-        aom_wb_write_bit(wb, cm->allow_ref_frame_mvs);
+        aom_wb_write_bit(wb, features->allow_ref_frame_mvs);
       } else {
-        assert(cm->allow_ref_frame_mvs == 0);
+        assert(features->allow_ref_frame_mvs == 0);
       }
     }
   }
 
-  const int might_bwd_adapt =
-      !(seq_params->reduced_still_picture_hdr) && !(cm->disable_cdf_update);
+  const int might_bwd_adapt = !(seq_params->reduced_still_picture_hdr) &&
+                              !(features->disable_cdf_update);
   if (cm->large_scale_tile)
     assert(cm->refresh_frame_context == REFRESH_FRAME_CONTEXT_DISABLED);
 
@@ -3067,7 +3072,7 @@
     if (delta_q_info->delta_q_present_flag) {
       aom_wb_write_literal(wb, get_msb(delta_q_info->delta_q_res), 2);
       xd->current_qindex = cm->base_qindex;
-      if (cm->allow_intrabc)
+      if (features->allow_intrabc)
         assert(delta_q_info->delta_lf_present_flag == 0);
       else
         aom_wb_write_bit(wb, delta_q_info->delta_lf_present_flag);
@@ -3079,10 +3084,10 @@
     }
   }
 
-  if (cm->all_lossless) {
+  if (features->all_lossless) {
     assert(!av1_superres_scaled(cm));
   } else {
-    if (!cm->coded_lossless) {
+    if (!features->coded_lossless) {
       encode_loopfilter(cm, wb);
       encode_cdef(cm, wb);
     }
@@ -3090,7 +3095,7 @@
   }
 
   // Write TX mode
-  if (cm->coded_lossless)
+  if (features->coded_lossless)
     assert(cm->tx_mode == ONLY_4X4);
   else
     aom_wb_write_bit(wb, cm->tx_mode == TX_MODE_SELECT);
@@ -3106,11 +3111,11 @@
     aom_wb_write_bit(wb, current_frame->skip_mode_info.skip_mode_flag);
 
   if (frame_might_allow_warped_motion(cm))
-    aom_wb_write_bit(wb, cm->allow_warped_motion);
+    aom_wb_write_bit(wb, features->allow_warped_motion);
   else
-    assert(!cm->allow_warped_motion);
+    assert(!features->allow_warped_motion);
 
-  aom_wb_write_bit(wb, cm->reduced_tx_set_used);
+  aom_wb_write_bit(wb, features->reduced_tx_set_used);
 
   if (!frame_is_intra_only(cm)) write_global_motion(cpi, wb);
 
@@ -3509,7 +3514,7 @@
         cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx;
         mode_bc.allow_update_cdf = !cm->large_scale_tile;
         mode_bc.allow_update_cdf =
-            mode_bc.allow_update_cdf && !cm->disable_cdf_update;
+            mode_bc.allow_update_cdf && !cm->features.disable_cdf_update;
         aom_start_encode(&mode_bc, buf->data + data_offset);
         write_modes(cpi, &tile_info, &mode_bc, tile_row, tile_col);
         aom_stop_encode(&mode_bc);
@@ -3648,7 +3653,7 @@
       cpi->td.mb.e_mbd.tile_ctx = &this_tile->tctx;
       mode_bc.allow_update_cdf = 1;
       mode_bc.allow_update_cdf =
-          mode_bc.allow_update_cdf && !cm->disable_cdf_update;
+          mode_bc.allow_update_cdf && !cm->features.disable_cdf_update;
       const int num_planes = av1_num_planes(cm);
       av1_reset_loop_restoration(&cpi->td.mb.e_mbd, num_planes);
 
@@ -3686,7 +3691,7 @@
           saved_wb->bit_buffer += length_field_size;
         }
 
-        if (!first_tg && cm->error_resilient_mode) {
+        if (!first_tg && cm->features.error_resilient_mode) {
           // Make room for a duplicate Frame Header OBU.
           memmove(data + fh_info->total_length, data, curr_tg_data_size);
 
diff --git a/av1/encoder/encode_strategy.c b/av1/encoder/encode_strategy.c
index eecaabb..f722991 100644
--- a/av1/encoder/encode_strategy.c
+++ b/av1/encoder/encode_strategy.c
@@ -121,9 +121,15 @@
 
 static void set_additional_frame_flags(const AV1_COMMON *const cm,
                                        unsigned int *const frame_flags) {
-  if (frame_is_intra_only(cm)) *frame_flags |= FRAMEFLAGS_INTRAONLY;
-  if (frame_is_sframe(cm)) *frame_flags |= FRAMEFLAGS_SWITCH;
-  if (cm->error_resilient_mode) *frame_flags |= FRAMEFLAGS_ERROR_RESILIENT;
+  if (frame_is_intra_only(cm)) {
+    *frame_flags |= FRAMEFLAGS_INTRAONLY;
+  }
+  if (frame_is_sframe(cm)) {
+    *frame_flags |= FRAMEFLAGS_SWITCH;
+  }
+  if (cm->features.error_resilient_mode) {
+    *frame_flags |= FRAMEFLAGS_ERROR_RESILIENT;
+  }
 }
 
 static INLINE void update_keyframe_counters(AV1_COMP *cpi) {
@@ -199,7 +205,7 @@
     cm->refresh_frame_context = cpi->ext_refresh_frame_context;
     cpi->ext_refresh_frame_context_pending = 0;
   }
-  cm->allow_ref_frame_mvs = cpi->ext_use_ref_frame_mvs;
+  cm->features.allow_ref_frame_mvs = cpi->ext_use_ref_frame_mvs;
 
   frame_params->error_resilient_mode = cpi->ext_use_error_resilient;
   // A keyframe is already error resilient and keyframes with
@@ -270,7 +276,7 @@
   const int current_frame_ref_type =
       get_current_frame_ref_type(cpi, frame_params);
 
-  if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
+  if (frame_is_intra_only(cm) || cm->features.error_resilient_mode ||
       cpi->ext_use_primary_ref_none) {
     for (int i = 0; i < REF_FRAMES; i++) {
       fb_of_context_type[i] = -1;
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 23c6e1f..275644d 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -1074,7 +1074,7 @@
                mbmi->angle_delta[PLANE_TYPE_UV] + MAX_ANGLE_DELTA,
                2 * MAX_ANGLE_DELTA + 1);
   }
-  if (av1_allow_palette(cm->allow_screen_content_tools, bsize)) {
+  if (av1_allow_palette(cm->features.allow_screen_content_tools, bsize)) {
     update_palette_cdf(xd, mbmi, counts);
   }
 }
@@ -1346,7 +1346,7 @@
       const MOTION_MODE motion_allowed =
           cm->switchable_motion_mode
               ? motion_mode_allowed(xd->global_motion, xd, mbmi,
-                                    cm->allow_warped_motion)
+                                    cm->features.allow_warped_motion)
               : SIMPLE_TRANSLATION;
       if (mbmi->ref_frame[1] != INTRA_FRAME) {
         if (motion_allowed == WARPED_CAUSAL) {
@@ -1462,9 +1462,9 @@
       }
     }
     if (have_newmv_in_inter_mode(mbmi->mode)) {
-      const int allow_hp = cm->cur_frame_force_integer_mv
+      const int allow_hp = cm->features.cur_frame_force_integer_mv
                                ? MV_SUBPEL_NONE
-                               : cm->allow_high_precision_mv;
+                               : cm->features.allow_high_precision_mv;
       if (new_mv) {
         for (int ref = 0; ref < 1 + has_second_ref(mbmi); ++ref) {
           const int_mv ref_mv = av1_get_ref_mv(x, ref);
@@ -1652,7 +1652,7 @@
     // Gather obmc and warped motion count to update the probability.
     if ((!cpi->sf.inter_sf.disable_obmc &&
          cpi->sf.inter_sf.prune_obmc_prob_thresh > 0) ||
-        (cm->allow_warped_motion &&
+        (cm->features.allow_warped_motion &&
          cpi->sf.inter_sf.prune_warped_prob_thresh > 0)) {
       const int inter_block = is_inter_block(mbmi);
       const int seg_ref_active =
@@ -1661,7 +1661,7 @@
         const MOTION_MODE motion_allowed =
             cm->switchable_motion_mode
                 ? motion_mode_allowed(xd->global_motion, xd, mbmi,
-                                      cm->allow_warped_motion)
+                                      cm->features.allow_warped_motion)
                 : SIMPLE_TRANSLATION;
 
         if (mbmi->ref_frame[1] != INTRA_FRAME) {
@@ -4781,8 +4781,8 @@
       if (cpi->sf.inter_sf.disable_sb_level_mv_cost_upd &&
           mi_col != tile_info->mi_col_start)
         break;
-      av1_fill_mv_costs(xd->tile_ctx, cm->cur_frame_force_integer_mv,
-                        cm->allow_high_precision_mv, x);
+      av1_fill_mv_costs(xd->tile_ctx, cm->features.cur_frame_force_integer_mv,
+                        cm->features.allow_high_precision_mv, x);
       break;
     default: assert(0);
   }
@@ -4850,7 +4850,7 @@
     PC_TREE *const pc_root = td->pc_root[mib_size_log2 - MIN_MIB_SIZE_LOG2];
     pc_root->index = 0;
 
-    xd->cur_frame_force_integer_mv = cm->cur_frame_force_integer_mv;
+    xd->cur_frame_force_integer_mv = cm->features.cur_frame_force_integer_mv;
     td->mb.cb_coef_buff = av1_get_cb_coeff_buffer(cpi, mi_row, mi_col);
     x->source_variance = UINT_MAX;
     x->simple_motion_pred_sse = UINT_MAX;
@@ -4941,7 +4941,7 @@
       tplist_count = av1_get_sb_rows_in_tile(cm, tile_data->tile_info);
       tile_data->allow_update_cdf = !cm->large_scale_tile;
       tile_data->allow_update_cdf =
-          tile_data->allow_update_cdf && !cm->disable_cdf_update;
+          tile_data->allow_update_cdf && !cm->features.disable_cdf_update;
       tile_data->tctx = *cm->fc;
     }
   }
@@ -5332,11 +5332,11 @@
 
     if (cm->global_motion[frame].wmtype == TRANSLATION) {
       cm->global_motion[frame].wmmat[0] =
-          convert_to_trans_prec(cm->allow_high_precision_mv,
+          convert_to_trans_prec(cm->features.allow_high_precision_mv,
                                 cm->global_motion[frame].wmmat[0]) *
           GM_TRANS_ONLY_DECODE_FACTOR;
       cm->global_motion[frame].wmmat[1] =
-          convert_to_trans_prec(cm->allow_high_precision_mv,
+          convert_to_trans_prec(cm->features.allow_high_precision_mv,
                                 cm->global_motion[frame].wmmat[1]) *
           GM_TRANS_ONLY_DECODE_FACTOR;
     }
@@ -5350,7 +5350,7 @@
     if (!av1_is_enough_erroradvantage(
             (double)best_warp_error / ref_frame_error,
             gm_get_params_cost(&cm->global_motion[frame], ref_params,
-                               cm->allow_high_precision_mv),
+                               cm->features.allow_high_precision_mv),
             cpi->sf.gm_sf.gm_erroradv_type)) {
       cm->global_motion[frame] = default_warp_params;
     }
@@ -5430,7 +5430,7 @@
 
   cpi->gmparams_cost[frame] =
       gm_get_params_cost(&cm->global_motion[frame], ref_params,
-                         cm->allow_high_precision_mv) +
+                         cm->features.allow_high_precision_mv) +
       cpi->gmtype_cost[cm->global_motion[frame].wmtype] -
       cpi->gmtype_cost[IDENTITY];
 }
@@ -5529,6 +5529,7 @@
   ThreadData *const td = &cpi->td;
   MACROBLOCK *const x = &td->mb;
   AV1_COMMON *const cm = &cpi->common;
+  FeatureFlags *const features = &cm->features;
   MACROBLOCKD *const xd = &x->e_mbd;
   RD_COUNTS *const rdc = &cpi->td.rd_counts;
   int i;
@@ -5558,17 +5559,17 @@
   cpi->intrabc_used = 0;
   // Need to disable intrabc when superres is selected
   if (av1_superres_scaled(cm)) {
-    cm->allow_intrabc = 0;
+    features->allow_intrabc = 0;
   }
 
-  cm->allow_intrabc &= (cpi->oxcf.enable_intrabc);
+  features->allow_intrabc &= (cpi->oxcf.enable_intrabc);
 
-  if (cm->allow_warped_motion &&
+  if (features->allow_warped_motion &&
       cpi->sf.inter_sf.prune_warped_prob_thresh > 0) {
     const FRAME_UPDATE_TYPE update_type = get_frame_update_type(&cpi->gf_group);
     if (cpi->warped_probs[update_type] <
         cpi->sf.inter_sf.prune_warped_prob_thresh)
-      cm->allow_warped_motion = 0;
+      features->allow_warped_motion = 0;
   }
 
   if (!is_stat_generation_stage(cpi) && av1_use_hash_me(cpi) &&
@@ -5638,8 +5639,8 @@
       cpi->optimize_seg_arr[i] = cpi->sf.rd_sf.optimize_coefficients;
     }
   }
-  cm->coded_lossless = is_coded_lossless(cm, xd);
-  cm->all_lossless = cm->coded_lossless && !av1_superres_scaled(cm);
+  features->coded_lossless = is_coded_lossless(cm, xd);
+  features->all_lossless = features->coded_lossless && !av1_superres_scaled(cm);
 
   // Fix delta q resolution for the moment
   cm->delta_q_info.delta_q_res = 0;
@@ -5683,7 +5684,7 @@
     cm->last_frame_seg_map = cm->prev_frame->seg_map;
   else
     cm->last_frame_seg_map = NULL;
-  if (cm->allow_intrabc || cm->coded_lossless) {
+  if (features->allow_intrabc || features->coded_lossless) {
     av1_set_default_ref_deltas(cm->lf.ref_deltas);
     av1_set_default_mode_deltas(cm->lf.mode_deltas);
   } else if (cm->prev_frame) {
@@ -5793,7 +5794,7 @@
 #if CONFIG_COLLECT_COMPONENT_TIMING
   start_timing(cpi, av1_setup_motion_field_time);
 #endif
-  if (cm->allow_ref_frame_mvs) av1_setup_motion_field(cm);
+  if (features->allow_ref_frame_mvs) av1_setup_motion_field(cm);
 #if CONFIG_COLLECT_COMPONENT_TIMING
   end_timing(cpi, av1_setup_motion_field_time);
 #endif
@@ -5818,8 +5819,12 @@
   }
 
   // If intrabc is allowed but never selected, reset the allow_intrabc flag.
-  if (cm->allow_intrabc && !cpi->intrabc_used) cm->allow_intrabc = 0;
-  if (cm->allow_intrabc) cm->delta_q_info.delta_lf_present_flag = 0;
+  if (features->allow_intrabc && !cpi->intrabc_used) {
+    features->allow_intrabc = 0;
+  }
+  if (features->allow_intrabc) {
+    cm->delta_q_info.delta_lf_present_flag = 0;
+  }
 
   if (cm->delta_q_info.delta_q_present_flag && cpi->deltaq_used == 0) {
     cm->delta_q_info.delta_q_present_flag = 0;
@@ -5873,7 +5878,7 @@
     }
   }
 
-  if (cm->allow_warped_motion &&
+  if (features->allow_warped_motion &&
       cpi->sf.inter_sf.prune_warped_prob_thresh > 0) {
     const FRAME_UPDATE_TYPE update_type = get_frame_update_type(&cpi->gf_group);
     int sum = 0;
@@ -5919,7 +5924,7 @@
   const int num_planes = av1_num_planes(cm);
   // Indicates whether or not to use a default reduced set for ext-tx
   // rather than the potential full set of 16 transforms
-  cm->reduced_tx_set_used = cpi->oxcf.reduced_tx_type_set;
+  cm->features.reduced_tx_set_used = cpi->oxcf.reduced_tx_type_set;
 
   // Make sure segment_id is no larger than last_active_segid.
   if (cm->seg.enabled && cm->seg.update_map) {
@@ -6219,7 +6224,7 @@
       mbmi->skip = 0;
 
     xd->cfl.store_y = 0;
-    if (av1_allow_palette(cm->allow_screen_content_tools, bsize)) {
+    if (av1_allow_palette(cm->features.allow_screen_content_tools, bsize)) {
       for (int plane = 0; plane < AOMMIN(2, num_planes); ++plane) {
         if (mbmi->palette_mode_info.palette_size[plane] > 0) {
           if (!dry_run) {
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index f212b13..1dce2ba 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -316,7 +316,7 @@
   txfm_param->tx_size = tx_size;
   txfm_param->lossless = xd->lossless[mbmi->segment_id];
   txfm_param->tx_set_type = av1_get_ext_tx_set_type(
-      tx_size, is_inter_block(mbmi), cm->reduced_tx_set_used);
+      tx_size, is_inter_block(mbmi), cm->features.reduced_tx_set_used);
 
   txfm_param->bd = xd->bd;
   txfm_param->is_hbd = is_cur_buf_hbd(xd);
@@ -383,7 +383,7 @@
   TX_TYPE tx_type = DCT_DCT;
   if (!is_blk_skip(x, plane, blk_row * bw + blk_col) && !mbmi->skip_mode) {
     tx_type = av1_get_tx_type(xd, pd->plane_type, blk_row, blk_col, tx_size,
-                              cm->reduced_tx_set_used);
+                              cm->features.reduced_tx_set_used);
     TxfmParam txfm_param;
     QUANT_PARAM quant_param;
     int use_trellis = (args->enable_optimize_b != NO_TRELLIS_OPT);
@@ -427,7 +427,7 @@
     *(args->skip) = 0;
     av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst,
                                 pd->dst.stride, p->eobs[block],
-                                cm->reduced_tx_set_used);
+                                cm->features.reduced_tx_set_used);
   }
 
   // TODO(debargha, jingning): Temporarily disable txk_type check for eob=0
@@ -715,7 +715,7 @@
     const ENTROPY_CONTEXT *a = &args->ta[blk_col];
     const ENTROPY_CONTEXT *l = &args->tl[blk_row];
     tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
-                              cm->reduced_tx_set_used);
+                              cm->features.reduced_tx_set_used);
     TxfmParam txfm_param;
     QUANT_PARAM quant_param;
     int use_trellis = args->enable_optimize_b != NO_TRELLIS_OPT;
@@ -762,7 +762,8 @@
 
   if (*eob) {
     av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, dst,
-                                dst_stride, *eob, cm->reduced_tx_set_used);
+                                dst_stride, *eob,
+                                cm->features.reduced_tx_set_used);
   }
 
   // TODO(jingning): Temporarily disable txk_type check for eob=0 case.
diff --git a/av1/encoder/encodemv.c b/av1/encoder/encodemv.c
index d764ac1..e66a733 100644
--- a/av1/encoder/encodemv.c
+++ b/av1/encoder/encodemv.c
@@ -179,7 +179,7 @@
   const MV_JOINT_TYPE j = av1_get_mv_joint(&diff);
   // If the mv_diff is zero, then we should have used near or nearest instead.
   assert(j != MV_JOINT_ZERO);
-  if (cpi->common.cur_frame_force_integer_mv) {
+  if (cpi->common.features.cur_frame_force_integer_mv) {
     usehp = MV_SUBPEL_NONE;
   }
   aom_write_symbol(w, j, mvctx->joints_cdf, MV_JOINTS);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index b64b085..5acc8e8 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -603,7 +603,7 @@
   // other inter-frames the encoder currently uses only two contexts;
   // context 1 for ALTREF frames and context 0 for the others.
 
-  if (frame_is_intra_only(cm) || cm->error_resilient_mode ||
+  if (frame_is_intra_only(cm) || cm->features.error_resilient_mode ||
       cpi->ext_use_primary_ref_none) {
     av1_setup_past_independence(cm);
   }
@@ -3933,17 +3933,18 @@
   }
 }
 
-static void set_screen_content_options(AV1_COMP *cpi) {
-  AV1_COMMON *cm = &cpi->common;
+static void set_screen_content_options(const AV1_COMP *const cpi,
+                                       FeatureFlags *const features) {
+  const AV1_COMMON *const cm = &cpi->common;
 
   if (cm->seq_params.force_screen_content_tools != 2) {
-    cm->allow_screen_content_tools = cm->allow_intrabc =
+    features->allow_screen_content_tools = features->allow_intrabc =
         cm->seq_params.force_screen_content_tools;
     return;
   }
 
   if (cpi->oxcf.content == AOM_CONTENT_SCREEN) {
-    cm->allow_screen_content_tools = cm->allow_intrabc = 1;
+    features->allow_screen_content_tools = features->allow_intrabc = 1;
     return;
   }
 
@@ -3990,24 +3991,25 @@
   }
 
   // The threshold values are selected experimentally.
-  cm->allow_screen_content_tools =
+  features->allow_screen_content_tools =
       counts_1 * blk_h * blk_w * 10 > width * height;
   // IntraBC would force loop filters off, so we use more strict rules that also
   // requires that the block has high variance.
-  cm->allow_intrabc = cm->allow_screen_content_tools &&
-                      counts_2 * blk_h * blk_w * 12 > width * height;
+  features->allow_intrabc = features->allow_screen_content_tools &&
+                            counts_2 * blk_h * blk_w * 12 > width * height;
 }
 
 static void set_size_independent_vars(AV1_COMP *cpi) {
   int i;
-  AV1_COMMON *cm = &cpi->common;
+  AV1_COMMON *const cm = &cpi->common;
+  FeatureFlags *const features = &cm->features;
   for (i = LAST_FRAME; i <= ALTREF_FRAME; ++i) {
     cm->global_motion[i] = default_warp_params;
   }
   cpi->global_motion_search_done = 0;
 
-  if (frame_is_intra_only(cm)) set_screen_content_options(cpi);
-  cpi->is_screen_content_type = (cm->allow_screen_content_tools != 0);
+  if (frame_is_intra_only(cm)) set_screen_content_options(cpi, features);
+  cpi->is_screen_content_type = (features->allow_screen_content_tools != 0);
 
   av1_set_speed_features_framesize_independent(cpi, cpi->speed);
   av1_set_rd_speed_thresholds(cpi);
@@ -4314,7 +4316,8 @@
     // There has been a change in the encoded frame size
     av1_set_size_literal(cpi, width, height);
     // Recalculate 'all_lossless' in case super-resolution was (un)selected.
-    cm->all_lossless = cm->coded_lossless && !av1_superres_scaled(cm);
+    cm->features.all_lossless =
+        cm->features.coded_lossless && !av1_superres_scaled(cm);
   }
   set_mv_search_params(cpi);
 
@@ -4510,7 +4513,7 @@
     case SUPERRES_RANDOM: new_denom = lcg_rand16(&seed) % 9 + 8; break;
     case SUPERRES_QTHRESH: {
       // Do not use superres when screen content tools are used.
-      if (cpi->common.allow_screen_content_tools) break;
+      if (cpi->common.features.allow_screen_content_tools) break;
       if (oxcf->rc_mode == AOM_VBR || oxcf->rc_mode == AOM_CQ)
         av1_set_target_rate(cpi, cpi->oxcf.width, cpi->oxcf.height);
 
@@ -4532,7 +4535,7 @@
     }
     case SUPERRES_AUTO: {
       // Do not use superres when screen content tools are used.
-      if (cpi->common.allow_screen_content_tools) break;
+      if (cpi->common.features.allow_screen_content_tools) break;
       if (oxcf->rc_mode == AOM_VBR || oxcf->rc_mode == AOM_CQ)
         av1_set_target_rate(cpi, cpi->oxcf.width, cpi->oxcf.height);
 
@@ -4691,7 +4694,7 @@
 
   assert(cpi->oxcf.enable_superres);
   assert(!is_lossless_requested(&cpi->oxcf));
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   av1_superres_upscale(cm, NULL);
 
@@ -4782,13 +4785,15 @@
   MACROBLOCKD *xd = &cpi->td.mb.e_mbd;
 
   assert(IMPLIES(is_lossless_requested(&cpi->oxcf),
-                 cm->coded_lossless && cm->all_lossless));
+                 cm->features.coded_lossless && cm->features.all_lossless));
 
-  const int use_loopfilter = !cm->coded_lossless && !cm->large_scale_tile;
-  const int use_cdef = cm->seq_params.enable_cdef && !cm->coded_lossless &&
-                       !cm->large_scale_tile;
+  const int use_loopfilter =
+      !cm->features.coded_lossless && !cm->large_scale_tile;
+  const int use_cdef = cm->seq_params.enable_cdef &&
+                       !cm->features.coded_lossless && !cm->large_scale_tile;
   const int use_restoration = cm->seq_params.enable_restoration &&
-                              !cm->all_lossless && !cm->large_scale_tile;
+                              !cm->features.all_lossless &&
+                              !cm->large_scale_tile;
 
   struct loopfilter *lf = &cm->lf;
 
@@ -5169,6 +5174,7 @@
     const int is_screen_content_type_orig_decision, const int pass,
     int *projected_size_pass, PSNR_STATS *psnr) {
   AV1_COMMON *const cm = &cpi->common;
+  FeatureFlags *const features = &cm->features;
   projected_size_pass[pass] = cpi->rc.projected_frame_size;
 #if CONFIG_AV1_HIGHBITDEPTH
   const uint32_t in_bit_depth = cpi->oxcf.input_bit_depth;
@@ -5184,13 +5190,14 @@
   const int is_sc_encoding_much_better = psnr_diff > STRICT_PSNR_DIFF_THRESH;
   if (is_sc_encoding_much_better) {
     // Use screen content tools, if we get coding gain.
-    cm->allow_screen_content_tools = 1;
-    cm->allow_intrabc = cpi->intrabc_used;
+    features->allow_screen_content_tools = 1;
+    features->allow_intrabc = cpi->intrabc_used;
     cpi->is_screen_content_type = 1;
   } else {
     // Use original screen content decision.
-    cm->allow_screen_content_tools = allow_screen_content_tools_orig_decision;
-    cm->allow_intrabc = allow_intrabc_orig_decision;
+    features->allow_screen_content_tools =
+        allow_screen_content_tools_orig_decision;
+    features->allow_intrabc = allow_intrabc_orig_decision;
     cpi->is_screen_content_type = is_screen_content_type_orig_decision;
   }
 }
@@ -5203,8 +5210,8 @@
   if (pass == 0) {
     // In the first pass, encode without screen content tools.
     // Use a high q, and a fixed block size for fast encoding.
-    cm->allow_screen_content_tools = 0;
-    cm->allow_intrabc = 0;
+    cm->features.allow_screen_content_tools = 0;
+    cm->features.allow_intrabc = 0;
     cpi->is_screen_content_type = 0;
     cpi->sf.part_sf.partition_search_type = FIXED_PARTITION;
     cpi->sf.part_sf.always_this_block_size = BLOCK_32X32;
@@ -5213,7 +5220,7 @@
   assert(pass == 1);
   // In the second pass, encode with screen content tools.
   // Use a high q, and a fixed block size for fast encoding.
-  cm->allow_screen_content_tools = 1;
+  cm->features.allow_screen_content_tools = 1;
   // TODO(chengchen): turn intrabc on could lead to data race issue.
   // cm->allow_intrabc = 1;
   cpi->is_screen_content_type = 1;
@@ -5223,8 +5230,8 @@
 }
 
 // Determines whether to use screen content tools for the key frame group.
-// This function modifies "cm->allow_screen_content_tools",
-// "cm->allow_intrabc" and "cpi->is_screen_content_type".
+// This function modifies "cm->features.allow_screen_content_tools",
+// "cm->features.allow_intrabc" and "cpi->is_screen_content_type".
 static void determine_sc_tools_with_encoding(AV1_COMP *cpi, const int q_orig) {
   if (!is_stat_consumption_stage_twopass(cpi)) return;
 
@@ -5234,8 +5241,8 @@
   PSNR_STATS psnr[3];
   const int is_key_frame = cm->current_frame.frame_type == KEY_FRAME;
   const int allow_screen_content_tools_orig_decision =
-      cm->allow_screen_content_tools;
-  const int allow_intrabc_orig_decision = cm->allow_intrabc;
+      cm->features.allow_screen_content_tools;
+  const int allow_intrabc_orig_decision = cm->features.allow_intrabc;
   const int is_screen_content_type_orig_decision = cpi->is_screen_content_type;
   // Turn off the encoding trial for forward key frame and superres.
   if (cpi->sf.rt_sf.use_nonrd_pick_mode || cpi->oxcf.fwd_kf_enabled ||
@@ -5486,10 +5493,11 @@
 
       // If the precision has changed during different iteration of the loop,
       // then we need to reset the global motion vectors
-      if (loop_count > 0 && cm->allow_high_precision_mv != last_loop_allow_hp) {
+      if (loop_count > 0 &&
+          cm->features.allow_high_precision_mv != last_loop_allow_hp) {
         cpi->global_motion_search_done = 0;
       }
-      last_loop_allow_hp = cm->allow_high_precision_mv;
+      last_loop_allow_hp = cm->features.allow_high_precision_mv;
     }
 
     // transform / motion compensation build reconstruction frame
@@ -5631,7 +5639,7 @@
   // off.
 
   // Pick the loop filter level for the frame.
-  if (!cm->allow_intrabc) {
+  if (!cm->features.allow_intrabc) {
     loopfilter_frame(cpi, cm);
   } else {
     cm->lf.filter_level[0] = 0;
@@ -6174,6 +6182,7 @@
   CurrentFrame *const current_frame = &cm->current_frame;
   const AV1EncoderConfig *const oxcf = &cpi->oxcf;
   struct segmentation *const seg = &cm->seg;
+  FeatureFlags *const features = &cm->features;
 
 #if CONFIG_COLLECT_COMPONENT_TIMING
   start_timing(cpi, encode_frame_to_data_rate_time);
@@ -6185,13 +6194,13 @@
   cm->large_scale_tile = cpi->oxcf.large_scale_tile;
   cm->single_tile_decoding = cpi->oxcf.single_tile_decoding;
 
-  cm->allow_ref_frame_mvs &= frame_might_allow_ref_frame_mvs(cm);
-  // cm->allow_ref_frame_mvs needs to be written into the frame header while
-  // cm->large_scale_tile is 1, therefore, "cm->large_scale_tile=1" case is
-  // separated from frame_might_allow_ref_frame_mvs().
-  cm->allow_ref_frame_mvs &= !cm->large_scale_tile;
+  features->allow_ref_frame_mvs &= frame_might_allow_ref_frame_mvs(cm);
+  // features->allow_ref_frame_mvs needs to be written into the frame header
+  // while cm->large_scale_tile is 1, therefore, "cm->large_scale_tile=1" case
+  // is separated from frame_might_allow_ref_frame_mvs().
+  features->allow_ref_frame_mvs &= !cm->large_scale_tile;
 
-  cm->allow_warped_motion =
+  features->allow_warped_motion =
       cpi->oxcf.allow_warped_motion && frame_might_allow_warped_motion(cm);
 
   cpi->last_frame_type = current_frame->frame_type;
@@ -6238,21 +6247,22 @@
 
   // Work out whether to force_integer_mv this frame
   if (!is_stat_generation_stage(cpi) &&
-      cpi->common.allow_screen_content_tools && !frame_is_intra_only(cm)) {
+      cpi->common.features.allow_screen_content_tools &&
+      !frame_is_intra_only(cm)) {
     if (cpi->common.seq_params.force_integer_mv == 2) {
       // Adaptive mode: see what previous frame encoded did
       if (cpi->unscaled_last_source != NULL) {
-        cm->cur_frame_force_integer_mv =
+        features->cur_frame_force_integer_mv =
             is_integer_mv(cpi, cpi->source, cpi->unscaled_last_source);
       } else {
-        cpi->common.cur_frame_force_integer_mv = 0;
+        cpi->common.features.cur_frame_force_integer_mv = 0;
       }
     } else {
-      cpi->common.cur_frame_force_integer_mv =
+      cpi->common.features.cur_frame_force_integer_mv =
           cpi->common.seq_params.force_integer_mv;
     }
   } else {
-    cpi->common.cur_frame_force_integer_mv = 0;
+    cpi->common.features.cur_frame_force_integer_mv = 0;
   }
 
 #if CONFIG_DEBUG
@@ -6343,10 +6353,10 @@
 
   switch (cpi->oxcf.cdf_update_mode) {
     case 0:  // No CDF update for any frames(4~6% compression loss).
-      cm->disable_cdf_update = 1;
+      features->disable_cdf_update = 1;
       break;
     case 1:  // Enable CDF update for all frames.
-      cm->disable_cdf_update = 0;
+      features->disable_cdf_update = 0;
       break;
     case 2:
       // Strategically determine at which frames to do CDF update.
@@ -6354,7 +6364,7 @@
       // compression loss).
       // TODO(huisu@google.com): design schemes for various trade-offs between
       // compression quality and decoding speed.
-      cm->disable_cdf_update =
+      features->disable_cdf_update =
           (frame_is_intra_only(cm) || !cm->show_frame) ? 0 : 1;
       break;
   }
@@ -6488,7 +6498,7 @@
   cpi->unscaled_last_source = frame_input->last_source;
 
   current_frame->refresh_frame_flags = frame_params->refresh_frame_flags;
-  cm->error_resilient_mode = frame_params->error_resilient_mode;
+  cm->features.error_resilient_mode = frame_params->error_resilient_mode;
   cm->primary_ref_frame = frame_params->primary_ref_frame;
   cm->current_frame.frame_type = frame_params->frame_type;
   cm->show_frame = frame_params->show_frame;
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 2a2b0a0..36ac9dd 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1318,7 +1318,7 @@
 
 // TODO(huisu@google.com, youzhou@microsoft.com): enable hash-me for HBD.
 static INLINE int av1_use_hash_me(const AV1_COMP *const cpi) {
-  return (cpi->common.allow_screen_content_tools &&
+  return (cpi->common.features.allow_screen_content_tools &&
           frame_is_intra_only(&cpi->common));
 }
 
@@ -1486,7 +1486,7 @@
 // frame. An exception can be made for a forward keyframe since it has no
 // previous dependencies.
 static INLINE int encode_show_existing_frame(const AV1_COMMON *cm) {
-  return cm->show_existing_frame && (!cm->error_resilient_mode ||
+  return cm->show_existing_frame && (!cm->features.error_resilient_mode ||
                                      cm->current_frame.frame_type == KEY_FRAME);
 }
 
diff --git a/av1/encoder/encodetxb.c b/av1/encoder/encodetxb.c
index 2193112..0b539b0 100644
--- a/av1/encoder/encodetxb.c
+++ b/av1/encoder/encodetxb.c
@@ -519,8 +519,9 @@
   if (eob == 0) return;
 
   const PLANE_TYPE plane_type = get_plane_type(plane);
-  const TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col,
-                                          tx_size, cm->reduced_tx_set_used);
+  const TX_TYPE tx_type =
+      av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
+                      cm->features.reduced_tx_set_used);
   // Only y plane's tx_type is transmitted
   if (plane == 0) {
     av1_write_tx_type(cm, xd, tx_type, tx_size, w);
@@ -1891,8 +1892,8 @@
                          levels, iqmatrix);
   }
 
-  const int tx_type_cost =
-      get_tx_type_cost(x, xd, plane, tx_size, tx_type, cm->reduced_tx_set_used);
+  const int tx_type_cost = get_tx_type_cost(x, xd, plane, tx_size, tx_type,
+                                            cm->features.reduced_tx_set_used);
   if (eob == 0)
     accu_rate += skip_cost;
   else
@@ -1912,7 +1913,7 @@
                      int blk_row, int blk_col, int block, TX_SIZE tx_size,
                      TXB_CTX *txb_ctx, int fast_mode, int *rate_cost) {
   const AV1_COMMON *cm = &cpi->common;
-  const int reduced_tx_set_used = cm->reduced_tx_set_used;
+  const int reduced_tx_set_used = cm->features.reduced_tx_set_used;
   MACROBLOCKD *const xd = &x->e_mbd;
   const PLANE_TYPE plane_type = get_plane_type(plane);
   const TX_SIZE txs_ctx = get_txsize_entropy_ctx(tx_size);
@@ -2009,7 +2010,7 @@
                                  uint8_t allow_update_cdf) {
   MB_MODE_INFO *mbmi = xd->mi[0];
   int is_inter = is_inter_block(mbmi);
-  const int reduced_tx_set_used = cm->reduced_tx_set_used;
+  const int reduced_tx_set_used = cm->features.reduced_tx_set_used;
   FRAME_CONTEXT *fc = xd->tile_ctx;
 #if !CONFIG_ENTROPY_STATS
   (void)counts;
@@ -2088,8 +2089,9 @@
   const int block_offset = BLOCK_OFFSET(block);
   tran_low_t *qcoeff = p->qcoeff + block_offset;
   const PLANE_TYPE plane_type = pd->plane_type;
-  const TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col,
-                                          tx_size, cm->reduced_tx_set_used);
+  const TX_TYPE tx_type =
+      av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
+                      cm->features.reduced_tx_set_used);
   const SCAN_ORDER *const scan_order = get_scan(tx_size, tx_type);
   tran_low_t *tcoeff;
   assert(args->dry_run != DRY_RUN_COSTCOEFFS);
diff --git a/av1/encoder/intra_mode_search.c b/av1/encoder/intra_mode_search.c
index c4bc98a..0b5fb3e 100644
--- a/av1/encoder/intra_mode_search.c
+++ b/av1/encoder/intra_mode_search.c
@@ -317,8 +317,8 @@
   // Can only activate one mode.
   assert(((mbmi->mode != DC_PRED) + use_palette + use_intrabc +
           use_filter_intra) <= 1);
-  const int try_palette =
-      av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type);
+  const int try_palette = av1_allow_palette(
+      cpi->common.features.allow_screen_content_tools, mbmi->sb_type);
   if (try_palette && mbmi->mode == DC_PRED) {
     const MACROBLOCKD *xd = &x->e_mbd;
     const int bsize_ctx = av1_get_palette_bsize_ctx(bsize);
@@ -372,8 +372,8 @@
   // Can only activate one mode.
   assert(((mode != UV_DC_PRED) + use_palette + mbmi->use_intrabc) <= 1);
 
-  const int try_palette =
-      av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type);
+  const int try_palette = av1_allow_palette(
+      cpi->common.features.allow_screen_content_tools, mbmi->sb_type);
   if (try_palette && mode == UV_DC_PRED) {
     const PALETTE_MODE_INFO *pmi = &mbmi->palette_mode_info;
     total_rate +=
@@ -811,7 +811,8 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
   assert(!is_inter_block(mbmi));
-  assert(av1_allow_palette(cpi->common.allow_screen_content_tools, bsize));
+  assert(av1_allow_palette(cpi->common.features.allow_screen_content_tools,
+                           bsize));
 
   const int src_stride = x->plane[0].src.stride;
   const uint8_t *const src = x->plane[0].src.buf;
@@ -1007,8 +1008,8 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
   assert(!is_inter_block(mbmi));
-  assert(
-      av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type));
+  assert(av1_allow_palette(cpi->common.features.allow_screen_content_tools,
+                           mbmi->sb_type));
   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
   const BLOCK_SIZE bsize = mbmi->sb_type;
   const SequenceHeader *const seq_params = &cpi->common.seq_params;
@@ -1503,7 +1504,8 @@
 
   const int try_palette =
       cpi->oxcf.enable_palette &&
-      av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type);
+      av1_allow_palette(cpi->common.features.allow_screen_content_tools,
+                        mbmi->sb_type);
   if (try_palette) {
     uint8_t *best_palette_color_map = x->palette_buffer->best_palette_color_map;
     rd_pick_palette_intra_sbuv(
@@ -1841,7 +1843,8 @@
     PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
     const int try_palette =
         cpi->oxcf.enable_palette &&
-        av1_allow_palette(cm->allow_screen_content_tools, mbmi->sb_type);
+        av1_allow_palette(cm->features.allow_screen_content_tools,
+                          mbmi->sb_type);
     const TX_SIZE uv_tx = av1_get_tx_size(AOM_PLANE_U, xd);
     if (intra_search_state->rate_uv_intra == INT_MAX) {
       const int rate_y =
@@ -1947,7 +1950,8 @@
   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
   const int try_palette =
       cpi->oxcf.enable_palette &&
-      av1_allow_palette(cpi->common.allow_screen_content_tools, mbmi->sb_type);
+      av1_allow_palette(cpi->common.features.allow_screen_content_tools,
+                        mbmi->sb_type);
   uint8_t *best_palette_color_map =
       try_palette ? x->palette_buffer->best_palette_color_map : NULL;
   const MB_MODE_INFO *above_mi = xd->above_mbmi;
diff --git a/av1/encoder/mcomp.c b/av1/encoder/mcomp.c
index 3d587b0..35a0463 100644
--- a/av1/encoder/mcomp.c
+++ b/av1/encoder/mcomp.c
@@ -54,7 +54,7 @@
     int mask_stride, int invert_mask, int do_reset_fractional_mv) {
   const AV1_COMMON *cm = &cpi->common;
   // High level params
-  ms_params->allow_hp = cm->allow_high_precision_mv;
+  ms_params->allow_hp = cm->features.allow_high_precision_mv;
   ms_params->forced_stop = cpi->sf.mv_sf.subpel_force_stop;
   ms_params->iters_per_step = cpi->sf.mv_sf.subpel_iters_per_step;
   ms_params->cost_list = cond_cost_list_const(cpi, cost_list);
@@ -2888,7 +2888,7 @@
   unsigned int bestmse;
   SubpelMvLimits mv_limits;
 
-  const int start = cm->allow_high_precision_mv ? 0 : 4;
+  const int start = cm->features.allow_high_precision_mv ? 0 : 4;
   int ite;
 
   av1_set_subpel_mv_search_range(&mv_limits, &x->mv_limits, &ref_mv.as_mv);
diff --git a/av1/encoder/motion_search_facade.c b/av1/encoder/motion_search_facade.c
index d163c02..43a7cf8 100644
--- a/av1/encoder/motion_search_facade.c
+++ b/av1/encoder/motion_search_facade.c
@@ -192,12 +192,12 @@
     }
   }
 
-  if (cpi->common.cur_frame_force_integer_mv) {
+  if (cpi->common.features.cur_frame_force_integer_mv) {
     convert_fullmv_to_mv(&x->best_mv);
   }
 
   const int use_fractional_mv =
-      bestsme < INT_MAX && cpi->common.cur_frame_force_integer_mv == 0;
+      bestsme < INT_MAX && cpi->common.features.cur_frame_force_integer_mv == 0;
   if (use_fractional_mv) {
     const uint8_t *second_pred = NULL;
     const uint8_t *mask = NULL;
@@ -402,10 +402,11 @@
     // Do sub-pixel compound motion search on the current reference frame.
     if (id) xd->plane[plane].pre[0] = ref_yv12[id];
 
-    if (cpi->common.cur_frame_force_integer_mv) {
+    if (cpi->common.features.cur_frame_force_integer_mv) {
       convert_fullmv_to_mv(best_int_mv);
     }
-    if (bestsme < INT_MAX && cpi->common.cur_frame_force_integer_mv == 0) {
+    if (bestsme < INT_MAX &&
+        cpi->common.features.cur_frame_force_integer_mv == 0) {
       int dis; /* TODO: use dis in distortion calculation later. */
       unsigned int sse;
       SUBPEL_MOTION_SEARCH_PARAMS ms_params;
@@ -518,11 +519,11 @@
     }
   }
 
-  if (cpi->common.cur_frame_force_integer_mv) {
+  if (cpi->common.features.cur_frame_force_integer_mv) {
     convert_fullmv_to_mv(best_int_mv);
   }
   const int use_fractional_mv =
-      bestsme < INT_MAX && cpi->common.cur_frame_force_integer_mv == 0;
+      bestsme < INT_MAX && cpi->common.features.cur_frame_force_integer_mv == 0;
   if (use_fractional_mv) {
     int dis; /* TODO: use dis in distortion calculation later. */
     unsigned int sse;
@@ -715,7 +716,8 @@
   x->mv_limits = tmp_mv_limits;
 
   const int use_subpel_search =
-      var < INT_MAX && !cpi->common.cur_frame_force_integer_mv && use_subpixel;
+      var < INT_MAX && !cpi->common.features.cur_frame_force_integer_mv &&
+      use_subpixel;
   if (scaled_ref_frame) {
     xd->plane[AOM_PLANE_Y].pre[ref_idx] = backup_yv12;
   }
diff --git a/av1/encoder/mv_prec.c b/av1/encoder/mv_prec.c
index d206a41..601d958 100644
--- a/av1/encoder/mv_prec.c
+++ b/av1/encoder/mv_prec.c
@@ -65,7 +65,7 @@
   const int int_part = offset >> 3;         // int mv data
   const int frac_part = (offset >> 1) & 3;  // fractional mv data
   const int high_part = offset & 1;         // high precision mv data
-  const int use_hp = cpi->common.allow_high_precision_mv;
+  const int use_hp = cpi->common.features.allow_high_precision_mv;
   int r_idx = 0;
 
   const MACROBLOCK *const x = &cpi->td.mb;
@@ -128,7 +128,7 @@
   FRAME_CONTEXT *ec_ctx = xd->tile_ctx;
   nmv_context *nmvc = &ec_ctx->nmvc;
   aom_cdf_prob *joint_cdf = nmvc->joints_cdf;
-  const int use_hp = cpi->common.allow_high_precision_mv;
+  const int use_hp = cpi->common.features.allow_high_precision_mv;
 
   const MV diff = { cur_mv->row - ref_mv->row, cur_mv->col - ref_mv->col };
   const int mv_joint = av1_get_mv_joint(&diff);
@@ -421,5 +421,5 @@
 #endif  // !CONFIG_REALTIME_ONLY
 
   av1_set_high_precision_mv(cpi, use_hp,
-                            cpi->common.cur_frame_force_integer_mv);
+                            cpi->common.features.cur_frame_force_integer_mv);
 }
diff --git a/av1/encoder/mv_prec.h b/av1/encoder/mv_prec.h
index f2112b7..8df8b96 100644
--- a/av1/encoder/mv_prec.h
+++ b/av1/encoder/mv_prec.h
@@ -33,7 +33,7 @@
     AV1_COMP *cpi, int allow_high_precision_mv,
     int cur_frame_force_integer_mv) {
   MACROBLOCK *const x = &cpi->td.mb;
-  const int copy_hp = cpi->common.allow_high_precision_mv =
+  const int copy_hp = cpi->common.features.allow_high_precision_mv =
       allow_high_precision_mv && !cur_frame_force_integer_mv;
   x->nmvcost[0] = &x->nmv_costs[0][MV_MAX];
   x->nmvcost[1] = &x->nmv_costs[1][MV_MAX];
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 8e77e2d..bcfd8d7 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -283,9 +283,9 @@
     // TODO(Ravi): Populate mbmi_ext->ref_mv_stack[ref_frame][4] and
     // mbmi_ext->weight[ref_frame][4] inside av1_find_mv_refs.
     av1_copy_usable_ref_mv_stack_and_weight(xd, mbmi_ext, ref_frame);
-    av1_find_best_ref_mvs_from_stack(cm->allow_high_precision_mv, mbmi_ext,
-                                     ref_frame, &frame_mv[NEARESTMV][ref_frame],
-                                     &frame_mv[NEARMV][ref_frame], 0);
+    av1_find_best_ref_mvs_from_stack(
+        cm->features.allow_high_precision_mv, mbmi_ext, ref_frame,
+        &frame_mv[NEARESTMV][ref_frame], &frame_mv[NEARMV][ref_frame], 0);
     // Early exit for non-LAST frame if force_skip_low_temp_var is set.
     if (!av1_is_scaled(sf) && bsize >= BLOCK_8X8 &&
         !(force_skip_low_temp_var && ref_frame != LAST_FRAME)) {
diff --git a/av1/encoder/pickrst.c b/av1/encoder/pickrst.c
index 8e0bb3f..50d70a7 100644
--- a/av1/encoder/pickrst.c
+++ b/av1/encoder/pickrst.c
@@ -1701,7 +1701,7 @@
 void av1_pick_filter_restoration(const YV12_BUFFER_CONFIG *src, AV1_COMP *cpi) {
   AV1_COMMON *const cm = &cpi->common;
   const int num_planes = av1_num_planes(cm);
-  assert(!cm->all_lossless);
+  assert(!cm->features.all_lossless);
 
   int ntiles[2];
   for (int is_uv = 0; is_uv < 2; ++is_uv)
diff --git a/av1/encoder/rd.c b/av1/encoder/rd.c
index 5b4b730..b7b0cd9 100644
--- a/av1/encoder/rd.c
+++ b/av1/encoder/rd.c
@@ -598,11 +598,12 @@
   if ((!cpi->sf.rt_sf.use_nonrd_pick_mode &&
        cpi->oxcf.mv_cost_upd_freq != COST_UPD_OFF) ||
       frame_is_intra_only(cm) || (cm->current_frame.frame_number & 0x07) == 1)
-    av1_fill_mv_costs(cm->fc, cm->cur_frame_force_integer_mv,
-                      cm->allow_high_precision_mv, x);
+    av1_fill_mv_costs(cm->fc, cm->features.cur_frame_force_integer_mv,
+                      cm->features.allow_high_precision_mv, x);
 
   if (!cpi->sf.rt_sf.use_nonrd_pick_mode && frame_is_intra_only(cm) &&
-      cm->allow_screen_content_tools && !is_stat_generation_stage(cpi)) {
+      cm->features.allow_screen_content_tools &&
+      !is_stat_generation_stage(cpi)) {
     int *dvcost[2] = { &cpi->dv_cost[0][MV_MAX], &cpi->dv_cost[1][MV_MAX] };
     av1_build_nmv_cost_table(cpi->dv_joint_cost, dvcost, &cm->fc->ndvc,
                              MV_SUBPEL_NONE);
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 116f56a..c8c0f6d 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -1031,8 +1031,8 @@
                                      const MACROBLOCK *x) {
   const MACROBLOCKD *const xd = &x->e_mbd;
   *out_mv = in_mv;
-  lower_mv_precision(&out_mv->as_mv, cm->allow_high_precision_mv,
-                     cm->cur_frame_force_integer_mv);
+  lower_mv_precision(&out_mv->as_mv, cm->features.allow_high_precision_mv,
+                     cm->features.cur_frame_force_integer_mv);
   clamp_mv2(&out_mv->as_mv, xd);
   return av1_is_fullmv_in_range(&x->mv_limits,
                                 get_fullmv_from_mv(&out_mv->as_mv));
@@ -1252,8 +1252,8 @@
   mbmi->num_proj_ref = 1;  // assume num_proj_ref >=1
   MOTION_MODE last_motion_mode_allowed = SIMPLE_TRANSLATION;
   if (cm->switchable_motion_mode) {
-    last_motion_mode_allowed = motion_mode_allowed(xd->global_motion, xd, mbmi,
-                                                   cm->allow_warped_motion);
+    last_motion_mode_allowed = motion_mode_allowed(
+        xd->global_motion, xd, mbmi, cm->features.allow_warped_motion);
   }
 
   if (last_motion_mode_allowed == WARPED_CAUSAL) {
@@ -4791,7 +4791,8 @@
   // Only try palette mode when the best mode so far is an intra mode.
   const int try_palette =
       cpi->oxcf.enable_palette &&
-      av1_allow_palette(cm->allow_screen_content_tools, mbmi->sb_type) &&
+      av1_allow_palette(cm->features.allow_screen_content_tools,
+                        mbmi->sb_type) &&
       !is_inter_mode(search_state.best_mbmode.mode);
   PALETTE_MODE_INFO *const pmi = &mbmi->palette_mode_info;
   RD_STATS this_rd_cost;
@@ -4951,8 +4952,8 @@
   mbmi->ref_frame[1] = NONE_FRAME;
   mbmi->mv[0].as_int =
       gm_get_motion_vector(&cm->global_motion[mbmi->ref_frame[0]],
-                           cm->allow_high_precision_mv, bsize, mi_col, mi_row,
-                           cm->cur_frame_force_integer_mv)
+                           cm->features.allow_high_precision_mv, bsize, mi_col,
+                           mi_row, cm->features.cur_frame_force_integer_mv)
           .as_int;
   mbmi->tx_size = max_txsize_lookup[bsize];
   x->force_skip = 1;
diff --git a/av1/encoder/rdopt_utils.h b/av1/encoder/rdopt_utils.h
index 341ba0d..9c4f5899 100644
--- a/av1/encoder/rdopt_utils.h
+++ b/av1/encoder/rdopt_utils.h
@@ -365,7 +365,7 @@
 
 static TX_MODE select_tx_mode(
     const AV1_COMP *cpi, const TX_SIZE_SEARCH_METHOD tx_size_search_method) {
-  if (cpi->common.coded_lossless) return ONLY_4X4;
+  if (cpi->common.features.coded_lossless) return ONLY_4X4;
   if (tx_size_search_method == USE_LARGESTALL) {
     return TX_MODE_LARGEST;
   } else {
diff --git a/av1/encoder/segmentation.c b/av1/encoder/segmentation.c
index 9c1ede1..43a2803 100644
--- a/av1/encoder/segmentation.c
+++ b/av1/encoder/segmentation.c
@@ -231,7 +231,7 @@
 
   // Now choose which coding method to use.
   if (t_pred_cost < no_pred_cost) {
-    assert(!cm->error_resilient_mode);
+    assert(!cm->features.error_resilient_mode);
     seg->temporal_update = 1;
   } else {
     seg->temporal_update = 0;
diff --git a/av1/encoder/speed_features.c b/av1/encoder/speed_features.c
index 2c4aa6a..4fe5cb0 100644
--- a/av1/encoder/speed_features.c
+++ b/av1/encoder/speed_features.c
@@ -270,6 +270,8 @@
   const int boosted = frame_is_boosted(cpi);
   const int is_boosted_arf2_bwd_type =
       boosted || gf_group->update_type[gf_group->index] == INTNL_ARF_UPDATE;
+  const int allow_screen_content_tools =
+      cm->features.allow_screen_content_tools;
   if (!cpi->oxcf.large_scale_tile) {
     sf->hl_sf.high_precision_mv_usage = LAST_MV_DATA;
   }
@@ -294,7 +296,7 @@
   sf->inter_sf.prune_mode_search_simple_translation = 1;
   sf->inter_sf.prune_motion_mode_level = 1;
   sf->inter_sf.prune_ref_frame_for_rect_partitions =
-      (boosted || (cm->allow_screen_content_tools))
+      (boosted || (allow_screen_content_tools))
           ? 0
           : (is_boosted_arf2_bwd_type ? 1 : 2);
   sf->inter_sf.prune_wedge_pred_diff_based = 1;
@@ -331,8 +333,7 @@
     // 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 =
-        cm->allow_screen_content_tools ? 1 : 2;
+    sf->part_sf.simple_motion_search_split = allow_screen_content_tools ? 1 : 2;
 
     sf->mv_sf.use_accurate_subpel_search = USE_4_TAPS;
     sf->mv_sf.exhaustive_searches_thresh <<= 1;
@@ -344,7 +345,7 @@
     sf->inter_sf.prune_comp_type_by_model_rd = boosted ? 0 : 1;
     sf->inter_sf.prune_motion_mode_level = 2;
     sf->inter_sf.prune_ref_frame_for_rect_partitions =
-        (frame_is_intra_only(&cpi->common) || (cm->allow_screen_content_tools))
+        (frame_is_intra_only(&cpi->common) || (allow_screen_content_tools))
             ? 0
             : (boosted ? 1 : 2);
     sf->inter_sf.reduce_inter_modes = boosted ? 1 : 2;
@@ -414,8 +415,7 @@
     sf->rd_sf.perform_coeff_opt = is_boosted_arf2_bwd_type ? 2 : 3;
 
     sf->lpf_sf.prune_wiener_based_on_src_var = 1;
-    sf->lpf_sf.prune_sgr_based_on_wiener =
-        cm->allow_screen_content_tools ? 0 : 1;
+    sf->lpf_sf.prune_sgr_based_on_wiener = !allow_screen_content_tools;
   }
 
   if (speed >= 3) {
@@ -427,7 +427,7 @@
     sf->part_sf.less_rectangular_check_level = 2;
     sf->part_sf.simple_motion_search_prune_agg = 1;
     sf->part_sf.prune_4_partition_using_split_info =
-        cm->allow_screen_content_tools ? 0 : 1;
+        !allow_screen_content_tools;
 
     // adaptive_motion_search breaks encoder multi-thread tests.
     // The values in x->pred_mv[] differ for single and multi-thread cases.
@@ -453,10 +453,9 @@
     if (cpi->oxcf.enable_smooth_interintra)
       sf->inter_sf.disable_smooth_interintra = boosted ? 0 : 1;
     sf->inter_sf.reuse_compound_type_decision = 1;
-    sf->inter_sf.txfm_rd_gate_level =
-        (boosted || cm->allow_screen_content_tools)
-            ? 0
-            : (is_boosted_arf2_bwd_type ? 1 : 2);
+    sf->inter_sf.txfm_rd_gate_level = (boosted || allow_screen_content_tools)
+                                          ? 0
+                                          : (is_boosted_arf2_bwd_type ? 1 : 2);
 
     sf->intra_sf.prune_palette_search_level = 2;
 
@@ -466,7 +465,7 @@
 
     sf->tx_sf.adaptive_txb_search_level = boosted ? 2 : 3;
     sf->tx_sf.tx_type_search.use_skip_flag_prediction =
-        cm->allow_screen_content_tools ? 1 : 2;
+        allow_screen_content_tools ? 1 : 2;
 
     // TODO(any): Refactor the code related to following winner mode speed
     // features
@@ -475,7 +474,7 @@
     sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch =
         frame_is_intra_only(&cpi->common) ? 0 : 1;
     sf->winner_mode_sf.enable_winner_mode_for_use_tx_domain_dist =
-        cm->allow_screen_content_tools ? 0 : 1;
+        !allow_screen_content_tools;
     sf->winner_mode_sf.motion_mode_for_winner_cand =
         boosted
             ? 0
@@ -483,10 +482,9 @@
                                                                          : 2;
 
     // TODO(any): evaluate if these lpf features can be moved to speed 2.
-    sf->lpf_sf.prune_sgr_based_on_wiener =
-        cm->allow_screen_content_tools ? 0 : 2;
+    sf->lpf_sf.prune_sgr_based_on_wiener = allow_screen_content_tools ? 0 : 2;
     sf->lpf_sf.disable_loop_restoration_chroma =
-        (boosted || cm->allow_screen_content_tools) ? 0 : 1;
+        (boosted || allow_screen_content_tools) ? 0 : 1;
     sf->lpf_sf.reduce_wiener_window_size = !boosted;
     sf->lpf_sf.prune_wiener_based_on_src_var = 2;
 
@@ -498,13 +496,13 @@
 
     sf->part_sf.simple_motion_search_prune_agg = 2;
     sf->part_sf.prune_ab_partition_using_split_info =
-        cm->allow_screen_content_tools ? 0 : 1;
+        !allow_screen_content_tools;
 
     sf->inter_sf.adaptive_mode_search = 1;
     sf->inter_sf.alt_ref_search_fp = 1;
     sf->inter_sf.prune_ref_mv_idx_search = 1;
     sf->inter_sf.txfm_rd_gate_level =
-        (boosted || cm->allow_screen_content_tools) ? 0 : 3;
+        (boosted || allow_screen_content_tools) ? 0 : 3;
 
     sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 2;
     sf->inter_sf.disable_smooth_interintra = 1;
@@ -540,7 +538,7 @@
         frame_is_intra_only(&cpi->common) ? 1 : 0;
     sf->winner_mode_sf.enable_winner_mode_for_tx_size_srch = 1;
 
-    sf->lpf_sf.cdef_pick_method = cm->allow_screen_content_tools
+    sf->lpf_sf.cdef_pick_method = allow_screen_content_tools
                                       ? CDEF_FAST_SEARCH_LVL1
                                       : CDEF_FAST_SEARCH_LVL2;
 
@@ -566,14 +564,14 @@
   if (speed >= 5) {
     sf->part_sf.simple_motion_search_prune_agg = 3;
     sf->part_sf.ext_partition_eval_thresh =
-        cm->allow_screen_content_tools ? BLOCK_8X8 : BLOCK_16X16;
+        allow_screen_content_tools ? BLOCK_8X8 : BLOCK_16X16;
 
     sf->inter_sf.prune_inter_modes_based_on_tpl = boosted ? 0 : 3;
     sf->inter_sf.disable_interinter_wedge = 1;
     sf->inter_sf.disable_obmc = 1;
     sf->inter_sf.disable_onesided_comp = 1;
     sf->inter_sf.txfm_rd_gate_level =
-        (boosted || cm->allow_screen_content_tools) ? 0 : 4;
+        (boosted || allow_screen_content_tools) ? 0 : 4;
     sf->inter_sf.prune_inter_modes_if_skippable = 1;
 
     sf->lpf_sf.lpf_pick = LPF_PICK_FROM_FULL_IMAGE_NON_DUAL;
@@ -1274,7 +1272,7 @@
   if (is_720p_or_larger && cpi->oxcf.mode == GOOD && speed == 0) {
     if (cm->base_qindex <= 80) {
       sf->part_sf.simple_motion_search_split =
-          cm->allow_screen_content_tools ? 1 : 2;
+          cm->features.allow_screen_content_tools ? 1 : 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;
diff --git a/av1/encoder/temporal_filter.c b/av1/encoder/temporal_filter.c
index b8d7814..465cfb8 100644
--- a/av1/encoder/temporal_filter.c
+++ b/av1/encoder/temporal_filter.c
@@ -95,7 +95,7 @@
   const int step_param = av1_init_search_range(
       AOMMAX(frame_to_filter->y_crop_width, frame_to_filter->y_crop_height));
   const SUBPEL_SEARCH_TYPE subpel_search_type = USE_8_TAPS;
-  const int force_integer_mv = cpi->common.cur_frame_force_integer_mv;
+  const int force_integer_mv = cpi->common.features.cur_frame_force_integer_mv;
   const MV_COST_TYPE mv_cost_type =
       min_frame_size >= 720
           ? MV_COST_L1_HDRES
@@ -1217,8 +1217,9 @@
   const int rdmult = av1_compute_rd_mult_based_on_qindex(cpi, TF_QINDEX);
   set_error_per_bit(&cpi->td.mb, rdmult);
   av1_initialize_me_consts(cpi, &cpi->td.mb, TF_QINDEX);
-  av1_fill_mv_costs(cpi->common.fc, cpi->common.cur_frame_force_integer_mv,
-                    cpi->common.allow_high_precision_mv, &cpi->td.mb);
+  av1_fill_mv_costs(cpi->common.fc,
+                    cpi->common.features.cur_frame_force_integer_mv,
+                    cpi->common.features.allow_high_precision_mv, &cpi->td.mb);
 
   // TODO(weitinglin): Currently, we enforce the filtering strength on internal
   // ARFs to be zeros. We should investigate in which case it is more beneficial
diff --git a/av1/encoder/tx_search.c b/av1/encoder/tx_search.c
index e2fb8e8..0ff71ef 100644
--- a/av1/encoder/tx_search.c
+++ b/av1/encoder/tx_search.c
@@ -1114,7 +1114,7 @@
 
     inverse_transform_block_facade(xd, plane, block, blk_row, blk_col,
                                    x->plane[plane].eobs[block],
-                                   cm->reduced_tx_set_used);
+                                   cm->features.reduced_tx_set_used);
 
     // This may happen because of hash collision. The eob stored in the hash
     // table is non-zero, but the real eob is zero. We need to make sure tx_type
@@ -1222,10 +1222,10 @@
 
   const PLANE_TYPE plane_type = get_plane_type(plane);
   TX_TYPE tx_type = av1_get_tx_type(xd, plane_type, blk_row, blk_col, tx_size,
-                                    cpi->common.reduced_tx_set_used);
+                                    cpi->common.features.reduced_tx_set_used);
   av1_inverse_transform_block(xd, dqcoeff, plane, tx_type, tx_size, recon,
                               MAX_TX_SIZE, eob,
-                              cpi->common.reduced_tx_set_used);
+                              cpi->common.features.reduced_tx_set_used);
 
   return 16 * pixel_dist(cpi, x, plane, src, src_stride, recon, MAX_TX_SIZE,
                          blk_row, blk_col, plane_bsize, tx_bsize);
@@ -1282,7 +1282,7 @@
       xd->tx_type_map[tx_type_map_idx] = (*intra_txb_rd_info)->tx_type;
       const TX_TYPE ref_tx_type =
           av1_get_tx_type(xd, get_plane_type(plane), blk_row, blk_col, tx_size,
-                          cpi->common.reduced_tx_set_used);
+                          cpi->common.features.reduced_tx_set_used);
       return (ref_tx_type == (*intra_txb_rd_info)->tx_type);
     }
   }
@@ -1932,15 +1932,15 @@
     if (plane == 0) txk_allowed = DCT_DCT;
   }
 
-  const TxSetType tx_set_type =
-      av1_get_ext_tx_set_type(tx_size, is_inter, cm->reduced_tx_set_used);
+  const TxSetType tx_set_type = av1_get_ext_tx_set_type(
+      tx_size, is_inter, cm->features.reduced_tx_set_used);
 
   TX_TYPE uv_tx_type = DCT_DCT;
   if (plane) {
     // tx_type of PLANE_TYPE_UV should be the same as PLANE_TYPE_Y
     uv_tx_type = txk_allowed =
         av1_get_tx_type(xd, get_plane_type(plane), blk_row, blk_col, tx_size,
-                        cm->reduced_tx_set_used);
+                        cm->features.reduced_tx_set_used);
   }
   PREDICTION_MODE intra_dir =
       mbmi->filter_intra_mode_info.use_filter_intra
@@ -1999,16 +1999,17 @@
       int pf = prune_factors[x->prune_mode];
       int mf = mul_factors[x->prune_mode];
       if (num_allowed <= 7) {
-        const uint16_t prune = prune_txk_type(
-            cpi, x, plane, block, tx_size, blk_row, blk_col, plane_bsize,
-            txk_map, allowed_tx_mask, pf, txb_ctx, cm->reduced_tx_set_used);
+        const uint16_t prune =
+            prune_txk_type(cpi, x, plane, block, tx_size, blk_row, blk_col,
+                           plane_bsize, txk_map, allowed_tx_mask, pf, txb_ctx,
+                           cm->features.reduced_tx_set_used);
         allowed_tx_mask &= (~prune);
       } else {
         const int num_sel = (num_allowed * mf + 50) / 100;
         const uint16_t prune = prune_txk_type_separ(
             cpi, x, plane, block, tx_size, blk_row, blk_col, plane_bsize,
-            txk_map, allowed_tx_mask, pf, txb_ctx, cm->reduced_tx_set_used,
-            ref_best_rd, num_sel);
+            txk_map, allowed_tx_mask, pf, txb_ctx,
+            cm->features.reduced_tx_set_used, ref_best_rd, num_sel);
 
         allowed_tx_mask &= (~prune);
       }
@@ -2225,9 +2226,9 @@
       av1_optimize_b(cpi, x, plane, block, tx_size, tx_type, txb_ctx,
                      cpi->sf.rd_sf.trellis_eob_fast, &rate_cost);
     } else {
-      rate_cost =
-          av1_cost_coeffs(x, plane, block, tx_size, tx_type, txb_ctx,
-                          use_fast_coef_costing, cm->reduced_tx_set_used);
+      rate_cost = av1_cost_coeffs(x, plane, block, tx_size, tx_type, txb_ctx,
+                                  use_fast_coef_costing,
+                                  cm->features.reduced_tx_set_used);
     }
 
     // If rd cost based on coeff rate is more than best_rd, skip the calculation
@@ -2403,7 +2404,7 @@
     if (plane == 0) xd->tx_type_map[tx_type_map_idx] = rd_info_array->tx_type;
     const TX_TYPE ref_tx_type =
         av1_get_tx_type(&x->e_mbd, get_plane_type(plane), blk_row, blk_col,
-                        tx_size, cpi->common.reduced_tx_set_used);
+                        tx_size, cpi->common.features.reduced_tx_set_used);
     if (ref_tx_type == rd_info_array->tx_type) {
       rd_stats->rate += rd_info_array->rate;
       rd_stats->dist += rd_info_array->dist;
@@ -3234,7 +3235,7 @@
   // context and terminate early.
   int64_t dist;
   if (x->predict_skip_level &&
-      predict_skip_flag(x, bsize, &dist, cm->reduced_tx_set_used)) {
+      predict_skip_flag(x, bsize, &dist, cm->features.reduced_tx_set_used)) {
     set_skip_flag(x, rd_stats, bsize, dist);
     // Save the RD search results into tx_rd_record.
     if (is_mb_rd_hash_enabled)
@@ -3317,7 +3318,8 @@
 
   if (x->predict_skip_level && is_inter &&
       (!xd->lossless[xd->mi[0]->segment_id]) &&
-      predict_skip_flag(x, bs, &dist, cpi->common.reduced_tx_set_used)) {
+      predict_skip_flag(x, bs, &dist,
+                        cpi->common.features.reduced_tx_set_used)) {
     // Populate rdstats as per skip decision
     set_skip_flag(x, rd_stats, bs, dist);
     // Save the RD search results into tx_rd_record.