Refactor CommmonContexts from AV1_COMMON

Also, add documentation for the members.

BUG=aomedia:2610

Change-Id: I07b49e61730ac4be7a5d4db228c0026e2d7b9bea
diff --git a/av1/common/alloccommon.c b/av1/common/alloccommon.c
index 2addde9..badee3d 100644
--- a/av1/common/alloccommon.c
+++ b/av1/common/alloccommon.c
@@ -132,86 +132,85 @@
   aom_free_frame_buffer(&cm->rst_frame);
 }
 
-void av1_free_above_context_buffers(AV1_COMMON *cm,
-                                    int num_free_above_contexts) {
+void av1_free_above_context_buffers(CommonContexts *above_contexts) {
   int i;
-  const int num_planes = cm->num_allocated_above_context_planes;
+  const int num_planes = above_contexts->num_planes;
 
-  for (int tile_row = 0; tile_row < num_free_above_contexts; tile_row++) {
+  for (int tile_row = 0; tile_row < above_contexts->num_tile_rows; tile_row++) {
     for (i = 0; i < num_planes; i++) {
-      aom_free(cm->above_context[i][tile_row]);
-      cm->above_context[i][tile_row] = NULL;
+      aom_free(above_contexts->entropy[i][tile_row]);
+      above_contexts->entropy[i][tile_row] = NULL;
     }
-    aom_free(cm->above_seg_context[tile_row]);
-    cm->above_seg_context[tile_row] = NULL;
+    aom_free(above_contexts->partition[tile_row]);
+    above_contexts->partition[tile_row] = NULL;
 
-    aom_free(cm->above_txfm_context[tile_row]);
-    cm->above_txfm_context[tile_row] = NULL;
+    aom_free(above_contexts->txfm[tile_row]);
+    above_contexts->txfm[tile_row] = NULL;
   }
   for (i = 0; i < num_planes; i++) {
-    aom_free(cm->above_context[i]);
-    cm->above_context[i] = NULL;
+    aom_free(above_contexts->entropy[i]);
+    above_contexts->entropy[i] = NULL;
   }
-  aom_free(cm->above_seg_context);
-  cm->above_seg_context = NULL;
+  aom_free(above_contexts->partition);
+  above_contexts->partition = NULL;
 
-  aom_free(cm->above_txfm_context);
-  cm->above_txfm_context = NULL;
+  aom_free(above_contexts->txfm);
+  above_contexts->txfm = NULL;
 
-  cm->num_allocated_above_contexts = 0;
-  cm->num_allocated_above_context_mi_col = 0;
-  cm->num_allocated_above_context_planes = 0;
+  above_contexts->num_tile_rows = 0;
+  above_contexts->num_mi_cols = 0;
+  above_contexts->num_planes = 0;
 }
 
 void av1_free_context_buffers(AV1_COMMON *cm) {
   cm->mi_params.free_mi(&cm->mi_params);
 
-  av1_free_above_context_buffers(cm, cm->num_allocated_above_contexts);
+  av1_free_above_context_buffers(&cm->above_contexts);
 
 #if CONFIG_LPF_MASK
   av1_free_loop_filter_mask(cm);
 #endif
 }
 
-int av1_alloc_above_context_buffers(AV1_COMMON *cm,
-                                    int num_alloc_above_contexts) {
-  const int num_planes = av1_num_planes(cm);
-  int plane_idx;
+int av1_alloc_above_context_buffers(CommonContexts *above_contexts,
+                                    int num_tile_rows, int num_mi_cols,
+                                    int num_planes) {
   const int aligned_mi_cols =
-      ALIGN_POWER_OF_TWO(cm->mi_params.mi_cols, MAX_MIB_SIZE_LOG2);
+      ALIGN_POWER_OF_TWO(num_mi_cols, MAX_MIB_SIZE_LOG2);
 
   // Allocate above context buffers
-  cm->num_allocated_above_contexts = num_alloc_above_contexts;
-  cm->num_allocated_above_context_mi_col = aligned_mi_cols;
-  cm->num_allocated_above_context_planes = num_planes;
-  for (plane_idx = 0; plane_idx < num_planes; plane_idx++) {
-    cm->above_context[plane_idx] = (ENTROPY_CONTEXT **)aom_calloc(
-        num_alloc_above_contexts, sizeof(cm->above_context[0]));
-    if (!cm->above_context[plane_idx]) return 1;
+  above_contexts->num_tile_rows = num_tile_rows;
+  above_contexts->num_mi_cols = aligned_mi_cols;
+  above_contexts->num_planes = num_planes;
+  for (int plane_idx = 0; plane_idx < num_planes; plane_idx++) {
+    above_contexts->entropy[plane_idx] = (ENTROPY_CONTEXT **)aom_calloc(
+        num_tile_rows, sizeof(above_contexts->entropy[0]));
+    if (!above_contexts->entropy[plane_idx]) return 1;
   }
 
-  cm->above_seg_context = (PARTITION_CONTEXT **)aom_calloc(
-      num_alloc_above_contexts, sizeof(cm->above_seg_context));
-  if (!cm->above_seg_context) return 1;
+  above_contexts->partition = (PARTITION_CONTEXT **)aom_calloc(
+      num_tile_rows, sizeof(above_contexts->partition));
+  if (!above_contexts->partition) return 1;
 
-  cm->above_txfm_context = (TXFM_CONTEXT **)aom_calloc(
-      num_alloc_above_contexts, sizeof(cm->above_txfm_context));
-  if (!cm->above_txfm_context) return 1;
+  above_contexts->txfm =
+      (TXFM_CONTEXT **)aom_calloc(num_tile_rows, sizeof(above_contexts->txfm));
+  if (!above_contexts->txfm) return 1;
 
-  for (int tile_row = 0; tile_row < num_alloc_above_contexts; tile_row++) {
-    for (plane_idx = 0; plane_idx < num_planes; plane_idx++) {
-      cm->above_context[plane_idx][tile_row] = (ENTROPY_CONTEXT *)aom_calloc(
-          aligned_mi_cols, sizeof(*cm->above_context[0][tile_row]));
-      if (!cm->above_context[plane_idx][tile_row]) return 1;
+  for (int tile_row = 0; tile_row < num_tile_rows; tile_row++) {
+    for (int plane_idx = 0; plane_idx < num_planes; plane_idx++) {
+      above_contexts->entropy[plane_idx][tile_row] =
+          (ENTROPY_CONTEXT *)aom_calloc(
+              aligned_mi_cols, sizeof(*above_contexts->entropy[0][tile_row]));
+      if (!above_contexts->entropy[plane_idx][tile_row]) return 1;
     }
 
-    cm->above_seg_context[tile_row] = (PARTITION_CONTEXT *)aom_calloc(
-        aligned_mi_cols, sizeof(*cm->above_seg_context[tile_row]));
-    if (!cm->above_seg_context[tile_row]) return 1;
+    above_contexts->partition[tile_row] = (PARTITION_CONTEXT *)aom_calloc(
+        aligned_mi_cols, sizeof(*above_contexts->partition[tile_row]));
+    if (!above_contexts->partition[tile_row]) return 1;
 
-    cm->above_txfm_context[tile_row] = (TXFM_CONTEXT *)aom_calloc(
-        aligned_mi_cols, sizeof(*cm->above_txfm_context[tile_row]));
-    if (!cm->above_txfm_context[tile_row]) return 1;
+    above_contexts->txfm[tile_row] = (TXFM_CONTEXT *)aom_calloc(
+        aligned_mi_cols, sizeof(*above_contexts->txfm[tile_row]));
+    if (!above_contexts->txfm[tile_row]) return 1;
   }
 
   return 0;
diff --git a/av1/common/alloccommon.h b/av1/common/alloccommon.h
index f9d9166..fe8e0c5 100644
--- a/av1/common/alloccommon.h
+++ b/av1/common/alloccommon.h
@@ -22,14 +22,15 @@
 
 struct AV1Common;
 struct BufferPool;
+struct CommonContexts;
 struct CommonModeInfoParams;
 
 void av1_remove_common(struct AV1Common *cm);
 
-int av1_alloc_above_context_buffers(struct AV1Common *cm,
-                                    int num_alloc_above_contexts);
-void av1_free_above_context_buffers(struct AV1Common *cm,
-                                    int num_free_above_contexts);
+int av1_alloc_above_context_buffers(struct CommonContexts *above_contexts,
+                                    int num_tile_rows, int num_mi_cols,
+                                    int num_planes);
+void av1_free_above_context_buffers(struct CommonContexts *above_contexts);
 int av1_alloc_context_buffers(struct AV1Common *cm, int width, int height);
 void av1_init_mi_buffers(struct CommonModeInfoParams *mi_params);
 void av1_free_context_buffers(struct AV1Common *cm);
diff --git a/av1/common/av1_common_int.h b/av1/common/av1_common_int.h
index e98e14b..bc64924 100644
--- a/av1/common/av1_common_int.h
+++ b/av1/common/av1_common_int.h
@@ -454,6 +454,34 @@
   int qm_v;
 };
 
+// Context used for transmitting various symbols in the bistream.
+typedef struct CommonContexts CommonContexts;
+struct CommonContexts {
+  // Context used by 'FRAME_CONTEXT.partition_cdf' to transmit partition type.
+  // partition[i][j] is the context for ith tile row, jth mi_col.
+  PARTITION_CONTEXT **partition;
+
+  // Context used to derive context for multiple symbols:
+  // - 'TXB_CTX.txb_skip_ctx' used by 'FRAME_CONTEXT.txb_skip_cdf' to transmit
+  // to transmit skip_txfm flag.
+  // - 'TXB_CTX.dc_sign_ctx' used by 'FRAME_CONTEXT.dc_sign_cdf' to transmit
+  // sign.
+  // entropy[i][j][k] is the context for ith plane, jth tile row, kth mi_col.
+  ENTROPY_CONTEXT **entropy[MAX_MB_PLANE];
+
+  // Context used to derive context for 'FRAME_CONTEXT.txfm_partition_cdf' to
+  // transmit 'is_split' flag to indicate if this transform block should be
+  // split into smaller sub-blocks.
+  // txfm[i][j] is the context for ith tile row, jth mi_col.
+  TXFM_CONTEXT **txfm;
+
+  // Dimensions that were used to allocate the arrays above.
+  // If these dimensions change, the arrays may have to be re-allocated.
+  int num_planes;     // Corresponds to av1_num_planes(cm)
+  int num_tile_rows;  // Corresponds to cm->tiles.row
+  int num_mi_cols;    // Corresponds to cm->mi_params.mi_cols
+};
+
 typedef struct AV1Common {
   // Information about the current frame that is being coded.
   CurrentFrame current_frame;
@@ -618,9 +646,12 @@
   // External BufferPool passed from outside.
   BufferPool *buffer_pool;
 
-  PARTITION_CONTEXT **above_seg_context;
-  ENTROPY_CONTEXT **above_context[MAX_MB_PLANE];
-  TXFM_CONTEXT **above_txfm_context;
+  // Above context buffers and their sizes.
+  // Note: above contexts are allocated in this struct, as their size is
+  // dependent on frame width, while left contexts are declared and allocated in
+  // MACROBLOCKD struct, as they have a fixed size.
+  CommonContexts above_contexts;
+
   int current_frame_id;
   int ref_frame_id[REF_FRAMES];
   TPL_MV_REF *tpl_mvs;
@@ -634,9 +665,6 @@
   int spatial_layer_id;
   unsigned int number_temporal_layers;
   unsigned int number_spatial_layers;
-  int num_allocated_above_context_mi_col;
-  int num_allocated_above_contexts;
-  int num_allocated_above_context_planes;
 
 #if TXCOEFF_TIMER
   int64_t cum_txcoeff_timer;
@@ -846,14 +874,14 @@
   return cm->seq_params.monochrome ? 1 : MAX_MB_PLANE;
 }
 
-static INLINE void av1_init_above_context(AV1_COMMON *cm, MACROBLOCKD *xd,
-                                          const int tile_row) {
-  const int num_planes = av1_num_planes(cm);
+static INLINE void av1_init_above_context(CommonContexts *above_contexts,
+                                          int num_planes, int tile_row,
+                                          MACROBLOCKD *xd) {
   for (int i = 0; i < num_planes; ++i) {
-    xd->above_context[i] = cm->above_context[i][tile_row];
+    xd->above_context[i] = above_contexts->entropy[i][tile_row];
   }
-  xd->above_seg_context = cm->above_seg_context[tile_row];
-  xd->above_txfm_context = cm->above_txfm_context[tile_row];
+  xd->above_seg_context = above_contexts->partition[tile_row];
+  xd->above_txfm_context = above_contexts->txfm[tile_row];
 }
 
 static INLINE void av1_init_macroblockd(AV1_COMMON *cm, MACROBLOCKD *xd,
@@ -1186,26 +1214,30 @@
   const int width = mi_col_end - mi_col_start;
   const int aligned_width =
       ALIGN_POWER_OF_TWO(width, seq_params->mib_size_log2);
-
   const int offset_y = mi_col_start;
   const int width_y = aligned_width;
   const int offset_uv = offset_y >> seq_params->subsampling_x;
   const int width_uv = width_y >> seq_params->subsampling_x;
+  CommonContexts *const above_contexts = &cm->above_contexts;
 
-  av1_zero_array(cm->above_context[0][tile_row] + offset_y, width_y);
+  av1_zero_array(above_contexts->entropy[0][tile_row] + offset_y, width_y);
   if (num_planes > 1) {
-    if (cm->above_context[1][tile_row] && cm->above_context[2][tile_row]) {
-      av1_zero_array(cm->above_context[1][tile_row] + offset_uv, width_uv);
-      av1_zero_array(cm->above_context[2][tile_row] + offset_uv, width_uv);
+    if (above_contexts->entropy[1][tile_row] &&
+        above_contexts->entropy[2][tile_row]) {
+      av1_zero_array(above_contexts->entropy[1][tile_row] + offset_uv,
+                     width_uv);
+      av1_zero_array(above_contexts->entropy[2][tile_row] + offset_uv,
+                     width_uv);
     } else {
       aom_internal_error(xd->error_info, AOM_CODEC_CORRUPT_FRAME,
                          "Invalid value of planes");
     }
   }
 
-  av1_zero_array(cm->above_seg_context[tile_row] + mi_col_start, aligned_width);
+  av1_zero_array(above_contexts->partition[tile_row] + mi_col_start,
+                 aligned_width);
 
-  memset(cm->above_txfm_context[tile_row] + mi_col_start,
+  memset(above_contexts->txfm[tile_row] + mi_col_start,
          tx_size_wide[TX_SIZES_LARGEST], aligned_width * sizeof(TXFM_CONTEXT));
 }
 
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 2e16afe..4541008 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -3072,7 +3072,8 @@
       }
 #endif
       av1_init_macroblockd(cm, &td->xd, NULL);
-      av1_init_above_context(cm, &td->xd, row);
+      av1_init_above_context(&cm->above_contexts, av1_num_planes(cm), row,
+                             &td->xd);
 
       // Initialise the tile context from the frame context
       tile_data->tctx = *cm->fc;
@@ -3144,7 +3145,8 @@
 #endif
   av1_init_macroblockd(cm, &td->xd, NULL);
   td->xd.error_info = &thread_data->error_info;
-  av1_init_above_context(cm, &td->xd, tile_row);
+  av1_init_above_context(&cm->above_contexts, av1_num_planes(cm), tile_row,
+                         &td->xd);
 
   // Initialise the tile context from the frame context
   tile_data->tctx = *cm->fc;
@@ -5184,13 +5186,17 @@
                      cm->seq_params.separate_uv_delta_q, rb);
   xd->bd = (int)seq_params->bit_depth;
 
-  if (cm->num_allocated_above_context_planes < av1_num_planes(cm) ||
-      cm->num_allocated_above_context_mi_col < cm->mi_params.mi_cols ||
-      cm->num_allocated_above_contexts < cm->tiles.rows) {
-    av1_free_above_context_buffers(cm, cm->num_allocated_above_contexts);
-    if (av1_alloc_above_context_buffers(cm, cm->tiles.rows))
+  CommonContexts *const above_contexts = &cm->above_contexts;
+  if (above_contexts->num_planes < av1_num_planes(cm) ||
+      above_contexts->num_mi_cols < cm->mi_params.mi_cols ||
+      above_contexts->num_tile_rows < cm->tiles.rows) {
+    av1_free_above_context_buffers(above_contexts);
+    if (av1_alloc_above_context_buffers(above_contexts, cm->tiles.rows,
+                                        cm->mi_params.mi_cols,
+                                        av1_num_planes(cm))) {
       aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
                          "Failed to allocate context buffers");
+    }
   }
 
   if (features->primary_ref_frame == PRIMARY_REF_NONE) {
diff --git a/av1/decoder/decodemv.c b/av1/decoder/decodemv.c
index dc987d1..d47868f 100644
--- a/av1/decoder/decodemv.c
+++ b/av1/decoder/decodemv.c
@@ -779,7 +779,7 @@
 
   const int mi_row = xd->mi_row;
   const int mi_col = xd->mi_col;
-  xd->above_txfm_context = cm->above_txfm_context[xd->tile.tile_row] + mi_col;
+  xd->above_txfm_context = cm->above_contexts.txfm[xd->tile.tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
 
@@ -1513,7 +1513,7 @@
   mbmi->current_qindex = xd->current_qindex;
 
   xd->above_txfm_context =
-      cm->above_txfm_context[xd->tile.tile_row] + xd->mi_col;
+      cm->above_contexts.txfm[xd->tile.tile_row] + xd->mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (xd->mi_row & MAX_MIB_MASK);
 
diff --git a/av1/encoder/bitstream.c b/av1/encoder/bitstream.c
index a7f1cf5..396731a 100644
--- a/av1/encoder/bitstream.c
+++ b/av1/encoder/bitstream.c
@@ -1487,7 +1487,7 @@
   set_mi_row_col(xd, tile, mi_row, bh, mi_col, bw, mi_params->mi_rows,
                  mi_params->mi_cols);
 
-  xd->above_txfm_context = cm->above_txfm_context[tile->tile_row] + mi_col;
+  xd->above_txfm_context = cm->above_contexts.txfm[tile->tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
 
@@ -1685,21 +1685,21 @@
   const int mi_row_end = tile->mi_row_end;
   const int mi_col_start = tile->mi_col_start;
   const int mi_col_end = tile->mi_col_end;
-  int mi_row, mi_col, sb_row_in_tile;
+  const int num_planes = av1_num_planes(cm);
 
   av1_zero_above_context(cm, xd, mi_col_start, mi_col_end, tile->tile_row);
-  av1_init_above_context(cm, xd, tile->tile_row);
+  av1_init_above_context(&cm->above_contexts, num_planes, tile->tile_row, xd);
 
   if (cpi->common.delta_q_info.delta_q_present_flag) {
     xd->current_qindex = cpi->common.quant_params.base_qindex;
     if (cpi->common.delta_q_info.delta_lf_present_flag) {
-      av1_reset_loop_filter_delta(xd, av1_num_planes(cm));
+      av1_reset_loop_filter_delta(xd, num_planes);
     }
   }
 
-  for (mi_row = mi_row_start; mi_row < mi_row_end;
+  for (int mi_row = mi_row_start; mi_row < mi_row_end;
        mi_row += cm->seq_params.mib_size) {
-    sb_row_in_tile =
+    const int sb_row_in_tile =
         (mi_row - tile->mi_row_start) >> cm->seq_params.mib_size_log2;
     const TOKENEXTRA *tok =
         cpi->tplist[tile_row][tile_col][sb_row_in_tile].start;
@@ -1708,7 +1708,7 @@
 
     av1_zero_left_context(xd);
 
-    for (mi_col = mi_col_start; mi_col < mi_col_end;
+    for (int mi_col = mi_col_start; mi_col < mi_col_end;
          mi_col += cm->seq_params.mib_size) {
       cpi->td.mb.cb_coef_buff = av1_get_cb_coeff_buffer(cpi, mi_row, mi_col);
       write_modes_sb(cpi, tile, w, &tok, tok_end, mi_row, mi_col,
diff --git a/av1/encoder/encodeframe.c b/av1/encoder/encodeframe.c
index ccf66d6..1f59d8b 100644
--- a/av1/encoder/encodeframe.c
+++ b/av1/encoder/encodeframe.c
@@ -397,7 +397,7 @@
   set_mode_info_offsets(cpi, x, xd, mi_row, mi_col);
 
   set_skip_context(xd, mi_row, mi_col, num_planes);
-  xd->above_txfm_context = cm->above_txfm_context[tile->tile_row] + mi_col;
+  xd->above_txfm_context = cm->above_contexts.txfm[tile->tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
 
@@ -1913,7 +1913,8 @@
 
   pc_tree->partitioning = partition;
 
-  xd->above_txfm_context = cm->above_txfm_context[tile_info->tile_row] + mi_col;
+  xd->above_txfm_context =
+      cm->above_contexts.txfm[tile_info->tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
   save_context(x, &x_ctx, mi_row, mi_col, bsize, num_planes);
@@ -2209,7 +2210,8 @@
 
   pc_tree->partitioning = partition;
 
-  xd->above_txfm_context = cm->above_txfm_context[tile_info->tile_row] + mi_col;
+  xd->above_txfm_context =
+      cm->above_contexts.txfm[tile_info->tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
 
@@ -2240,7 +2242,7 @@
               mi_col + x_idx >= mi_params->mi_cols)
             continue;
           xd->above_txfm_context =
-              cm->above_txfm_context[tile_info->tile_row] + mi_col + x_idx;
+              cm->above_contexts.txfm[tile_info->tile_row] + mi_col + x_idx;
           xd->left_txfm_context =
               xd->left_txfm_context_buffer + ((mi_row + y_idx) & MAX_MIB_MASK);
           pc_tree->split[i]->partitioning = PARTITION_NONE;
@@ -2324,7 +2326,7 @@
         av1_invalid_rd_stats(&none_rdc);
         save_context(x, &x_ctx, mi_row, mi_col, bsize, 3);
         xd->above_txfm_context =
-            cm->above_txfm_context[tile_info->tile_row] + mi_col;
+            cm->above_contexts.txfm[tile_info->tile_row] + mi_col;
         xd->left_txfm_context =
             xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
         pc_tree->partitioning = PARTITION_NONE;
@@ -2346,7 +2348,7 @@
                 (mi_col + x_idx >= mi_params->mi_cols))
               continue;
             xd->above_txfm_context =
-                cm->above_txfm_context[tile_info->tile_row] + mi_col + x_idx;
+                cm->above_contexts.txfm[tile_info->tile_row] + mi_col + x_idx;
             xd->left_txfm_context = xd->left_txfm_context_buffer +
                                     ((mi_row + y_idx) & MAX_MIB_MASK);
             pc_tree->split[i]->partitioning = PARTITION_NONE;
@@ -2806,7 +2808,8 @@
     partition_vert_allowed &= !has_cols;
   }
 
-  xd->above_txfm_context = cm->above_txfm_context[tile_info->tile_row] + mi_col;
+  xd->above_txfm_context =
+      cm->above_contexts.txfm[tile_info->tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
   save_context(x, &x_ctx, mi_row, mi_col, bsize, num_planes);
@@ -4486,7 +4489,8 @@
   const int num_planes = av1_num_planes(cm);
   const BLOCK_SIZE sb_size = cm->seq_params.sb_size;
 
-  xd->above_txfm_context = cm->above_txfm_context[tile_info->tile_row] + mi_col;
+  xd->above_txfm_context =
+      cm->above_contexts.txfm[tile_info->tile_row] + mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (mi_row & MAX_MIB_MASK);
   save_context(x, &sb_fp_stats->x_ctx, mi_row, mi_col, sb_size, num_planes);
@@ -5051,19 +5055,19 @@
   TileDataEnc *const this_tile =
       &cpi->tile_data[tile_row * cm->tiles.cols + tile_col];
   const TileInfo *const tile_info = &this_tile->tile_info;
-  int mi_row;
 
   if (!cpi->sf.rt_sf.use_nonrd_pick_mode) av1_inter_mode_data_init(this_tile);
 
   av1_zero_above_context(cm, &td->mb.e_mbd, tile_info->mi_col_start,
                          tile_info->mi_col_end, tile_row);
-  av1_init_above_context(cm, &td->mb.e_mbd, tile_row);
+  av1_init_above_context(&cm->above_contexts, av1_num_planes(cm), tile_row,
+                         &td->mb.e_mbd);
 
   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);
 
-  for (mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
+  for (int mi_row = tile_info->mi_row_start; mi_row < tile_info->mi_row_end;
        mi_row += cm->seq_params.mib_size) {
     av1_encode_sb_row(cpi, td, tile_row, tile_col, mi_row);
   }
@@ -6186,7 +6190,7 @@
   const int bw = tx_size_wide_unit[max_tx_size];
 
   xd->above_txfm_context =
-      cm->above_txfm_context[xd->tile.tile_row] + xd->mi_col;
+      cm->above_contexts.txfm[xd->tile.tile_row] + xd->mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (xd->mi_row & MAX_MIB_MASK);
 
@@ -6246,7 +6250,7 @@
   const int bw = tx_size_wide_unit[max_tx_size];
 
   xd->above_txfm_context =
-      cm->above_txfm_context[xd->tile.tile_row] + xd->mi_col;
+      cm->above_contexts.txfm[xd->tile.tile_row] + xd->mi_col;
   xd->left_txfm_context =
       xd->left_txfm_context_buffer + (xd->mi_row & MAX_MIB_MASK);
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index f7864e9..dfb7fa9 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -4338,11 +4338,14 @@
   alloc_frame_mvs(cm, cm->cur_frame);
 
   // Allocate above context buffers
-  if (cm->num_allocated_above_context_planes < av1_num_planes(cm) ||
-      cm->num_allocated_above_context_mi_col < cm->mi_params.mi_cols ||
-      cm->num_allocated_above_contexts < cm->tiles.rows) {
-    av1_free_above_context_buffers(cm, cm->num_allocated_above_contexts);
-    if (av1_alloc_above_context_buffers(cm, cm->tiles.rows))
+  CommonContexts *const above_contexts = &cm->above_contexts;
+  if (above_contexts->num_planes < av1_num_planes(cm) ||
+      above_contexts->num_mi_cols < cm->mi_params.mi_cols ||
+      above_contexts->num_tile_rows < cm->tiles.rows) {
+    av1_free_above_context_buffers(above_contexts);
+    if (av1_alloc_above_context_buffers(above_contexts, cm->tiles.rows,
+                                        cm->mi_params.mi_cols,
+                                        av1_num_planes(cm)))
       aom_internal_error(&cm->error, AOM_CODEC_MEM_ERROR,
                          "Failed to allocate context buffers");
   }
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index f13153a..b1c83ff 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -342,7 +342,8 @@
       memcpy(td->mb.e_mbd.tile_ctx, &this_tile->tctx, sizeof(FRAME_CONTEXT));
     }
 
-    av1_init_above_context(cm, &td->mb.e_mbd, tile_row);
+    av1_init_above_context(&cm->above_contexts, av1_num_planes(cm), tile_row,
+                           &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);