Abstract workers and tile_thr_data to PrimaryMultiThreadInfo

Moved workers and tile_thr_data to newly created
PrimaryMultiThreadInfo. The frame contexts also maintain a
copy of workers and tile_thr_data. This is to facilitate
division of workers and tile_thr_data accross frames when
frame parallel encode is turned on.

Change-Id: I574750aee2df2311dce56434bb591954c1cb9082
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index c28633f..204f2d8 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -2643,7 +2643,7 @@
 
     if (cpi->oxcf.pass == 1) {
 #if !CONFIG_REALTIME_ONLY
-      num_workers = cpi->mt_info.num_mod_workers[MOD_FP] =
+      num_workers = ppi->p_mt_info.num_mod_workers[MOD_FP] =
           av1_fp_compute_num_enc_workers(cpi);
 #endif
     } else {
@@ -2651,25 +2651,34 @@
       num_workers = av1_get_max_num_workers(cpi);
     }
     if ((num_workers > 1) && (cpi->mt_info.num_workers == 0)) {
-      av1_create_workers(cpi, num_workers);
-      av1_init_tile_thread_data(cpi, cpi->oxcf.pass == 1);
+      av1_create_workers(ppi, num_workers);
+      av1_init_tile_thread_data(ppi, cpi->oxcf.pass == 1);
+#if CONFIG_FRAME_PARALLEL_ENCODE
+      for (int i = 0; i < ppi->num_fp_contexts; i++) {
+        av1_init_frame_mt(ppi, ppi->parallel_cpi[i]);
+#if CONFIG_MULTITHREAD
+        av1_init_mt_sync(ppi->parallel_cpi[i],
+                         ppi->parallel_cpi[i]->oxcf.pass == 1);
+#endif  // CONFIG_MULTITHREAD
+      }
+#else
+      av1_init_frame_mt(ppi, cpi);
 #if CONFIG_MULTITHREAD
       av1_init_mt_sync(cpi, cpi->oxcf.pass == 1);
-      if (cpi_lap != NULL) {
-        av1_init_mt_sync(cpi_lap, 1);
-      }
 #endif  // CONFIG_MULTITHREAD
+#endif
+      if (cpi_lap != NULL) {
+        av1_init_frame_mt(ppi, cpi_lap);
+#if CONFIG_MULTITHREAD
+        av1_init_mt_sync(cpi_lap, 1);
+#endif  // CONFIG_MULTITHREAD
+      }
     }
 
     // Call for LAP stage
     if (cpi_lap != NULL) {
       int64_t dst_time_stamp_la;
       int64_t dst_end_time_stamp_la;
-      if (cpi_lap->mt_info.workers == NULL) {
-        cpi_lap->mt_info.workers = cpi->mt_info.workers;
-        cpi_lap->mt_info.tile_thr_data = cpi->mt_info.tile_thr_data;
-      }
-      cpi_lap->mt_info.num_workers = cpi->mt_info.num_workers;
       const int status = av1_get_compressed_data(
           cpi_lap, &lib_flags, &frame_size, cx_data_sz, NULL,
           &dst_time_stamp_la, &dst_end_time_stamp_la, !img, timestamp_ratio);
diff --git a/av1/encoder/context_tree.c b/av1/encoder/context_tree.c
index 9fd9d1b..451375f 100644
--- a/av1/encoder/context_tree.c
+++ b/av1/encoder/context_tree.c
@@ -41,16 +41,16 @@
   dst_ctx->rd_mode_is_ready = src_ctx->rd_mode_is_ready;
 }
 
-void av1_setup_shared_coeff_buffer(AV1_COMMON *cm,
+void av1_setup_shared_coeff_buffer(struct aom_internal_error_info *error,
                                    PC_TREE_SHARED_BUFFERS *shared_bufs) {
   for (int i = 0; i < 3; i++) {
     const int max_num_pix = MAX_SB_SIZE * MAX_SB_SIZE;
-    CHECK_MEM_ERROR(cm, shared_bufs->coeff_buf[i],
-                    aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
-    CHECK_MEM_ERROR(cm, shared_bufs->qcoeff_buf[i],
-                    aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
-    CHECK_MEM_ERROR(cm, shared_bufs->dqcoeff_buf[i],
-                    aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
+    AOM_CHECK_MEM_ERROR(error, shared_bufs->coeff_buf[i],
+                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
+    AOM_CHECK_MEM_ERROR(error, shared_bufs->qcoeff_buf[i],
+                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
+    AOM_CHECK_MEM_ERROR(error, shared_bufs->dqcoeff_buf[i],
+                        aom_memalign(32, max_num_pix * sizeof(tran_low_t)));
   }
 }
 
diff --git a/av1/encoder/context_tree.h b/av1/encoder/context_tree.h
index 484a1b3..7f89b14 100644
--- a/av1/encoder/context_tree.h
+++ b/av1/encoder/context_tree.h
@@ -21,6 +21,7 @@
 extern "C" {
 #endif
 
+struct AV1_PRIMARY;
 struct AV1_COMP;
 struct AV1Common;
 struct ThreadData;
@@ -101,7 +102,7 @@
   int sms_rect_valid;
 } SIMPLE_MOTION_DATA_TREE;
 
-void av1_setup_shared_coeff_buffer(AV1_COMMON *cm,
+void av1_setup_shared_coeff_buffer(struct aom_internal_error_info *error,
                                    PC_TREE_SHARED_BUFFERS *shared_bufs);
 void av1_free_shared_coeff_buffer(PC_TREE_SHARED_BUFFERS *shared_bufs);
 
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 234acb0..5cc9ad8 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -746,7 +746,7 @@
   }
 
   if (x->comp_rd_buffer.pred0 == NULL) {
-    alloc_compound_type_rd_buffers(cm, &x->comp_rd_buffer);
+    alloc_compound_type_rd_buffers(&cpi->ppi->error, &x->comp_rd_buffer);
   }
 
   if (x->tmp_conv_dst == NULL) {
@@ -1342,7 +1342,7 @@
   }
 #endif
 
-  alloc_obmc_buffers(&cpi->td.mb.obmc_buffer, cm);
+  alloc_obmc_buffers(&cpi->td.mb.obmc_buffer, &ppi->error);
 
   CHECK_MEM_ERROR(
       cm, cpi->td.mb.inter_modes_info,
@@ -1451,22 +1451,20 @@
 // This function will change the state and free the mutex of corresponding
 // workers and terminate the object. The object can not be re-used unless a call
 // to reset() is made.
-static AOM_INLINE void terminate_worker_data(AV1_COMP *cpi) {
-  MultiThreadInfo *const mt_info = &cpi->mt_info;
-  for (int t = mt_info->num_workers - 1; t >= 0; --t) {
-    AVxWorker *const worker = &mt_info->workers[t];
+static AOM_INLINE void terminate_worker_data(AV1_PRIMARY *ppi) {
+  PrimaryMultiThreadInfo *const p_mt_info = &ppi->p_mt_info;
+  for (int t = p_mt_info->num_workers - 1; t >= 0; --t) {
+    AVxWorker *const worker = &p_mt_info->workers[t];
     aom_get_worker_interface()->end(worker);
   }
 }
 
 // Deallocate allocated thread_data.
-static AOM_INLINE void free_thread_data(AV1_COMP *cpi) {
-  MultiThreadInfo *const mt_info = &cpi->mt_info;
-  AV1_COMMON *cm = &cpi->common;
-  for (int t = 0; t < mt_info->num_workers; ++t) {
-    EncWorkerData *const thread_data = &mt_info->tile_thr_data[t];
+static AOM_INLINE void free_thread_data(AV1_PRIMARY *ppi) {
+  PrimaryMultiThreadInfo *const p_mt_info = &ppi->p_mt_info;
+  for (int t = 1; t < p_mt_info->num_workers; ++t) {
+    EncWorkerData *const thread_data = &p_mt_info->tile_thr_data[t];
     aom_free(thread_data->td->tctx);
-    if (t == 0) continue;
     aom_free(thread_data->td->palette_buffer);
     aom_free(thread_data->td->tmp_conv_dst);
     release_compound_type_rd_buffers(&thread_data->td->comp_rd_buffer);
@@ -1485,7 +1483,8 @@
       }
     }
     aom_free(thread_data->td->counts);
-    av1_free_pmc(thread_data->td->firstpass_ctx, av1_num_planes(cm));
+    av1_free_pmc(thread_data->td->firstpass_ctx,
+                 ppi->seq_params.monochrome ? 1 : MAX_MB_PLANE);
     thread_data->td->firstpass_ctx = NULL;
     av1_free_shared_coeff_buffer(&thread_data->td->shared_coeff_buf);
     av1_free_sms_tree(thread_data->td);
@@ -1516,6 +1515,12 @@
   av1_tpl_dealloc(&tpl_data->tpl_mt_sync);
 #endif
 
+  terminate_worker_data(ppi);
+  free_thread_data(ppi);
+
+  aom_free(ppi->p_mt_info.tile_thr_data);
+  aom_free(ppi->p_mt_info.workers);
+
   aom_free(ppi);
 }
 
@@ -1542,11 +1547,7 @@
   av1_denoiser_free(&(cpi->denoiser));
 #endif
 
-  if (cpi->compressor_stage != LAP_STAGE) {
-    terminate_worker_data(cpi);
-    free_thread_data(cpi);
-  }
-
+  aom_free(cpi->td.tctx);
   MultiThreadInfo *const mt_info = &cpi->mt_info;
 #if CONFIG_MULTITHREAD
   pthread_mutex_t *const enc_row_mt_mutex_ = mt_info->enc_row_mt.mutex_;
@@ -1566,10 +1567,6 @@
   }
 #endif
   av1_row_mt_mem_dealloc(cpi);
-  if (cpi->compressor_stage != LAP_STAGE) {
-    aom_free(mt_info->tile_thr_data);
-    aom_free(mt_info->workers);
-  }
 
   if (mt_info->num_workers > 1) {
     av1_loop_filter_dealloc(&mt_info->lf_row_sync);
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index 3cdc2a5..138e5c1 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -1411,6 +1411,32 @@
 } AV1EncRowMultiThreadInfo;
 
 /*!
+ * \brief Primary Encoder parameters related to multi-threading.
+ */
+typedef struct PrimaryMultiThreadInfo {
+  /*!
+   * Number of workers created for multi-threading.
+   */
+  int num_workers;
+
+  /*!
+   * Number of workers used for different MT modules.
+   */
+  int num_mod_workers[NUM_MT_MODULES];
+
+  /*!
+   * Synchronization object used to launch job in the worker thread.
+   */
+  AVxWorker *workers;
+
+  /*!
+   * Data specific to each worker in encoder multi-threading.
+   * tile_thr_data[i] stores the worker data of the ith thread.
+   */
+  struct EncWorkerData *tile_thr_data;
+} PrimaryMultiThreadInfo;
+
+/*!
  * \brief Encoder parameters related to multi-threading.
  */
 typedef struct MultiThreadInfo {
@@ -2371,6 +2397,11 @@
    * frame of the same type as the current frame).
    */
   int fb_of_context_type[REF_FRAMES];
+
+  /*!
+   * Primary Multi-threading parameters.
+   */
+  PrimaryMultiThreadInfo p_mt_info;
 } AV1_PRIMARY;
 
 /*!
diff --git a/av1/encoder/encoder_alloc.h b/av1/encoder/encoder_alloc.h
index 912280c..3fccc24 100644
--- a/av1/encoder/encoder_alloc.h
+++ b/av1/encoder/encoder_alloc.h
@@ -85,7 +85,7 @@
   CHECK_MEM_ERROR(cm, cpi->td.mb.dv_costs,
                   (IntraBCMVCosts *)aom_malloc(sizeof(*cpi->td.mb.dv_costs)));
 
-  av1_setup_shared_coeff_buffer(&cpi->common, &cpi->td.shared_coeff_buf);
+  av1_setup_shared_coeff_buffer(&cpi->ppi->error, &cpi->td.shared_coeff_buf);
   av1_setup_sms_tree(cpi, &cpi->td);
   cpi->td.firstpass_ctx =
       av1_alloc_pmc(cpi, BLOCK_16X16, &cpi->td.shared_coeff_buf);
@@ -112,20 +112,20 @@
                   aom_calloc(mi_params->mi_rows * mi_params->mi_cols, 1));
 }
 
-static AOM_INLINE void alloc_obmc_buffers(OBMCBuffer *obmc_buffer,
-                                          AV1_COMMON *cm) {
-  CHECK_MEM_ERROR(
-      cm, obmc_buffer->wsrc,
+static AOM_INLINE void alloc_obmc_buffers(
+    OBMCBuffer *obmc_buffer, struct aom_internal_error_info *error) {
+  AOM_CHECK_MEM_ERROR(
+      error, obmc_buffer->wsrc,
       (int32_t *)aom_memalign(16, MAX_SB_SQUARE * sizeof(*obmc_buffer->wsrc)));
-  CHECK_MEM_ERROR(
-      cm, obmc_buffer->mask,
+  AOM_CHECK_MEM_ERROR(
+      error, obmc_buffer->mask,
       (int32_t *)aom_memalign(16, MAX_SB_SQUARE * sizeof(*obmc_buffer->mask)));
-  CHECK_MEM_ERROR(
-      cm, obmc_buffer->above_pred,
+  AOM_CHECK_MEM_ERROR(
+      error, obmc_buffer->above_pred,
       (uint8_t *)aom_memalign(
           16, MAX_MB_PLANE * MAX_SB_SQUARE * sizeof(*obmc_buffer->above_pred)));
-  CHECK_MEM_ERROR(
-      cm, obmc_buffer->left_pred,
+  AOM_CHECK_MEM_ERROR(
+      error, obmc_buffer->left_pred,
       (uint8_t *)aom_memalign(
           16, MAX_MB_PLANE * MAX_SB_SQUARE * sizeof(*obmc_buffer->left_pred)));
 }
@@ -143,22 +143,22 @@
 }
 
 static AOM_INLINE void alloc_compound_type_rd_buffers(
-    AV1_COMMON *const cm, CompoundTypeRdBuffers *const bufs) {
-  CHECK_MEM_ERROR(
-      cm, bufs->pred0,
+    struct aom_internal_error_info *error, CompoundTypeRdBuffers *const bufs) {
+  AOM_CHECK_MEM_ERROR(
+      error, bufs->pred0,
       (uint8_t *)aom_memalign(16, 2 * MAX_SB_SQUARE * sizeof(*bufs->pred0)));
-  CHECK_MEM_ERROR(
-      cm, bufs->pred1,
+  AOM_CHECK_MEM_ERROR(
+      error, bufs->pred1,
       (uint8_t *)aom_memalign(16, 2 * MAX_SB_SQUARE * sizeof(*bufs->pred1)));
-  CHECK_MEM_ERROR(
-      cm, bufs->residual1,
+  AOM_CHECK_MEM_ERROR(
+      error, bufs->residual1,
       (int16_t *)aom_memalign(32, MAX_SB_SQUARE * sizeof(*bufs->residual1)));
-  CHECK_MEM_ERROR(
-      cm, bufs->diff10,
+  AOM_CHECK_MEM_ERROR(
+      error, bufs->diff10,
       (int16_t *)aom_memalign(32, MAX_SB_SQUARE * sizeof(*bufs->diff10)));
-  CHECK_MEM_ERROR(cm, bufs->tmp_best_mask_buf,
-                  (uint8_t *)aom_malloc(2 * MAX_SB_SQUARE *
-                                        sizeof(*bufs->tmp_best_mask_buf)));
+  AOM_CHECK_MEM_ERROR(error, bufs->tmp_best_mask_buf,
+                      (uint8_t *)aom_malloc(2 * MAX_SB_SQUARE *
+                                            sizeof(*bufs->tmp_best_mask_buf)));
 }
 
 static AOM_INLINE void release_compound_type_rd_buffers(
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index c70ade2..44ca4df 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -538,6 +538,17 @@
   return 1;
 }
 
+void av1_init_frame_mt(AV1_PRIMARY *ppi, AV1_COMP *cpi) {
+  cpi->mt_info.workers = ppi->p_mt_info.workers;
+  cpi->mt_info.num_workers = ppi->p_mt_info.num_workers;
+  cpi->mt_info.tile_thr_data = ppi->p_mt_info.tile_thr_data;
+  int i;
+  for (i = MOD_FP; i < NUM_MT_MODULES; i++) {
+    cpi->mt_info.num_mod_workers[i] =
+        AOMMIN(cpi->mt_info.num_workers, ppi->p_mt_info.num_mod_workers[i]);
+  }
+}
+
 #if CONFIG_MULTITHREAD
 void av1_init_mt_sync(AV1_COMP *cpi, int is_first_pass) {
   AV1_COMMON *const cm = &cpi->common;
@@ -577,114 +588,127 @@
 }
 #endif  // CONFIG_MULTITHREAD
 
-void av1_init_tile_thread_data(AV1_COMP *cpi, int is_first_pass) {
-  AV1_COMMON *const cm = &cpi->common;
-  MultiThreadInfo *const mt_info = &cpi->mt_info;
+void av1_init_tile_thread_data(AV1_PRIMARY *ppi, int is_first_pass) {
+  PrimaryMultiThreadInfo *const p_mt_info = &ppi->p_mt_info;
 
-  assert(mt_info->workers != NULL);
-  assert(mt_info->tile_thr_data != NULL);
+  assert(p_mt_info->workers != NULL);
+  assert(p_mt_info->tile_thr_data != NULL);
 
-  int num_workers = mt_info->num_workers;
+  int num_workers = p_mt_info->num_workers;
 
   for (int i = num_workers - 1; i >= 0; i--) {
-    EncWorkerData *const thread_data = &mt_info->tile_thr_data[i];
+    EncWorkerData *const thread_data = &p_mt_info->tile_thr_data[i];
 
     if (i > 0) {
       // Allocate thread data.
-      CHECK_MEM_ERROR(cm, thread_data->td,
-                      aom_memalign(32, sizeof(*thread_data->td)));
+      AOM_CHECK_MEM_ERROR(&ppi->error, thread_data->td,
+                          aom_memalign(32, sizeof(*thread_data->td)));
       av1_zero(*thread_data->td);
 
       // Set up shared coeff buffers.
-      av1_setup_shared_coeff_buffer(cm, &thread_data->td->shared_coeff_buf);
-      CHECK_MEM_ERROR(
-          cm, thread_data->td->tmp_conv_dst,
+      av1_setup_shared_coeff_buffer(&ppi->error,
+                                    &thread_data->td->shared_coeff_buf);
+      AOM_CHECK_MEM_ERROR(
+          &ppi->error, thread_data->td->tmp_conv_dst,
           aom_memalign(32, MAX_SB_SIZE * MAX_SB_SIZE *
                                sizeof(*thread_data->td->tmp_conv_dst)));
 
-      if (i < mt_info->num_mod_workers[MOD_FP]) {
+      if (i < p_mt_info->num_mod_workers[MOD_FP]) {
         // Set up firstpass PICK_MODE_CONTEXT.
-        thread_data->td->firstpass_ctx =
-            av1_alloc_pmc(cpi, BLOCK_16X16, &thread_data->td->shared_coeff_buf);
+        thread_data->td->firstpass_ctx = av1_alloc_pmc(
+            ppi->cpi, BLOCK_16X16, &thread_data->td->shared_coeff_buf);
       }
 
-      if (!is_first_pass && i < mt_info->num_mod_workers[MOD_ENC]) {
+      if (!is_first_pass && i < p_mt_info->num_mod_workers[MOD_ENC]) {
         // Set up sms_tree.
-        av1_setup_sms_tree(cpi, thread_data->td);
+        av1_setup_sms_tree(ppi->cpi, thread_data->td);
 
-        alloc_obmc_buffers(&thread_data->td->obmc_buffer, cm);
+        alloc_obmc_buffers(&thread_data->td->obmc_buffer, &ppi->error);
 
-        CHECK_MEM_ERROR(cm, thread_data->td->inter_modes_info,
-                        (InterModesInfo *)aom_malloc(
-                            sizeof(*thread_data->td->inter_modes_info)));
+        AOM_CHECK_MEM_ERROR(&ppi->error, thread_data->td->inter_modes_info,
+                            (InterModesInfo *)aom_malloc(
+                                sizeof(*thread_data->td->inter_modes_info)));
 
         for (int x = 0; x < 2; x++)
           for (int y = 0; y < 2; y++)
-            CHECK_MEM_ERROR(
-                cm, thread_data->td->hash_value_buffer[x][y],
+            AOM_CHECK_MEM_ERROR(
+                &ppi->error, thread_data->td->hash_value_buffer[x][y],
                 (uint32_t *)aom_malloc(
                     AOM_BUFFER_SIZE_FOR_BLOCK_HASH *
                     sizeof(*thread_data->td->hash_value_buffer[0][0])));
 
         // Allocate frame counters in thread data.
-        CHECK_MEM_ERROR(cm, thread_data->td->counts,
-                        aom_calloc(1, sizeof(*thread_data->td->counts)));
+        AOM_CHECK_MEM_ERROR(&ppi->error, thread_data->td->counts,
+                            aom_calloc(1, sizeof(*thread_data->td->counts)));
 
         // Allocate buffers used by palette coding mode.
-        CHECK_MEM_ERROR(
-            cm, thread_data->td->palette_buffer,
+        AOM_CHECK_MEM_ERROR(
+            &ppi->error, thread_data->td->palette_buffer,
             aom_memalign(16, sizeof(*thread_data->td->palette_buffer)));
 
-        alloc_compound_type_rd_buffers(cm, &thread_data->td->comp_rd_buffer);
+        alloc_compound_type_rd_buffers(&ppi->error,
+                                       &thread_data->td->comp_rd_buffer);
 
         for (int j = 0; j < 2; ++j) {
-          CHECK_MEM_ERROR(
-              cm, thread_data->td->tmp_pred_bufs[j],
+          AOM_CHECK_MEM_ERROR(
+              &ppi->error, thread_data->td->tmp_pred_bufs[j],
               aom_memalign(32, 2 * MAX_MB_PLANE * MAX_SB_SQUARE *
                                    sizeof(*thread_data->td->tmp_pred_bufs[j])));
         }
 
-        const int plane_types = PLANE_TYPES >> cm->seq_params->monochrome;
-        CHECK_MEM_ERROR(
-            cm, thread_data->td->pixel_gradient_info,
+        const int plane_types = PLANE_TYPES >> ppi->seq_params.monochrome;
+        AOM_CHECK_MEM_ERROR(
+            &ppi->error, thread_data->td->pixel_gradient_info,
             aom_malloc(sizeof(*thread_data->td->pixel_gradient_info) *
                        plane_types * MAX_SB_SQUARE));
 
-        if (cpi->sf.part_sf.partition_search_type == VAR_BASED_PARTITION) {
+        if (ppi->cpi->sf.part_sf.partition_search_type == VAR_BASED_PARTITION) {
           const int num_64x64_blocks =
-              (cm->seq_params->sb_size == BLOCK_64X64) ? 1 : 4;
-          CHECK_MEM_ERROR(
-              cm, thread_data->td->vt64x64,
+              (ppi->seq_params.sb_size == BLOCK_64X64) ? 1 : 4;
+          AOM_CHECK_MEM_ERROR(
+              &ppi->error, thread_data->td->vt64x64,
               aom_malloc(sizeof(*thread_data->td->vt64x64) * num_64x64_blocks));
         }
       }
-    } else {
-      thread_data->td = &cpi->td;
     }
 
-    if (!is_first_pass && cpi->oxcf.row_mt == 1 &&
-        i < mt_info->num_mod_workers[MOD_ENC]) {
-      CHECK_MEM_ERROR(
-          cm, thread_data->td->tctx,
-          (FRAME_CONTEXT *)aom_memalign(16, sizeof(*thread_data->td->tctx)));
+    if (!is_first_pass && ppi->cpi->oxcf.row_mt == 1 &&
+        i < p_mt_info->num_mod_workers[MOD_ENC]) {
+      if (i == 0) {
+#if CONFIG_FRAME_PARALLEL_ENCODE
+        for (int j = 0; j < ppi->num_fp_contexts; j++) {
+          AOM_CHECK_MEM_ERROR(&ppi->error, ppi->parallel_cpi[j]->td.tctx,
+                              (FRAME_CONTEXT *)aom_memalign(
+                                  16, sizeof(*ppi->parallel_cpi[j]->td.tctx)));
+        }
+#else
+        AOM_CHECK_MEM_ERROR(
+            &ppi->error, ppi->cpi->td.tctx,
+            (FRAME_CONTEXT *)aom_memalign(16, sizeof(*ppi->cpi->td.tctx)));
+#endif
+      } else {
+        AOM_CHECK_MEM_ERROR(
+            &ppi->error, thread_data->td->tctx,
+            (FRAME_CONTEXT *)aom_memalign(16, sizeof(*thread_data->td->tctx)));
+      }
     }
   }
 }
 
-void av1_create_workers(AV1_COMP *cpi, int num_workers) {
-  AV1_COMMON *const cm = &cpi->common;
-  MultiThreadInfo *const mt_info = &cpi->mt_info;
+void av1_create_workers(AV1_PRIMARY *ppi, int num_workers) {
+  PrimaryMultiThreadInfo *const p_mt_info = &ppi->p_mt_info;
   const AVxWorkerInterface *const winterface = aom_get_worker_interface();
 
-  CHECK_MEM_ERROR(cm, mt_info->workers,
-                  aom_malloc(num_workers * sizeof(*mt_info->workers)));
+  AOM_CHECK_MEM_ERROR(&ppi->error, p_mt_info->workers,
+                      aom_malloc(num_workers * sizeof(*p_mt_info->workers)));
 
-  CHECK_MEM_ERROR(cm, mt_info->tile_thr_data,
-                  aom_calloc(num_workers, sizeof(*mt_info->tile_thr_data)));
+  AOM_CHECK_MEM_ERROR(
+      &ppi->error, p_mt_info->tile_thr_data,
+      aom_calloc(num_workers, sizeof(*p_mt_info->tile_thr_data)));
 
   for (int i = num_workers - 1; i >= 0; i--) {
-    AVxWorker *const worker = &mt_info->workers[i];
-    EncWorkerData *const thread_data = &mt_info->tile_thr_data[i];
+    AVxWorker *const worker = &p_mt_info->workers[i];
+    EncWorkerData *const thread_data = &p_mt_info->tile_thr_data[i];
 
     winterface->init(worker);
     worker->thread_name = "aom enc worker";
@@ -696,12 +720,12 @@
     if (i > 0) {
       // Create threads
       if (!winterface->reset(worker))
-        aom_internal_error(cm->error, AOM_CODEC_ERROR,
+        aom_internal_error(&ppi->error, AOM_CODEC_ERROR,
                            "Tile encoder thread creation failed");
     }
     winterface->sync(worker);
 
-    ++mt_info->num_workers;
+    ++p_mt_info->num_workers;
   }
 }
 
@@ -922,7 +946,8 @@
 int av1_get_max_num_workers(AV1_COMP *cpi) {
   int max_num_workers = 0;
   for (int i = MOD_FP; i < NUM_MT_MODULES; i++)
-    max_num_workers = AOMMAX(cpi->mt_info.num_mod_workers[i], max_num_workers);
+    max_num_workers =
+        AOMMAX(cpi->ppi->p_mt_info.num_mod_workers[i], max_num_workers);
   assert(max_num_workers >= 1);
   return AOMMIN(max_num_workers, cpi->oxcf.max_threads);
 }
@@ -2251,6 +2276,6 @@
 // Computes the number of workers for each MT modules in the encoder
 void av1_compute_num_workers_for_mt(AV1_COMP *cpi) {
   for (int i = MOD_FP; i < NUM_MT_MODULES; i++)
-    cpi->mt_info.num_mod_workers[i] =
+    cpi->ppi->p_mt_info.num_mod_workers[i] =
         compute_num_mod_workers(cpi, (MULTI_THREADED_MODULES)i);
 }
diff --git a/av1/encoder/ethread.h b/av1/encoder/ethread.h
index 85fcfe5..96eb675 100644
--- a/av1/encoder/ethread.h
+++ b/av1/encoder/ethread.h
@@ -78,13 +78,15 @@
 
 int av1_get_max_num_workers(AV1_COMP *cpi);
 
-void av1_create_workers(AV1_COMP *cpi, int num_workers);
+void av1_create_workers(AV1_PRIMARY *ppi, int num_workers);
+
+void av1_init_frame_mt(AV1_PRIMARY *ppi, AV1_COMP *cpi);
 
 #if CONFIG_MULTITHREAD
 void av1_init_mt_sync(AV1_COMP *cpi, int is_first_pass);
 #endif  // CONFIG_MULTITHREAD
 
-void av1_init_tile_thread_data(AV1_COMP *cpi, int is_first_pass);
+void av1_init_tile_thread_data(AV1_PRIMARY *ppi, int is_first_pass);
 
 void av1_cdef_mse_calc_frame_mt(AV1_COMMON *cm, MultiThreadInfo *mt_info,
                                 CdefSearchCtx *cdef_search_ctx);