Pack txfm-search records in MACROBLOCK to TxfmSearchInfo

This CL introduces TxfmSearchInfo struct that is meant to store the
intermediate results during txfm search.

Bug=aomedia:2618

Change-Id: Id5860a6017fceeaec742066644a03645114669e6
diff --git a/av1/encoder/block.h b/av1/encoder/block.h
index 3e9dce9..ba6892f 100644
--- a/av1/encoder/block.h
+++ b/av1/encoder/block.h
@@ -297,6 +297,61 @@
   TX_MODE tx_mode_search_type;
 } TxfmSearchParams;
 
+#define MAX_NUM_8X8_TXBS ((MAX_MIB_SIZE >> 1) * (MAX_MIB_SIZE >> 1))
+#define MAX_NUM_16X16_TXBS ((MAX_MIB_SIZE >> 2) * (MAX_MIB_SIZE >> 2))
+#define MAX_NUM_32X32_TXBS ((MAX_MIB_SIZE >> 3) * (MAX_MIB_SIZE >> 3))
+#define MAX_NUM_64X64_TXBS ((MAX_MIB_SIZE >> 4) * (MAX_MIB_SIZE >> 4))
+
+// This struct stores various encoding/search decisions related to txfm search.
+// This can include cache of previous txfm results, the current encoding
+// decision, etc.
+typedef struct {
+  // Skips transform and quantization on a partition block level.
+  int skip_txfm;
+
+  // Skips transform and quantization on a transform block level inside the
+  // current partition block. Each element of this array is used as a bit-field.
+  // So for example, the we are skipping on the luma plane, then the last bit
+  // would be set to 1.
+  uint8_t blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
+
+  // Keeps a record of what kind of transform to use for each of the transform
+  // block inside the partition block. A quick note here: the buffer here is
+  // NEVER directly used. Instead, this just allocates the memory for
+  // MACROBLOCKD::tx_type_map during rdopt on the partition block. So if we need
+  // to save memory, we could move the allocation to pick_sb_mode instead.
+  uint8_t tx_type_map_[MAX_MIB_SIZE * MAX_MIB_SIZE];
+
+  // Records of a partition block's inter-mode txfm result hashed by its
+  // residue. This is similar to txb_rd_record_*, but this operates on the whole
+  // prediction block.
+  MB_RD_RECORD mb_rd_record;
+
+  // Records of a transform block's result hashed by residue within the
+  // transform block. This operates on txb level only and only applies to square
+  // txfms.
+  // Inter transform block RD search
+  TXB_RD_RECORD txb_rd_record_8X8[MAX_NUM_8X8_TXBS];
+  TXB_RD_RECORD txb_rd_record_16X16[MAX_NUM_16X16_TXBS];
+  TXB_RD_RECORD txb_rd_record_32X32[MAX_NUM_32X32_TXBS];
+  TXB_RD_RECORD txb_rd_record_64X64[MAX_NUM_64X64_TXBS];
+  // Intra transform block RD search
+  TXB_RD_RECORD txb_rd_record_intra;
+
+  // Keep track of how many times we've used split partition for transform
+  // blocks. Misleadingly, his parameter doesn't actually keep track of the
+  // count of the current block. Instead, it's a cumulative count across of the
+  // whole frame. The main usage is that if txb_split_count is zero, then we
+  // can signal TX_MODE_LARGEST at frame level.
+  // TODO(chiyotsai@google.com): Move this to a more appropriate location such
+  // as ThreadData.
+  unsigned int txb_split_count;
+#if CONFIG_SPEED_STATS
+  // For debugging. Used to check how many txfm searches we are doing.
+  unsigned int tx_search_count;
+#endif  // CONFIG_SPEED_STATS
+} TxfmSearchInfo;
+
 struct inter_modes_info;
 typedef struct macroblock MACROBLOCK;
 struct macroblock {
@@ -310,18 +365,6 @@
   // prune_comp_search_by_single_result (3:MAX_REF_MV_SEARCH)
   SimpleRDState simple_rd_state[SINGLE_REF_MODES][3];
 
-  // Inter macroblock RD search info.
-  MB_RD_RECORD mb_rd_record;
-
-  // Inter transform block RD search info. for square TX sizes.
-  TXB_RD_RECORD txb_rd_record_8X8[(MAX_MIB_SIZE >> 1) * (MAX_MIB_SIZE >> 1)];
-  TXB_RD_RECORD txb_rd_record_16X16[(MAX_MIB_SIZE >> 2) * (MAX_MIB_SIZE >> 2)];
-  TXB_RD_RECORD txb_rd_record_32X32[(MAX_MIB_SIZE >> 3) * (MAX_MIB_SIZE >> 3)];
-  TXB_RD_RECORD txb_rd_record_64X64[(MAX_MIB_SIZE >> 4) * (MAX_MIB_SIZE >> 4)];
-
-  // Intra transform block RD search info. for square TX sizes.
-  TXB_RD_RECORD txb_rd_record_intra;
-
   MACROBLOCKD e_mbd;
   MB_MODE_INFO_EXT *mbmi_ext;
   MB_MODE_INFO_EXT_FRAME *mbmi_ext_frame;
@@ -341,11 +384,6 @@
   int mb_energy;
   int sb_energy_level;
 
-  unsigned int txb_split_count;
-#if CONFIG_SPEED_STATS
-  unsigned int tx_search_count;
-#endif  // CONFIG_SPEED_STATS
-
   // These are set to their default values at the beginning, and then adjusted
   // further in the encoding process.
   BLOCK_SIZE min_partition_size;
@@ -395,11 +433,6 @@
   // Stores the entropy cost needed to encode a motion vector.
   MvCostInfo mv_cost_info;
 
-  uint8_t blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
-  uint8_t tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
-
-  // Forces the coding block to skip transform and quantization.
-  int skip_txfm;
   int skip_txfm_cost[SKIP_CONTEXTS][2];
 
   // Skip mode tries to use the closest forward and backward references for
@@ -410,7 +443,6 @@
 
   LV_MAP_COEFF_COST coeff_costs[TX_SIZES][PLANE_TYPES];
   LV_MAP_EOB_COST eob_costs[7][2];
-  uint16_t cb_offset;
 
   // mode costs
   int intra_inter_cost[INTRA_INTER_CONTEXTS][2];
@@ -494,8 +526,6 @@
   COMP_RD_STATS comp_rd_stats[MAX_COMP_RD_STATS];
   int comp_rd_stats_idx;
 
-  CB_COEFF_BUFFER *cb_coef_buff;
-
 #if !CONFIG_REALTIME_ONLY
   int quad_tree_idx;
   int cnn_output_valid;
@@ -518,11 +548,22 @@
   uint8_t color_sensitivity[2];
   int nonrd_prune_ref_frame_search;
 
+  uint8_t search_ref_frame[REF_FRAMES];
+
   // Stores various txfm search related parameters such as txfm_type, txfm_size,
   // trellis eob search, etc.
   TxfmSearchParams txfm_search_params;
 
-  uint8_t search_ref_frame[REF_FRAMES];
+  // Caches old txfm search results and keeps the current txfm decisions.
+  TxfmSearchInfo txfm_search_info;
+
+  // Points to cb_coef_buff in the AV1_COMP struct, which contains the finalized
+  // coefficients. This is here to conveniently copy the best coefficients to
+  // frame level for bitstream packing. Since CB_COEFF_BUFFER is allocated on a
+  // superblock level, we need to combine it with cb_offset to get the proper
+  // position for the current coding block.
+  CB_COEFF_BUFFER *cb_coef_buff;
+  uint16_t cb_offset;
 
   // The information on a whole superblock level.
   // TODO(chiyotsai@google.com): Refactor this out of macroblock
@@ -585,34 +626,34 @@
   return depth;
 }
 
-static INLINE void set_blk_skip(MACROBLOCK *x, int plane, int blk_idx,
+static INLINE void set_blk_skip(uint8_t txb_skip[], int plane, int blk_idx,
                                 int skip) {
   if (skip)
-    x->blk_skip[blk_idx] |= 1UL << plane;
+    txb_skip[blk_idx] |= 1UL << plane;
   else
-    x->blk_skip[blk_idx] &= ~(1UL << plane);
+    txb_skip[blk_idx] &= ~(1UL << plane);
 #ifndef NDEBUG
   // Set chroma planes to uninitialized states when luma is set to check if
   // it will be set later
   if (plane == 0) {
-    x->blk_skip[blk_idx] |= 1UL << (1 + 4);
-    x->blk_skip[blk_idx] |= 1UL << (2 + 4);
+    txb_skip[blk_idx] |= 1UL << (1 + 4);
+    txb_skip[blk_idx] |= 1UL << (2 + 4);
   }
 
   // Clear the initialization checking bit
-  x->blk_skip[blk_idx] &= ~(1UL << (plane + 4));
+  txb_skip[blk_idx] &= ~(1UL << (plane + 4));
 #endif
 }
 
-static INLINE int is_blk_skip(MACROBLOCK *x, int plane, int blk_idx) {
+static INLINE int is_blk_skip(uint8_t *txb_skip, int plane, int blk_idx) {
 #ifndef NDEBUG
   // Check if this is initialized
-  assert(!(x->blk_skip[blk_idx] & (1UL << (plane + 4))));
+  assert(!(txb_skip[blk_idx] & (1UL << (plane + 4))));
 
   // The magic number is 0x77, this is to test if there is garbage data
-  assert((x->blk_skip[blk_idx] & 0x88) == 0);
+  assert((txb_skip[blk_idx] & 0x88) == 0);
 #endif
-  return (x->blk_skip[blk_idx] >> plane) & 1;
+  return (txb_skip[blk_idx] >> plane) & 1;
 }
 
 #ifdef __cplusplus
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index 720f9cf..b52c85c 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -488,6 +488,7 @@
 static AOM_INLINE void reset_tx_size(MACROBLOCK *x, MB_MODE_INFO *mbmi,
                                      const TX_MODE tx_mode) {
   MACROBLOCKD *const xd = &x->e_mbd;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   if (xd->lossless[mbmi->segment_id]) {
     mbmi->tx_size = TX_4X4;
   } else if (tx_mode != TX_MODE_SELECT) {
@@ -506,8 +507,8 @@
     memset(xd->tx_type_map + row * stride, DCT_DCT,
            bw * sizeof(xd->tx_type_map[0]));
   }
-  av1_zero(x->blk_skip);
-  x->skip_txfm = 0;
+  av1_zero(txfm_info->blk_skip);
+  txfm_info->skip_txfm = 0;
 }
 
 // This function will copy the best reference mode information from
@@ -546,6 +547,7 @@
   const int mis = mi_params->mi_stride;
   const int mi_width = mi_size_wide[bsize];
   const int mi_height = mi_size_high[bsize];
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
 
   assert(mi->sb_type == bsize);
 
@@ -553,9 +555,10 @@
   copy_mbmi_ext_frame_to_mbmi_ext(x->mbmi_ext, &ctx->mbmi_ext_best,
                                   av1_ref_frame_type(ctx->mic.ref_frame));
 
-  memcpy(x->blk_skip, ctx->blk_skip, sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+  memcpy(txfm_info->blk_skip, ctx->blk_skip,
+         sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
 
-  x->skip_txfm = ctx->rd_stats.skip_txfm;
+  txfm_info->skip_txfm = ctx->rd_stats.skip_txfm;
 
   xd->tx_type_map = ctx->tx_type_map;
   xd->tx_type_map_stride = mi_size_wide[bsize];
@@ -588,7 +591,7 @@
     if (cpi->oxcf.aq_mode == CYCLIC_REFRESH_AQ) {
       av1_cyclic_refresh_update_segment(cpi, mi_addr, mi_row, mi_col, bsize,
                                         ctx->rd_stats.rate, ctx->rd_stats.dist,
-                                        x->skip_txfm);
+                                        txfm_info->skip_txfm);
     }
     if (mi_addr->uv_mode == UV_CFL_PRED && !is_cfl_allowed(xd))
       mi_addr->uv_mode = UV_DC_PRED;
@@ -750,6 +753,8 @@
   struct macroblock_plane *const p = x->plane;
   struct macroblockd_plane *const pd = xd->plane;
   const AQ_MODE aq_mode = cpi->oxcf.aq_mode;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
+
   int i;
 
 #if CONFIG_COLLECT_COMPONENT_TIMING
@@ -767,7 +772,8 @@
   mbmi->mi_col = mi_col;
 #endif
 
-  xd->tx_type_map = x->tx_type_map;
+  // Sets up the tx_type_map buffer in MACROBLOCKD.
+  xd->tx_type_map = txfm_info->tx_type_map_;
   xd->tx_type_map_stride = mi_size_wide[bsize];
 
   for (i = 0; i < num_planes; ++i) {
@@ -2879,7 +2885,8 @@
   // when debugging.
   // bit 0, 1, 2 are blk_skip of each plane
   // bit 4, 5, 6 are initialization checking of each plane
-  memset(x->blk_skip, 0x77, sizeof(x->blk_skip));
+  memset(x->txfm_search_info.blk_skip, 0x77,
+         sizeof(x->txfm_search_info.blk_skip));
 #endif  // NDEBUG
 
   assert(mi_size_wide[bsize] == mi_size_high[bsize]);
@@ -4663,7 +4670,7 @@
   save_context(x, &sb_fp_stats->x_ctx, mi_row, mi_col, sb_size, num_planes);
 
   sb_fp_stats->rd_count = cpi->td.rd_counts;
-  sb_fp_stats->split_count = cpi->td.mb.txb_split_count;
+  sb_fp_stats->split_count = x->txfm_search_info.txb_split_count;
 
   sb_fp_stats->fc = *td->counts;
 
@@ -4696,7 +4703,7 @@
   restore_context(x, &sb_fp_stats->x_ctx, mi_row, mi_col, sb_size, num_planes);
 
   cpi->td.rd_counts = sb_fp_stats->rd_count;
-  cpi->td.mb.txb_split_count = sb_fp_stats->split_count;
+  x->txfm_search_info.txb_split_count = sb_fp_stats->split_count;
 
   *td->counts = sb_fp_stats->fc;
 
@@ -4854,7 +4861,7 @@
 #endif
 
   // Reset hash state for transform/mode rd hash information
-  reset_hash_records(x, cpi->sf.tx_sf.use_inter_txb_hash);
+  reset_hash_records(&x->txfm_search_info, cpi->sf.tx_sf.use_inter_txb_hash);
   av1_zero(x->picked_ref_frames_mask);
   av1_zero(x->pred_mv);
   av1_invalid_rd_stats(rd_cost);
@@ -5244,7 +5251,8 @@
 
   if (cpi->oxcf.enable_cfl_intra) cfl_init(&td->mb.e_mbd.cfl, &cm->seq_params);
 
-  av1_crc32c_calculator_init(&td->mb.mb_rd_record.crc_calculator);
+  av1_crc32c_calculator_init(
+      &td->mb.txfm_search_info.mb_rd_record.crc_calculator);
 
   for (int mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
        mi_row += cm->seq_params.mib_size) {
@@ -6066,9 +6074,9 @@
   // Figure out which ref frames can be skipped at frame level.
   setup_prune_ref_frame_mask(cpi);
 
-  x->txb_split_count = 0;
+  x->txfm_search_info.txb_split_count = 0;
 #if CONFIG_SPEED_STATS
-  x->tx_search_count = 0;
+  x->txfm_search_info.tx_search_count = 0;
 #endif  // CONFIG_SPEED_STATS
 
 #if CONFIG_COLLECT_COMPONENT_TIMING
@@ -6324,7 +6332,7 @@
 
     if (!cm->tiles.large_scale) {
       if (features->tx_mode == TX_MODE_SELECT &&
-          cpi->td.mb.txb_split_count == 0)
+          cpi->td.mb.txfm_search_info.txb_split_count == 0)
         features->tx_mode = TX_MODE_LARGEST;
     }
   } else {
@@ -6376,7 +6384,7 @@
 #endif
     if (allow_update_cdf)
       update_cdf(xd->tile_ctx->txfm_partition_cdf[ctx], 1, 2);
-    ++x->txb_split_count;
+    ++x->txfm_search_info.txb_split_count;
 
     if (sub_txs == TX_4X4) {
       mbmi->inter_tx_size[txb_size_index] = TX_4X4;
@@ -6595,7 +6603,7 @@
                                   tile_data->allow_update_cdf);
       } else {
         if (mbmi->tx_size != max_txsize_rect_lookup[bsize])
-          ++x->txb_split_count;
+          ++x->txfm_search_info.txb_split_count;
         if (block_signals_txsize(bsize)) {
           const int tx_size_ctx = get_tx_size_context(xd);
           const int32_t tx_size_cat = bsize_to_tx_size_cat(bsize);
@@ -6632,7 +6640,8 @@
               mi_row + j < cm->mi_params.mi_rows)
             mi_4x4[mis * j + i]->tx_size = intra_tx_size;
 
-      if (intra_tx_size != max_txsize_rect_lookup[bsize]) ++x->txb_split_count;
+      if (intra_tx_size != max_txsize_rect_lookup[bsize])
+        ++x->txfm_search_info.txb_split_count;
     }
   }
 
diff --git a/av1/encoder/encodemb.c b/av1/encoder/encodemb.c
index a6cc72e..5a986b1 100644
--- a/av1/encoder/encodemb.c
+++ b/av1/encoder/encodemb.c
@@ -366,7 +366,9 @@
   l = &args->tl[blk_row];
 
   TX_TYPE tx_type = DCT_DCT;
-  if (!is_blk_skip(x, plane, blk_row * bw + blk_col) && !mbmi->skip_mode) {
+  if (!is_blk_skip(x->txfm_search_info.blk_skip, 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->features.reduced_tx_set_used);
     TxfmParam txfm_param;
@@ -601,7 +603,7 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = xd->mi[0];
   mbmi->skip_txfm = 1;
-  if (x->skip_txfm) return;
+  if (x->txfm_search_info.skip_txfm) return;
 
   struct optimize_ctx ctx;
   struct encode_b_args arg = {
@@ -690,7 +692,8 @@
 
   TX_TYPE tx_type = DCT_DCT;
   const int bw = mi_size_wide[plane_bsize];
-  if (plane == 0 && is_blk_skip(x, plane, blk_row * bw + blk_col)) {
+  if (plane == 0 && is_blk_skip(x->txfm_search_info.blk_skip, plane,
+                                blk_row * bw + blk_col)) {
     *eob = 0;
     p->txb_entropy_ctx[block] = 0;
   } else {
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index e027b6a..b976f09 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -6939,8 +6939,8 @@
 #endif  // CONFIG_INTERNAL_STATS
 #if CONFIG_SPEED_STATS
   if (!is_stat_generation_stage(cpi) && !cm->show_existing_frame) {
-    cpi->tx_search_count += cpi->td.mb.tx_search_count;
-    cpi->td.mb.tx_search_count = 0;
+    cpi->tx_search_count += cpi->td.mb.txfm_search_info.tx_search_count;
+    cpi->td.mb.txfm_search_info.tx_search_count = 0;
   }
 #endif  // CONFIG_SPEED_STATS
 
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index 09039af..753bd2b 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -401,7 +401,8 @@
                            &td->mb.e_mbd);
 
     cfl_init(&td->mb.e_mbd.cfl, &cm->seq_params);
-    av1_crc32c_calculator_init(&td->mb.mb_rd_record.crc_calculator);
+    av1_crc32c_calculator_init(
+        &td->mb.txfm_search_info.mb_rd_record.crc_calculator);
 
     av1_encode_sb_row(cpi, td, tile_row, tile_col, current_mi_row);
 #if CONFIG_MULTITHREAD
@@ -595,9 +596,11 @@
     if (i > 0) {
       av1_accumulate_frame_counts(&cpi->counts, thread_data->td->counts);
       accumulate_rd_opt(&cpi->td, thread_data->td);
-      cpi->td.mb.txb_split_count += thread_data->td->mb.txb_split_count;
+      cpi->td.mb.txfm_search_info.txb_split_count +=
+          thread_data->td->mb.txfm_search_info.txb_split_count;
 #if CONFIG_SPEED_STATS
-      cpi->td.mb.tx_search_count += thread_data->td->mb.tx_search_count;
+      cpi->td.mb.txfm_search_info.tx_search_count +=
+          thread_data->td->mb.txfm_search_info.tx_search_count;
 #endif  // CONFIG_SPEED_STATS
     }
   }
diff --git a/av1/encoder/intra_mode_search.c b/av1/encoder/intra_mode_search.c
index 39fc8db..f1b5723 100644
--- a/av1/encoder/intra_mode_search.c
+++ b/av1/encoder/intra_mode_search.c
@@ -286,7 +286,8 @@
   this_rd = RDCOST(x->rdmult, this_rate, tokenonly_rd_stats.dist);
 
   if (this_rd < *best_rd) {
-    memcpy(best_blk_skip, x->blk_skip, sizeof(best_blk_skip[0]) * n4);
+    memcpy(best_blk_skip, x->txfm_search_info.blk_skip,
+           sizeof(best_blk_skip[0]) * n4);
     av1_copy_array(best_tx_type_map, xd->tx_type_map, n4);
     *best_rd = this_rd;
     *best_angle_delta = mbmi->angle_delta[PLANE_TYPE_Y];
@@ -455,8 +456,8 @@
       best_tx_size = mbmi->tx_size;
       filter_intra_mode_info = mbmi->filter_intra_mode_info;
       av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
-      memcpy(ctx->blk_skip, x->blk_skip,
-             sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+      memcpy(ctx->blk_skip, x->txfm_search_info.blk_skip,
+             sizeof(x->txfm_search_info.blk_skip[0]) * ctx->num_4x4_blk);
       *rate = this_rate;
       *rate_tokenonly = tokenonly_rd_stats.rate;
       *distortion = tokenonly_rd_stats.dist;
@@ -627,7 +628,8 @@
     memcpy(best_palette_color_map, color_map,
            block_width * block_height * sizeof(color_map[0]));
     *best_mbmi = *mbmi;
-    memcpy(blk_skip, x->blk_skip, sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+    memcpy(blk_skip, x->txfm_search_info.blk_skip,
+           sizeof(x->txfm_search_info.blk_skip[0]) * ctx->num_4x4_blk);
     av1_copy_array(tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
     if (rate) *rate = this_rate;
     if (rate_tokenonly) *rate_tokenonly = tokenonly_rd_stats.rate;
@@ -1569,7 +1571,7 @@
     return skippable;
   }
 
-  memcpy(x->blk_skip, best_blk_skip,
+  memcpy(x->txfm_search_info.blk_skip, best_blk_skip,
          sizeof(best_blk_skip[0]) * bsize_to_num_blk(bsize));
   av1_copy_array(xd->tx_type_map, best_tx_type_map, ctx->num_4x4_blk);
   memcpy(color_map, best_palette_color_map,
@@ -1648,7 +1650,8 @@
     *rate_tokenonly = this_rate_tokenonly;
     *distortion = rd_stats.dist;
     *skippable = rd_stats.skip_txfm;
-    av1_copy_array(ctx->blk_skip, x->blk_skip, ctx->num_4x4_blk);
+    av1_copy_array(ctx->blk_skip, x->txfm_search_info.blk_skip,
+                   ctx->num_4x4_blk);
     av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
     return 1;
   }
@@ -1716,7 +1719,8 @@
     mbmi->tx_size = best_tx_size;
     mbmi->angle_delta[PLANE_TYPE_Y] = best_angle_delta;
     const int n4 = bsize_to_num_blk(bsize);
-    memcpy(x->blk_skip, best_blk_skip, sizeof(best_blk_skip[0]) * n4);
+    memcpy(x->txfm_search_info.blk_skip, best_blk_skip,
+           sizeof(best_blk_skip[0]) * n4);
     av1_copy_array(xd->tx_type_map, best_tx_type_map, n4);
   }
   return best_rd;
@@ -1797,7 +1801,7 @@
       TX_SIZE best_tx_size = mbmi->tx_size;
       FILTER_INTRA_MODE best_fi_mode = FILTER_DC_PRED;
       uint8_t best_blk_skip[MAX_MIB_SIZE * MAX_MIB_SIZE];
-      memcpy(best_blk_skip, x->blk_skip,
+      memcpy(best_blk_skip, x->txfm_search_info.blk_skip,
              sizeof(best_blk_skip[0]) * ctx->num_4x4_blk);
       uint8_t best_tx_type_map[MAX_MIB_SIZE * MAX_MIB_SIZE];
       av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
@@ -1820,7 +1824,7 @@
         if (this_rd_tmp < best_rd_so_far) {
           best_tx_size = mbmi->tx_size;
           av1_copy_array(best_tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
-          memcpy(best_blk_skip, x->blk_skip,
+          memcpy(best_blk_skip, x->txfm_search_info.blk_skip,
                  sizeof(best_blk_skip[0]) * ctx->num_4x4_blk);
           best_fi_mode = fi_mode;
           *rd_stats_y = rd_stats_y_fi;
@@ -1831,8 +1835,8 @@
 
       mbmi->tx_size = best_tx_size;
       av1_copy_array(xd->tx_type_map, best_tx_type_map, ctx->num_4x4_blk);
-      memcpy(x->blk_skip, best_blk_skip,
-             sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+      memcpy(x->txfm_search_info.blk_skip, best_blk_skip,
+             sizeof(x->txfm_search_info.blk_skip[0]) * ctx->num_4x4_blk);
 
       if (filter_intra_selected_flag) {
         mbmi->filter_intra_mode_info.use_filter_intra = 1;
@@ -2053,8 +2057,8 @@
       *rate_tokenonly = this_rate_tokenonly;
       *distortion = this_distortion;
       *skippable = s;
-      memcpy(ctx->blk_skip, x->blk_skip,
-             sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+      memcpy(ctx->blk_skip, x->txfm_search_info.blk_skip,
+             sizeof(x->txfm_search_info.blk_skip[0]) * ctx->num_4x4_blk);
       av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
     }
   }
diff --git a/av1/encoder/nonrd_pickmode.c b/av1/encoder/nonrd_pickmode.c
index 0dcb3a0..93528e3 100644
--- a/av1/encoder/nonrd_pickmode.c
+++ b/av1/encoder/nonrd_pickmode.c
@@ -918,19 +918,21 @@
 static void store_coding_context(MACROBLOCK *x, PICK_MODE_CONTEXT *ctx) {
 #endif  // CONFIG_INTERNAL_STATS
   MACROBLOCKD *const xd = &x->e_mbd;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
 
   // Take a snapshot of the coding context so it can be
   // restored if we decide to encode this way
-  ctx->rd_stats.skip_txfm = x->skip_txfm;
+  ctx->rd_stats.skip_txfm = txfm_info->skip_txfm;
+
   memset(ctx->blk_skip, 0, sizeof(ctx->blk_skip[0]) * ctx->num_4x4_blk);
   memset(ctx->tx_type_map, DCT_DCT,
          sizeof(ctx->tx_type_map[0]) * ctx->num_4x4_blk);
-  ctx->skippable = x->skip_txfm;
+  ctx->skippable = txfm_info->skip_txfm;
 #if CONFIG_INTERNAL_STATS
   ctx->best_mode_index = mode_index;
 #endif  // CONFIG_INTERNAL_STATS
   ctx->mic = *xd->mi[0];
-  ctx->skippable = x->skip_txfm;
+  ctx->skippable = txfm_info->skip_txfm;
   av1_copy_mbmi_ext_to_mbmi_ext_frame(&ctx->mbmi_ext_best, x->mbmi_ext,
                                       av1_ref_frame_type(xd->mi[0]->ref_frame));
   ctx->comp_pred_diff = 0;
@@ -1738,6 +1740,7 @@
   struct buf_2d orig_dst = pd->dst;
   const CommonQuantParams *quant_params = &cm->quant_params;
   const TxfmSearchParams *txfm_params = &x->txfm_search_params;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
 #if COLLECT_PICK_MODE_STAT
   aom_usec_timer_start(&ms_stat.timer2);
 #endif
@@ -1768,7 +1771,7 @@
     tmp[3].in_use = 0;
   }
 
-  x->skip_txfm = 0;
+  txfm_info->skip_txfm = 0;
 
   // Instead of using av1_get_pred_context_switchable_interp(xd) to assign
   // filter_ref, we use a less strict condition on assigning filter_ref.
@@ -2107,7 +2110,7 @@
       if (reuse_inter_pred) free_pred_buffer(this_mode_pred);
     }
     if (best_early_term && idx > 0) {
-      x->skip_txfm = 1;
+      txfm_info->skip_txfm = 1;
       break;
     }
   }
@@ -2119,7 +2122,7 @@
   mi->ref_frame[0] = best_pickmode.best_ref_frame;
   mi->mv[0].as_int =
       frame_mv[best_pickmode.best_mode][best_pickmode.best_ref_frame].as_int;
-  x->skip_txfm = best_rdc.skip_txfm;
+  txfm_info->skip_txfm = best_rdc.skip_txfm;
 
   // Perform intra prediction search, if the best SAD is above a certain
   // threshold.
diff --git a/av1/encoder/rd.h b/av1/encoder/rd.h
index 4cf3816..32aea44 100644
--- a/av1/encoder/rd.h
+++ b/av1/encoder/rd.h
@@ -310,7 +310,7 @@
 }
 
 // Used to reset the state of tx/mb rd hash information
-static INLINE void reset_hash_records(MACROBLOCK *const x,
+static INLINE void reset_hash_records(TxfmSearchInfo *const txfm_info,
                                       int use_inter_txb_hash) {
   int32_t record_idx;
 
@@ -318,27 +318,28 @@
   if (use_inter_txb_hash) {
     for (record_idx = 0;
          record_idx < ((MAX_MIB_SIZE >> 1) * (MAX_MIB_SIZE >> 1)); record_idx++)
-      x->txb_rd_record_8X8[record_idx].num =
-          x->txb_rd_record_8X8[record_idx].index_start = 0;
+      txfm_info->txb_rd_record_8X8[record_idx].num =
+          txfm_info->txb_rd_record_8X8[record_idx].index_start = 0;
     for (record_idx = 0;
          record_idx < ((MAX_MIB_SIZE >> 2) * (MAX_MIB_SIZE >> 2)); record_idx++)
-      x->txb_rd_record_16X16[record_idx].num =
-          x->txb_rd_record_16X16[record_idx].index_start = 0;
+      txfm_info->txb_rd_record_16X16[record_idx].num =
+          txfm_info->txb_rd_record_16X16[record_idx].index_start = 0;
     for (record_idx = 0;
          record_idx < ((MAX_MIB_SIZE >> 3) * (MAX_MIB_SIZE >> 3)); record_idx++)
-      x->txb_rd_record_32X32[record_idx].num =
-          x->txb_rd_record_32X32[record_idx].index_start = 0;
+      txfm_info->txb_rd_record_32X32[record_idx].num =
+          txfm_info->txb_rd_record_32X32[record_idx].index_start = 0;
     for (record_idx = 0;
          record_idx < ((MAX_MIB_SIZE >> 4) * (MAX_MIB_SIZE >> 4)); record_idx++)
-      x->txb_rd_record_64X64[record_idx].num =
-          x->txb_rd_record_64X64[record_idx].index_start = 0;
+      txfm_info->txb_rd_record_64X64[record_idx].num =
+          txfm_info->txb_rd_record_64X64[record_idx].index_start = 0;
   }
 
   // Reset the state for use_intra_txb_hash
-  x->txb_rd_record_intra.num = x->txb_rd_record_intra.index_start = 0;
+  txfm_info->txb_rd_record_intra.num =
+      txfm_info->txb_rd_record_intra.index_start = 0;
 
   // Reset the state for use_mb_rd_hash
-  x->mb_rd_record.num = x->mb_rd_record.index_start = 0;
+  txfm_info->mb_rd_record.num = txfm_info->mb_rd_record.index_start = 0;
 }
 
 void av1_setup_pred_block(const MACROBLOCKD *xd,
diff --git a/av1/encoder/rdopt.c b/av1/encoder/rdopt.c
index 655d0de..8588928 100644
--- a/av1/encoder/rdopt.c
+++ b/av1/encoder/rdopt.c
@@ -901,7 +901,7 @@
 
   // Take a snapshot of the coding context so it can be
   // restored if we decide to encode this way
-  ctx->rd_stats.skip_txfm = x->skip_txfm;
+  ctx->rd_stats.skip_txfm = x->txfm_search_info.skip_txfm;
   ctx->skippable = skippable;
 #if CONFIG_INTERNAL_STATS
   ctx->best_mode_index = mode_index;
@@ -1232,6 +1232,7 @@
     int do_tx_search, InterModesInfo *inter_modes_info, int eval_motion_mode) {
   const AV1_COMMON *const cm = &cpi->common;
   const FeatureFlags *const features = &cm->features;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   const int num_planes = av1_num_planes(cm);
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = xd->mi[0];
@@ -1326,7 +1327,7 @@
             best_rd_stats_y = simple_states->rd_stats_y;
             best_rd_stats_uv = simple_states->rd_stats_uv;
             memcpy(best_blk_skip, simple_states->blk_skip,
-                   sizeof(x->blk_skip[0]) * xd->height * xd->width);
+                   sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
             av1_copy_array(best_tx_type_map, simple_states->tx_type_map,
                            xd->height * xd->width);
             best_xskip_txfm = simple_states->skip_txfm;
@@ -1428,7 +1429,7 @@
     // current mode
     if (!av1_check_newmv_joint_nonzero(cm, x)) continue;
 
-    x->skip_txfm = 0;
+    txfm_info->skip_txfm = 0;
     rd_stats->dist = 0;
     rd_stats->sse = 0;
     rd_stats->skip_txfm = 1;
@@ -1559,8 +1560,8 @@
         simple_states->rd_stats.rdcost = tmp_rd;
         simple_states->rd_stats_y = *rd_stats_y;
         simple_states->rd_stats_uv = *rd_stats_uv;
-        memcpy(simple_states->blk_skip, x->blk_skip,
-               sizeof(x->blk_skip[0]) * xd->height * xd->width);
+        memcpy(simple_states->blk_skip, txfm_info->blk_skip,
+               sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
         av1_copy_array(simple_states->tx_type_map, xd->tx_type_map,
                        xd->height * xd->width);
         simple_states->skip_txfm = mbmi->skip_txfm;
@@ -1574,8 +1575,8 @@
       best_rd_stats_y = *rd_stats_y;
       best_rate_mv = tmp_rate_mv;
       if (num_planes > 1) best_rd_stats_uv = *rd_stats_uv;
-      memcpy(best_blk_skip, x->blk_skip,
-             sizeof(x->blk_skip[0]) * xd->height * xd->width);
+      memcpy(best_blk_skip, txfm_info->blk_skip,
+             sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
       av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->height * xd->width);
       best_xskip_txfm = mbmi->skip_txfm;
       best_disable_skip_txfm = *disable_skip_txfm;
@@ -1595,10 +1596,10 @@
   *rd_stats = best_rd_stats;
   *rd_stats_y = best_rd_stats_y;
   if (num_planes > 1) *rd_stats_uv = best_rd_stats_uv;
-  memcpy(x->blk_skip, best_blk_skip,
-         sizeof(x->blk_skip[0]) * xd->height * xd->width);
+  memcpy(txfm_info->blk_skip, best_blk_skip,
+         sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
   av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
-  x->skip_txfm = best_xskip_txfm;
+  txfm_info->skip_txfm = best_xskip_txfm;
   *disable_skip_txfm = best_disable_skip_txfm;
 
   restore_dst_buf(xd, *orig_dst, num_planes);
@@ -2378,6 +2379,7 @@
   MACROBLOCKD *xd = &x->e_mbd;
   MB_MODE_INFO *mbmi = xd->mi[0];
   MB_MODE_INFO_EXT *const mbmi_ext = x->mbmi_ext;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   const int is_comp_pred = has_second_ref(mbmi);
   const PREDICTION_MODE this_mode = mbmi->mode;
 
@@ -2659,8 +2661,8 @@
         best_rd = tmp_rd;
         best_mbmi = *mbmi;
         best_disable_skip_txfm = *disable_skip_txfm;
-        best_xskip_txfm = x->skip_txfm;
-        memcpy(best_blk_skip, x->blk_skip,
+        best_xskip_txfm = txfm_info->skip_txfm;
+        memcpy(best_blk_skip, txfm_info->blk_skip,
                sizeof(best_blk_skip[0]) * xd->height * xd->width);
         av1_copy_array(best_tx_type_map, xd->tx_type_map,
                        xd->height * xd->width);
@@ -2684,10 +2686,10 @@
   *rd_stats_uv = best_rd_stats_uv;
   *mbmi = best_mbmi;
   *disable_skip_txfm = best_disable_skip_txfm;
-  x->skip_txfm = best_xskip_txfm;
+  txfm_info->skip_txfm = best_xskip_txfm;
   assert(IMPLIES(mbmi->comp_group_idx == 1,
                  mbmi->interinter_comp.type != COMPOUND_AVERAGE));
-  memcpy(x->blk_skip, best_blk_skip,
+  memcpy(txfm_info->blk_skip, best_blk_skip,
          sizeof(best_blk_skip[0]) * xd->height * xd->width);
   av1_copy_array(xd->tx_type_map, best_tx_type_map, xd->height * xd->width);
 
@@ -2707,6 +2709,8 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   const TileInfo *tile = &xd->tile;
   MB_MODE_INFO *mbmi = xd->mi[0];
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
+
   const int mi_row = xd->mi_row;
   const int mi_col = xd->mi_col;
   const int w = block_size_wide[bsize];
@@ -2865,15 +2869,15 @@
       best_rd = rd_stats_yuv.rdcost;
       best_mbmi = *mbmi;
       best_rdstats = rd_stats_yuv;
-      memcpy(best_blk_skip, x->blk_skip,
-             sizeof(x->blk_skip[0]) * xd->height * xd->width);
+      memcpy(best_blk_skip, txfm_info->blk_skip,
+             sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
       av1_copy_array(best_tx_type_map, xd->tx_type_map, xd->height * xd->width);
     }
   }
   *mbmi = best_mbmi;
   *rd_stats = best_rdstats;
-  memcpy(x->blk_skip, best_blk_skip,
-         sizeof(x->blk_skip[0]) * xd->height * xd->width);
+  memcpy(txfm_info->blk_skip, best_blk_skip,
+         sizeof(txfm_info->blk_skip[0]) * xd->height * xd->width);
   av1_copy_array(xd->tx_type_map, best_tx_type_map, ctx->num_4x4_blk);
 #if CONFIG_RD_DEBUG
   mbmi->rd_stats = *rd_stats;
@@ -2888,6 +2892,7 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
   const int num_planes = av1_num_planes(cm);
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   int rate_y = 0, rate_uv = 0, rate_y_tokenonly = 0, rate_uv_tokenonly = 0;
   int y_skip_txfm = 0, uv_skip_txfm = 0;
   int64_t dist_y = 0, dist_uv = 0;
@@ -2912,8 +2917,8 @@
     xd->cfl.store_y = store_cfl_required_rdo(cm, x);
     if (xd->cfl.store_y) {
       // Restore reconstructed luma values.
-      memcpy(x->blk_skip, ctx->blk_skip,
-             sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+      memcpy(txfm_info->blk_skip, ctx->blk_skip,
+             sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
       av1_copy_array(xd->tx_type_map, ctx->tx_type_map, ctx->num_4x4_blk);
       av1_encode_intra_block_plane(cpi, x, bsize, AOM_PLANE_Y, DRY_RUN_NORMAL,
                                    cpi->optimize_seg_arr[mbmi->segment_id]);
@@ -2944,8 +2949,8 @@
     best_rd = rd_cost->rdcost;
   if (rd_pick_intrabc_mode_sb(cpi, x, ctx, rd_cost, bsize, best_rd) < best_rd) {
     ctx->rd_stats.skip_txfm = mbmi->skip_txfm;
-    memcpy(ctx->blk_skip, x->blk_skip,
-           sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+    memcpy(ctx->blk_skip, txfm_info->blk_skip,
+           sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
     assert(rd_cost->rate != INT_MAX);
   }
   if (rd_cost->rate == INT_MAX) return;
@@ -3116,7 +3121,7 @@
     search_state->best_skip2 = 1;
     search_state->best_mode_skippable = 1;
 
-    x->skip_txfm = 1;
+    x->txfm_search_info.skip_txfm = 1;
   }
 }
 
@@ -3161,6 +3166,7 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
   TxfmSearchParams *txfm_params = &x->txfm_search_params;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   int64_t best_rd;
   const int num_planes = av1_num_planes(cm);
 
@@ -3226,7 +3232,7 @@
           memset(mbmi->inter_tx_size, mbmi->tx_size,
                  sizeof(mbmi->inter_tx_size));
           for (int i = 0; i < xd->height * xd->width; ++i)
-            set_blk_skip(x, 0, i, rd_stats_y.skip_txfm);
+            set_blk_skip(txfm_info->blk_skip, 0, i, rd_stats_y.skip_txfm);
         }
       } else {
         av1_pick_uniform_tx_size_type_yrd(cpi, x, &rd_stats_y, bsize,
@@ -3262,7 +3268,7 @@
       if (best_rd > this_rd) {
         *best_mbmode = *mbmi;
         *best_mode_index = winner_mode_index;
-        av1_copy_array(ctx->blk_skip, x->blk_skip, ctx->num_4x4_blk);
+        av1_copy_array(ctx->blk_skip, txfm_info->blk_skip, ctx->num_4x4_blk);
         av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
         rd_cost->rate = this_rate;
         rd_cost->dist = rd_stats_y.dist + rd_stats_uv.dist;
@@ -4222,6 +4228,7 @@
   const int mode_is_intra =
       (av1_mode_defs[new_best_mode].mode < INTRA_MODE_END);
   const int skip_txfm = mbmi->skip_txfm && !mode_is_intra;
+  const TxfmSearchInfo *txfm_info = &x->txfm_search_info;
 
   search_state->best_rd = new_best_rd_stats->rdcost;
   search_state->best_mode_index = new_best_mode;
@@ -4231,7 +4238,7 @@
   search_state->best_mode_skippable = new_best_rd_stats->skip_txfm;
   // When !txfm_search_done, new_best_rd_stats won't provide correct rate_y and
   // rate_uv because av1_txfm_search process is replaced by rd estimation.
-  // Therfore, we should avoid updating best_rate_y and best_rate_uv here.
+  // Therefore, we should avoid updating best_rate_y and best_rate_uv here.
   // These two values will be updated when av1_txfm_search is called.
   if (txfm_search_done) {
     search_state->best_rate_y =
@@ -4239,7 +4246,8 @@
         x->skip_txfm_cost[skip_ctx][new_best_rd_stats->skip_txfm || skip_txfm];
     search_state->best_rate_uv = new_best_rd_stats_uv->rate;
   }
-  memcpy(ctx->blk_skip, x->blk_skip, sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+  memcpy(ctx->blk_skip, txfm_info->blk_skip,
+         sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
   av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
 }
 
@@ -4304,7 +4312,7 @@
     // Continue if the best candidate is compound.
     if (!is_inter_singleref_mode(mbmi->mode)) continue;
 
-    x->skip_txfm = 0;
+    x->txfm_search_info.skip_txfm = 0;
     const int mode_index = get_prediction_mode_idx(
         mbmi->mode, mbmi->ref_frame[0], mbmi->ref_frame[1]);
     struct macroblockd_plane *p = xd->plane;
@@ -4555,6 +4563,7 @@
   const SPEED_FEATURES *const sf = &cpi->sf;
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   int i;
   const int *comp_inter_cost =
       x->comp_inter_cost[av1_get_reference_mode_context(xd)];
@@ -4759,7 +4768,7 @@
 
     init_mbmi(mbmi, this_mode, ref_frames, cm);
 
-    x->skip_txfm = 0;
+    txfm_info->skip_txfm = 0;
     set_ref_ptrs(cm, xd, ref_frame, second_ref_frame);
 
     // Apply speed features to decide if this inter mode can be skipped
@@ -4891,7 +4900,7 @@
       int64_t curr_est_rd = inter_modes_info->est_rd_arr[data_idx];
       if (curr_est_rd * 0.80 > top_est_rd) break;
 
-      x->skip_txfm = 0;
+      txfm_info->skip_txfm = 0;
       set_ref_ptrs(cm, xd, mbmi->ref_frame[0], mbmi->ref_frame[1]);
 
       // Select prediction reference frames.
@@ -5004,7 +5013,7 @@
     assert(av1_mode_defs[mode_enum].ref_frame[0] == INTRA_FRAME);
     assert(av1_mode_defs[mode_enum].ref_frame[1] == NONE_FRAME);
     init_mbmi(mbmi, this_mode, av1_mode_defs[mode_enum].ref_frame, cm);
-    x->skip_txfm = 0;
+    txfm_info->skip_txfm = 0;
 
     if (this_mode != DC_PRED) {
       // Only search the oblique modes if the best so far is
@@ -5079,8 +5088,8 @@
       search_state.best_mbmode = *mbmi;
       search_state.best_skip2 = 0;
       search_state.best_mode_skippable = this_skippable;
-      memcpy(ctx->blk_skip, x->blk_skip,
-             sizeof(x->blk_skip[0]) * ctx->num_4x4_blk);
+      memcpy(ctx->blk_skip, txfm_info->blk_skip,
+             sizeof(txfm_info->blk_skip[0]) * ctx->num_4x4_blk);
       av1_copy_array(ctx->tx_type_map, xd->tx_type_map, ctx->num_4x4_blk);
     }
   }
@@ -5129,7 +5138,7 @@
 
   // macroblock modes
   *mbmi = search_state.best_mbmode;
-  x->skip_txfm |= search_state.best_skip2;
+  txfm_info->skip_txfm |= search_state.best_skip2;
 
   // Note: this section is needed since the mode may have been forced to
   // GLOBALMV by the all-zero mode handling of ref-mv.
@@ -5153,7 +5162,7 @@
     }
   }
 
-  x->skip_txfm |= search_state.best_mode_skippable;
+  txfm_info->skip_txfm |= search_state.best_mode_skippable;
 
   assert(search_state.best_mode_index != THR_INVALID);
 
@@ -5226,7 +5235,7 @@
                            mi_row, features->cur_frame_force_integer_mv)
           .as_int;
   mbmi->tx_size = max_txsize_lookup[bsize];
-  x->skip_txfm = 1;
+  x->txfm_search_info.skip_txfm = 1;
 
   mbmi->ref_mv_idx = 0;
 
diff --git a/av1/encoder/rdopt_utils.h b/av1/encoder/rdopt_utils.h
index 752a0b8..3e2c267 100644
--- a/av1/encoder/rdopt_utils.h
+++ b/av1/encoder/rdopt_utils.h
@@ -467,6 +467,7 @@
   const SPEED_FEATURES *sf = &cpi->sf;
   const WinnerModeParams *winner_mode_params = &cpi->winner_mode_params;
   TxfmSearchParams *txfm_params = &x->txfm_search_params;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
 
   switch (mode_eval_type) {
     case DEFAULT_EVAL:
@@ -543,7 +544,7 @@
       // the decisions would have been sub-optimal
       // TODO(any): Move the evaluation of palette/IntraBC modes before winner
       // mode is processed and clean-up the code below
-      reset_hash_records(x, cpi->sf.tx_sf.use_inter_txb_hash);
+      reset_hash_records(txfm_info, cpi->sf.tx_sf.use_inter_txb_hash);
 
       break;
     default: assert(0);
diff --git a/av1/encoder/tx_search.c b/av1/encoder/tx_search.c
index 7aeda66..808f44c 100644
--- a/av1/encoder/tx_search.c
+++ b/av1/encoder/tx_search.c
@@ -252,10 +252,11 @@
 // the form of a quadtree for easier access in actual TX size search.
 static int find_tx_size_rd_records(MACROBLOCK *x, BLOCK_SIZE bsize,
                                    TXB_RD_INFO_NODE *dst_rd_info) {
-  TXB_RD_RECORD *rd_records_table[4] = { x->txb_rd_record_8X8,
-                                         x->txb_rd_record_16X16,
-                                         x->txb_rd_record_32X32,
-                                         x->txb_rd_record_64X64 };
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
+  TXB_RD_RECORD *rd_records_table[4] = { txfm_info->txb_rd_record_8X8,
+                                         txfm_info->txb_rd_record_16X16,
+                                         txfm_info->txb_rd_record_32X32,
+                                         txfm_info->txb_rd_record_64X64 };
   const TX_SIZE max_square_tx_size = max_txsize_lookup[bsize];
   const int bw = block_size_wide[bsize];
   const int bh = block_size_high[bsize];
@@ -301,9 +302,9 @@
             cur_hash_row += cur_tx_bw;
             cur_diff_row += diff_stride;
           }
-          const int hash = av1_get_crc32c_value(&x->mb_rd_record.crc_calculator,
-                                                (uint8_t *)hash_data,
-                                                2 * cur_tx_bw * cur_tx_bh);
+          const int hash = av1_get_crc32c_value(
+              &txfm_info->mb_rd_record.crc_calculator, (uint8_t *)hash_data,
+              2 * cur_tx_bw * cur_tx_bh);
           // Find corresponding RD info based on the hash value.
           const int record_idx =
               row_in_sb * (MAX_MIB_SIZE >> (tx_size_idx + 1)) + col_in_sb;
@@ -325,8 +326,9 @@
   const int rows = block_size_high[bsize];
   const int cols = block_size_wide[bsize];
   const int16_t *diff = x->plane[0].src_diff;
-  const uint32_t hash = av1_get_crc32c_value(&x->mb_rd_record.crc_calculator,
-                                             (uint8_t *)diff, 2 * rows * cols);
+  const uint32_t hash =
+      av1_get_crc32c_value(&x->txfm_search_info.mb_rd_record.crc_calculator,
+                           (uint8_t *)diff, 2 * rows * cols);
   return (hash << 5) + bsize;
 }
 
@@ -355,7 +357,7 @@
   MACROBLOCKD *const xd = &x->e_mbd;
   MB_MODE_INFO *const mbmi = xd->mi[0];
   mbmi->tx_size = tx_rd_info->tx_size;
-  memcpy(x->blk_skip, tx_rd_info->blk_skip,
+  memcpy(x->txfm_search_info.blk_skip, tx_rd_info->blk_skip,
          sizeof(tx_rd_info->blk_skip[0]) * n4);
   av1_copy(mbmi->inter_tx_size, tx_rd_info->inter_tx_size);
   av1_copy_array(xd->tx_type_map, tx_rd_info->tx_type_map, n4);
@@ -463,7 +465,8 @@
   memset(xd->tx_type_map, DCT_DCT, sizeof(xd->tx_type_map[0]) * n4);
   memset(mbmi->inter_tx_size, tx_size, sizeof(mbmi->inter_tx_size));
   mbmi->tx_size = tx_size;
-  for (int i = 0; i < n4; ++i) set_blk_skip(x, 0, i, 1);
+  for (int i = 0; i < n4; ++i)
+    set_blk_skip(x->txfm_search_info.blk_skip, 0, i, 1);
   rd_stats->skip_txfm = 1;
   if (is_cur_buf_hbd(xd)) dist = ROUND_POWER_OF_TWO(dist, (xd->bd - 8) * 2);
   rd_stats->dist = rd_stats->sse = (dist << 4);
@@ -512,7 +515,7 @@
   const MB_MODE_INFO *const mbmi = xd->mi[0];
   tx_rd_info->hash_value = hash;
   tx_rd_info->tx_size = mbmi->tx_size;
-  memcpy(tx_rd_info->blk_skip, x->blk_skip,
+  memcpy(tx_rd_info->blk_skip, x->txfm_search_info.blk_skip,
          sizeof(tx_rd_info->blk_skip[0]) * n4);
   av1_copy(tx_rd_info->inter_tx_size, mbmi->inter_tx_size);
   av1_copy_array(tx_rd_info->tx_type_map, xd->tx_type_map, n4);
@@ -1248,7 +1251,7 @@
     }
     hash_data = (uint8_t *)tmp_data;
   }
-  CRC32C *crc = &x->mb_rd_record.crc_calculator;
+  CRC32C *crc = &x->txfm_search_info.mb_rd_record.crc_calculator;
   const uint32_t hash = av1_get_crc32c_value(crc, hash_data, 2 * txb_w * txb_h);
   return (hash << 5) + tx_size;
 }
@@ -1265,17 +1268,19 @@
                                       const int tx_type_map_idx,
                                       uint16_t *cur_joint_ctx) {
   MACROBLOCKD *xd = &x->e_mbd;
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   assert(cpi->sf.tx_sf.use_intra_txb_hash &&
          frame_is_intra_only(&cpi->common) && !is_inter_block(xd->mi[0]) &&
          plane == 0 && tx_size_wide[tx_size] == tx_size_high[tx_size]);
   const uint32_t intra_hash =
       get_intra_txb_hash(x, plane, blk_row, blk_col, plane_bsize, tx_size);
   const int intra_hash_idx =
-      find_tx_size_rd_info(&x->txb_rd_record_intra, intra_hash);
-  *intra_txb_rd_info = &x->txb_rd_record_intra.tx_rd_info[intra_hash_idx];
+      find_tx_size_rd_info(&txfm_info->txb_rd_record_intra, intra_hash);
+  *intra_txb_rd_info =
+      &txfm_info->txb_rd_record_intra.tx_rd_info[intra_hash_idx];
   *cur_joint_ctx = (txb_ctx->dc_sign_ctx << 8) + txb_ctx->txb_skip_ctx;
   if ((*intra_txb_rd_info)->entropy_context == *cur_joint_ctx &&
-      x->txb_rd_record_intra.tx_rd_info[intra_hash_idx].valid) {
+      txfm_info->txb_rd_record_intra.tx_rd_info[intra_hash_idx].valid) {
     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,
@@ -2509,7 +2514,8 @@
     update_txk_array(xd, blk_row, blk_col, tx_size, DCT_DCT);
   }
   rd_stats->skip_txfm = pick_skip_txfm;
-  set_blk_skip(x, 0, blk_row * bw + blk_col, pick_skip_txfm);
+  set_blk_skip(x->txfm_search_info.blk_skip, 0, blk_row * bw + blk_col,
+               pick_skip_txfm);
 
   if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH)
     rd_stats->rate += x->txfm_partition_cost[txfm_partition_ctx][0];
@@ -2663,7 +2669,8 @@
     mbmi->tx_size = tx_size;
     update_txk_array(xd, blk_row, blk_col, tx_size, no_split.tx_type);
     const int bw = mi_size_wide[plane_bsize];
-    set_blk_skip(x, 0, blk_row * bw + blk_col, rd_stats->skip_txfm);
+    set_blk_skip(x->txfm_search_info.blk_skip, 0, blk_row * bw + blk_col,
+                 rd_stats->skip_txfm);
   } else {
     *rd_stats = split_rd_stats;
     if (split_rd_stats.rdcost == INT64_MAX) *is_cost_valid = 0;
@@ -2774,6 +2781,7 @@
   const int num_blks = bsize_to_num_blk(bs);
   x->rd_model = FULL_TXFM_RD;
   int64_t rd[MAX_TX_DEPTH + 1] = { INT64_MAX, INT64_MAX, INT64_MAX };
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   for (int tx_size = start_tx, depth = init_depth; depth <= MAX_TX_DEPTH;
        depth++, tx_size = sub_tx_size_map[tx_size]) {
     if (!cpi->oxcf.enable_tx64 && txsize_sqr_up_map[tx_size] == TX_64X64) {
@@ -2784,7 +2792,7 @@
     rd[depth] = av1_uniform_txfm_yrd(cpi, x, &this_rd_stats, ref_best_rd, bs,
                                      tx_size, FTXS_NONE, skip_trellis);
     if (rd[depth] < best_rd) {
-      av1_copy_array(best_blk_skip, x->blk_skip, num_blks);
+      av1_copy_array(best_blk_skip, txfm_info->blk_skip, num_blks);
       av1_copy_array(best_txk_type_map, xd->tx_type_map, num_blks);
       best_tx_size = tx_size;
       best_rd = rd[depth];
@@ -2802,7 +2810,7 @@
   if (rd_stats->rate != INT_MAX) {
     mbmi->tx_size = best_tx_size;
     av1_copy_array(xd->tx_type_map, best_txk_type_map, num_blks);
-    av1_copy_array(x->blk_skip, best_blk_skip, num_blks);
+    av1_copy_array(txfm_info->blk_skip, best_blk_skip, num_blks);
   }
 }
 
@@ -2852,10 +2860,13 @@
 
   const int blk_idx =
       blk_row * (block_size_wide[plane_bsize] >> MI_SIZE_LOG2) + blk_col;
+
+  TxfmSearchInfo *txfm_info = &x->txfm_search_info;
   if (plane == 0)
-    set_blk_skip(x, plane, blk_idx, x->plane[plane].eobs[block] == 0);
+    set_blk_skip(txfm_info->blk_skip, plane, blk_idx,
+                 x->plane[plane].eobs[block] == 0);
   else
-    set_blk_skip(x, plane, blk_idx, 0);
+    set_blk_skip(txfm_info->blk_skip, plane, blk_idx, 0);
 
   int64_t rd;
   if (is_inter) {
@@ -2976,19 +2987,20 @@
     tx_type_rd(cpi, x, tx_size, blk_row, blk_col, block, plane_bsize, &txb_ctx,
                rd_stats, ftxs_mode, ref_best_rd, NULL);
     const int mi_width = mi_size_wide[plane_bsize];
+    TxfmSearchInfo *txfm_info = &x->txfm_search_info;
     if (RDCOST(x->rdmult, rd_stats->rate, rd_stats->dist) >=
             RDCOST(x->rdmult, zero_blk_rate, rd_stats->sse) ||
         rd_stats->skip_txfm == 1) {
       rd_stats->rate = zero_blk_rate;
       rd_stats->dist = rd_stats->sse;
       rd_stats->skip_txfm = 1;
-      set_blk_skip(x, 0, blk_row * mi_width + blk_col, 1);
+      set_blk_skip(txfm_info->blk_skip, 0, blk_row * mi_width + blk_col, 1);
       x->plane[0].eobs[block] = 0;
       x->plane[0].txb_entropy_ctx[block] = 0;
       update_txk_array(xd, blk_row, blk_col, tx_size, DCT_DCT);
     } else {
       rd_stats->skip_txfm = 0;
-      set_blk_skip(x, 0, blk_row * mi_width + blk_col, 0);
+      set_blk_skip(txfm_info->blk_skip, 0, blk_row * mi_width + blk_col, 0);
     }
     if (tx_size > TX_4X4 && depth < MAX_VARTX_DEPTH)
       rd_stats->rate += x->txfm_partition_cost[ctx][0];
@@ -3259,7 +3271,7 @@
   const int n4 = bsize_to_num_blk(bsize);
   if (is_mb_rd_hash_enabled) {
     hash = get_block_residue_hash(x, bsize);
-    mb_rd_record = &x->mb_rd_record;
+    mb_rd_record = &x->txfm_search_info.mb_rd_record;
     const int match_index = find_mb_rd_info(mb_rd_record, ref_best_rd, hash);
     if (match_index != -1) {
       MB_RD_INFO *tx_rd_info = &mb_rd_record->tx_rd_info[match_index];
@@ -3281,7 +3293,7 @@
     return;
   }
 #if CONFIG_SPEED_STATS
-  ++x->tx_search_count;
+  ++x->txfm_search_info.tx_search_count;
 #endif  // CONFIG_SPEED_STATS
 
   // Pre-compute residue hashes (transform block level) and find existing or
@@ -3346,7 +3358,7 @@
         (mi_col + mi_size_wide[bs] < xd->tile.mi_col_end);
     if (within_border) {
       hash = get_block_residue_hash(x, bs);
-      mb_rd_record = &x->mb_rd_record;
+      mb_rd_record = &x->txfm_search_info.mb_rd_record;
       const int match_index = find_mb_rd_info(mb_rd_record, ref_best_rd, hash);
       if (match_index != -1) {
         MB_RD_INFO *tx_rd_info = &mb_rd_record->tx_rd_info[match_index];
@@ -3543,7 +3555,7 @@
     av1_pick_uniform_tx_size_type_yrd(cpi, x, rd_stats_y, bsize, rd_thresh);
     memset(mbmi->inter_tx_size, mbmi->tx_size, sizeof(mbmi->inter_tx_size));
     for (int i = 0; i < xd->height * xd->width; ++i)
-      set_blk_skip(x, 0, i, rd_stats_y->skip_txfm);
+      set_blk_skip(x->txfm_search_info.blk_skip, 0, i, rd_stats_y->skip_txfm);
   }
 
   if (rd_stats_y->rate == INT_MAX) return 0;