xref: /aosp_15_r20/external/libvpx/vp9/encoder/vp9_multi_thread.c (revision fb1b10ab9aebc7c7068eedab379b749d7e3900be)
1*fb1b10abSAndroid Build Coastguard Worker /*
2*fb1b10abSAndroid Build Coastguard Worker  *  Copyright (c) 2017 The WebM project authors. All Rights Reserved.
3*fb1b10abSAndroid Build Coastguard Worker  *
4*fb1b10abSAndroid Build Coastguard Worker  *  Use of this source code is governed by a BSD-style license
5*fb1b10abSAndroid Build Coastguard Worker  *  that can be found in the LICENSE file in the root of the source
6*fb1b10abSAndroid Build Coastguard Worker  *  tree. An additional intellectual property rights grant can be found
7*fb1b10abSAndroid Build Coastguard Worker  *  in the file PATENTS.  All contributing project authors may
8*fb1b10abSAndroid Build Coastguard Worker  *  be found in the AUTHORS file in the root of the source tree.
9*fb1b10abSAndroid Build Coastguard Worker  */
10*fb1b10abSAndroid Build Coastguard Worker 
11*fb1b10abSAndroid Build Coastguard Worker #include <assert.h>
12*fb1b10abSAndroid Build Coastguard Worker 
13*fb1b10abSAndroid Build Coastguard Worker #include "vpx_util/vpx_pthread.h"
14*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_encoder.h"
15*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_ethread.h"
16*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_multi_thread.h"
17*fb1b10abSAndroid Build Coastguard Worker #include "vp9/encoder/vp9_temporal_filter.h"
18*fb1b10abSAndroid Build Coastguard Worker 
vp9_enc_grp_get_next_job(MultiThreadHandle * multi_thread_ctxt,int tile_id)19*fb1b10abSAndroid Build Coastguard Worker void *vp9_enc_grp_get_next_job(MultiThreadHandle *multi_thread_ctxt,
20*fb1b10abSAndroid Build Coastguard Worker                                int tile_id) {
21*fb1b10abSAndroid Build Coastguard Worker   RowMTInfo *row_mt_info;
22*fb1b10abSAndroid Build Coastguard Worker   JobQueueHandle *job_queue_hdl = NULL;
23*fb1b10abSAndroid Build Coastguard Worker   void *next = NULL;
24*fb1b10abSAndroid Build Coastguard Worker   JobNode *job_info = NULL;
25*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
26*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_t *mutex_handle = NULL;
27*fb1b10abSAndroid Build Coastguard Worker #endif
28*fb1b10abSAndroid Build Coastguard Worker 
29*fb1b10abSAndroid Build Coastguard Worker   row_mt_info = (RowMTInfo *)(&multi_thread_ctxt->row_mt_info[tile_id]);
30*fb1b10abSAndroid Build Coastguard Worker   job_queue_hdl = (JobQueueHandle *)&row_mt_info->job_queue_hdl;
31*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
32*fb1b10abSAndroid Build Coastguard Worker   mutex_handle = &row_mt_info->job_mutex;
33*fb1b10abSAndroid Build Coastguard Worker #endif
34*fb1b10abSAndroid Build Coastguard Worker 
35*fb1b10abSAndroid Build Coastguard Worker // lock the mutex for queue access
36*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
37*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(mutex_handle);
38*fb1b10abSAndroid Build Coastguard Worker #endif
39*fb1b10abSAndroid Build Coastguard Worker   next = job_queue_hdl->next;
40*fb1b10abSAndroid Build Coastguard Worker   if (next != NULL) {
41*fb1b10abSAndroid Build Coastguard Worker     JobQueue *job_queue = (JobQueue *)next;
42*fb1b10abSAndroid Build Coastguard Worker     job_info = &job_queue->job_info;
43*fb1b10abSAndroid Build Coastguard Worker     // Update the next job in the queue
44*fb1b10abSAndroid Build Coastguard Worker     job_queue_hdl->next = job_queue->next;
45*fb1b10abSAndroid Build Coastguard Worker     job_queue_hdl->num_jobs_acquired++;
46*fb1b10abSAndroid Build Coastguard Worker   }
47*fb1b10abSAndroid Build Coastguard Worker 
48*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
49*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(mutex_handle);
50*fb1b10abSAndroid Build Coastguard Worker #endif
51*fb1b10abSAndroid Build Coastguard Worker 
52*fb1b10abSAndroid Build Coastguard Worker   return job_info;
53*fb1b10abSAndroid Build Coastguard Worker }
54*fb1b10abSAndroid Build Coastguard Worker 
vp9_row_mt_alloc_rd_thresh(VP9_COMP * const cpi,TileDataEnc * const this_tile)55*fb1b10abSAndroid Build Coastguard Worker void vp9_row_mt_alloc_rd_thresh(VP9_COMP *const cpi,
56*fb1b10abSAndroid Build Coastguard Worker                                 TileDataEnc *const this_tile) {
57*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
58*fb1b10abSAndroid Build Coastguard Worker   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
59*fb1b10abSAndroid Build Coastguard Worker   int i;
60*fb1b10abSAndroid Build Coastguard Worker 
61*fb1b10abSAndroid Build Coastguard Worker   if (this_tile->row_base_thresh_freq_fact != NULL) {
62*fb1b10abSAndroid Build Coastguard Worker     if (sb_rows <= this_tile->sb_rows) {
63*fb1b10abSAndroid Build Coastguard Worker       return;
64*fb1b10abSAndroid Build Coastguard Worker     }
65*fb1b10abSAndroid Build Coastguard Worker     vpx_free(this_tile->row_base_thresh_freq_fact);
66*fb1b10abSAndroid Build Coastguard Worker     this_tile->row_base_thresh_freq_fact = NULL;
67*fb1b10abSAndroid Build Coastguard Worker   }
68*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(
69*fb1b10abSAndroid Build Coastguard Worker       &cm->error, this_tile->row_base_thresh_freq_fact,
70*fb1b10abSAndroid Build Coastguard Worker       (int *)vpx_calloc(sb_rows * BLOCK_SIZES * MAX_MODES,
71*fb1b10abSAndroid Build Coastguard Worker                         sizeof(*(this_tile->row_base_thresh_freq_fact))));
72*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < sb_rows * BLOCK_SIZES * MAX_MODES; i++)
73*fb1b10abSAndroid Build Coastguard Worker     this_tile->row_base_thresh_freq_fact[i] = RD_THRESH_INIT_FACT;
74*fb1b10abSAndroid Build Coastguard Worker   this_tile->sb_rows = sb_rows;
75*fb1b10abSAndroid Build Coastguard Worker }
76*fb1b10abSAndroid Build Coastguard Worker 
vp9_row_mt_mem_alloc(VP9_COMP * cpi)77*fb1b10abSAndroid Build Coastguard Worker void vp9_row_mt_mem_alloc(VP9_COMP *cpi) {
78*fb1b10abSAndroid Build Coastguard Worker   struct VP9Common *cm = &cpi->common;
79*fb1b10abSAndroid Build Coastguard Worker   MultiThreadHandle *multi_thread_ctxt = &cpi->multi_thread_ctxt;
80*fb1b10abSAndroid Build Coastguard Worker   int tile_row, tile_col;
81*fb1b10abSAndroid Build Coastguard Worker   const int tile_cols = 1 << cm->log2_tile_cols;
82*fb1b10abSAndroid Build Coastguard Worker   const int tile_rows = 1 << cm->log2_tile_rows;
83*fb1b10abSAndroid Build Coastguard Worker   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
84*fb1b10abSAndroid Build Coastguard Worker   int jobs_per_tile_col, total_jobs;
85*fb1b10abSAndroid Build Coastguard Worker 
86*fb1b10abSAndroid Build Coastguard Worker   // Allocate memory that is large enough for all row_mt stages. First pass
87*fb1b10abSAndroid Build Coastguard Worker   // uses 16x16 block size.
88*fb1b10abSAndroid Build Coastguard Worker   jobs_per_tile_col = VPXMAX(cm->mb_rows, sb_rows);
89*fb1b10abSAndroid Build Coastguard Worker   // Calculate the total number of jobs
90*fb1b10abSAndroid Build Coastguard Worker   total_jobs = jobs_per_tile_col * tile_cols;
91*fb1b10abSAndroid Build Coastguard Worker 
92*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->allocated_tile_cols = tile_cols;
93*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->allocated_tile_rows = tile_rows;
94*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->allocated_vert_unit_rows = jobs_per_tile_col;
95*fb1b10abSAndroid Build Coastguard Worker 
96*fb1b10abSAndroid Build Coastguard Worker   CHECK_MEM_ERROR(&cm->error, multi_thread_ctxt->job_queue,
97*fb1b10abSAndroid Build Coastguard Worker                   (JobQueue *)vpx_memalign(32, total_jobs * sizeof(JobQueue)));
98*fb1b10abSAndroid Build Coastguard Worker 
99*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
100*fb1b10abSAndroid Build Coastguard Worker   // Create mutex for each tile
101*fb1b10abSAndroid Build Coastguard Worker   for (tile_col = 0; tile_col < tile_cols; tile_col++) {
102*fb1b10abSAndroid Build Coastguard Worker     RowMTInfo *row_mt_info = &multi_thread_ctxt->row_mt_info[tile_col];
103*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_init(&row_mt_info->job_mutex, NULL);
104*fb1b10abSAndroid Build Coastguard Worker   }
105*fb1b10abSAndroid Build Coastguard Worker #endif
106*fb1b10abSAndroid Build Coastguard Worker 
107*fb1b10abSAndroid Build Coastguard Worker   // Allocate memory for row based multi-threading
108*fb1b10abSAndroid Build Coastguard Worker   for (tile_col = 0; tile_col < tile_cols; tile_col++) {
109*fb1b10abSAndroid Build Coastguard Worker     TileDataEnc *this_tile = &cpi->tile_data[tile_col];
110*fb1b10abSAndroid Build Coastguard Worker     vp9_row_mt_sync_mem_alloc(&this_tile->row_mt_sync, cm, jobs_per_tile_col);
111*fb1b10abSAndroid Build Coastguard Worker   }
112*fb1b10abSAndroid Build Coastguard Worker 
113*fb1b10abSAndroid Build Coastguard Worker   // Assign the sync pointer of tile row zero for every tile row > 0
114*fb1b10abSAndroid Build Coastguard Worker   for (tile_row = 1; tile_row < tile_rows; tile_row++) {
115*fb1b10abSAndroid Build Coastguard Worker     for (tile_col = 0; tile_col < tile_cols; tile_col++) {
116*fb1b10abSAndroid Build Coastguard Worker       TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols + tile_col];
117*fb1b10abSAndroid Build Coastguard Worker       TileDataEnc *this_col_tile = &cpi->tile_data[tile_col];
118*fb1b10abSAndroid Build Coastguard Worker       this_tile->row_mt_sync = this_col_tile->row_mt_sync;
119*fb1b10abSAndroid Build Coastguard Worker     }
120*fb1b10abSAndroid Build Coastguard Worker   }
121*fb1b10abSAndroid Build Coastguard Worker 
122*fb1b10abSAndroid Build Coastguard Worker   // Calculate the number of vertical units in the given tile row
123*fb1b10abSAndroid Build Coastguard Worker   for (tile_row = 0; tile_row < tile_rows; tile_row++) {
124*fb1b10abSAndroid Build Coastguard Worker     TileDataEnc *this_tile = &cpi->tile_data[tile_row * tile_cols];
125*fb1b10abSAndroid Build Coastguard Worker     TileInfo *tile_info = &this_tile->tile_info;
126*fb1b10abSAndroid Build Coastguard Worker     multi_thread_ctxt->num_tile_vert_sbs[tile_row] =
127*fb1b10abSAndroid Build Coastguard Worker         get_num_vert_units(*tile_info, MI_BLOCK_SIZE_LOG2);
128*fb1b10abSAndroid Build Coastguard Worker   }
129*fb1b10abSAndroid Build Coastguard Worker }
130*fb1b10abSAndroid Build Coastguard Worker 
vp9_row_mt_mem_dealloc(VP9_COMP * cpi)131*fb1b10abSAndroid Build Coastguard Worker void vp9_row_mt_mem_dealloc(VP9_COMP *cpi) {
132*fb1b10abSAndroid Build Coastguard Worker   MultiThreadHandle *multi_thread_ctxt = &cpi->multi_thread_ctxt;
133*fb1b10abSAndroid Build Coastguard Worker   int tile_col;
134*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
135*fb1b10abSAndroid Build Coastguard Worker   int tile_row;
136*fb1b10abSAndroid Build Coastguard Worker #endif
137*fb1b10abSAndroid Build Coastguard Worker 
138*fb1b10abSAndroid Build Coastguard Worker   // Deallocate memory for job queue
139*fb1b10abSAndroid Build Coastguard Worker   if (multi_thread_ctxt->job_queue) {
140*fb1b10abSAndroid Build Coastguard Worker     vpx_free(multi_thread_ctxt->job_queue);
141*fb1b10abSAndroid Build Coastguard Worker     multi_thread_ctxt->job_queue = NULL;
142*fb1b10abSAndroid Build Coastguard Worker   }
143*fb1b10abSAndroid Build Coastguard Worker 
144*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
145*fb1b10abSAndroid Build Coastguard Worker   // Destroy mutex for each tile
146*fb1b10abSAndroid Build Coastguard Worker   for (tile_col = 0; tile_col < multi_thread_ctxt->allocated_tile_cols;
147*fb1b10abSAndroid Build Coastguard Worker        tile_col++) {
148*fb1b10abSAndroid Build Coastguard Worker     RowMTInfo *row_mt_info = &multi_thread_ctxt->row_mt_info[tile_col];
149*fb1b10abSAndroid Build Coastguard Worker     pthread_mutex_destroy(&row_mt_info->job_mutex);
150*fb1b10abSAndroid Build Coastguard Worker   }
151*fb1b10abSAndroid Build Coastguard Worker #endif
152*fb1b10abSAndroid Build Coastguard Worker 
153*fb1b10abSAndroid Build Coastguard Worker   // Free row based multi-threading sync memory
154*fb1b10abSAndroid Build Coastguard Worker   for (tile_col = 0; tile_col < multi_thread_ctxt->allocated_tile_cols;
155*fb1b10abSAndroid Build Coastguard Worker        tile_col++) {
156*fb1b10abSAndroid Build Coastguard Worker     TileDataEnc *this_tile = &cpi->tile_data[tile_col];
157*fb1b10abSAndroid Build Coastguard Worker     vp9_row_mt_sync_mem_dealloc(&this_tile->row_mt_sync);
158*fb1b10abSAndroid Build Coastguard Worker   }
159*fb1b10abSAndroid Build Coastguard Worker 
160*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
161*fb1b10abSAndroid Build Coastguard Worker   for (tile_row = 0; tile_row < multi_thread_ctxt->allocated_tile_rows;
162*fb1b10abSAndroid Build Coastguard Worker        tile_row++) {
163*fb1b10abSAndroid Build Coastguard Worker     for (tile_col = 0; tile_col < multi_thread_ctxt->allocated_tile_cols;
164*fb1b10abSAndroid Build Coastguard Worker          tile_col++) {
165*fb1b10abSAndroid Build Coastguard Worker       TileDataEnc *this_tile =
166*fb1b10abSAndroid Build Coastguard Worker           &cpi->tile_data[tile_row * multi_thread_ctxt->allocated_tile_cols +
167*fb1b10abSAndroid Build Coastguard Worker                           tile_col];
168*fb1b10abSAndroid Build Coastguard Worker       if (this_tile->row_base_thresh_freq_fact != NULL) {
169*fb1b10abSAndroid Build Coastguard Worker         vpx_free(this_tile->row_base_thresh_freq_fact);
170*fb1b10abSAndroid Build Coastguard Worker         this_tile->row_base_thresh_freq_fact = NULL;
171*fb1b10abSAndroid Build Coastguard Worker       }
172*fb1b10abSAndroid Build Coastguard Worker     }
173*fb1b10abSAndroid Build Coastguard Worker   }
174*fb1b10abSAndroid Build Coastguard Worker #endif
175*fb1b10abSAndroid Build Coastguard Worker 
176*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->allocated_tile_cols = 0;
177*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->allocated_tile_rows = 0;
178*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->allocated_vert_unit_rows = 0;
179*fb1b10abSAndroid Build Coastguard Worker }
180*fb1b10abSAndroid Build Coastguard Worker 
vp9_multi_thread_tile_init(VP9_COMP * cpi)181*fb1b10abSAndroid Build Coastguard Worker void vp9_multi_thread_tile_init(VP9_COMP *cpi) {
182*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
183*fb1b10abSAndroid Build Coastguard Worker   const int tile_cols = 1 << cm->log2_tile_cols;
184*fb1b10abSAndroid Build Coastguard Worker   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
185*fb1b10abSAndroid Build Coastguard Worker   int i;
186*fb1b10abSAndroid Build Coastguard Worker 
187*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < tile_cols; i++) {
188*fb1b10abSAndroid Build Coastguard Worker     TileDataEnc *this_tile = &cpi->tile_data[i];
189*fb1b10abSAndroid Build Coastguard Worker     int jobs_per_tile_col = cpi->oxcf.pass == 1 ? cm->mb_rows : sb_rows;
190*fb1b10abSAndroid Build Coastguard Worker 
191*fb1b10abSAndroid Build Coastguard Worker     // Initialize cur_col to -1 for all rows.
192*fb1b10abSAndroid Build Coastguard Worker     memset(this_tile->row_mt_sync.cur_col, -1,
193*fb1b10abSAndroid Build Coastguard Worker            sizeof(*this_tile->row_mt_sync.cur_col) * jobs_per_tile_col);
194*fb1b10abSAndroid Build Coastguard Worker     vp9_zero(this_tile->fp_data);
195*fb1b10abSAndroid Build Coastguard Worker     this_tile->fp_data.image_data_start_row = INVALID_ROW;
196*fb1b10abSAndroid Build Coastguard Worker   }
197*fb1b10abSAndroid Build Coastguard Worker }
198*fb1b10abSAndroid Build Coastguard Worker 
vp9_assign_tile_to_thread(MultiThreadHandle * multi_thread_ctxt,int tile_cols,int num_workers)199*fb1b10abSAndroid Build Coastguard Worker void vp9_assign_tile_to_thread(MultiThreadHandle *multi_thread_ctxt,
200*fb1b10abSAndroid Build Coastguard Worker                                int tile_cols, int num_workers) {
201*fb1b10abSAndroid Build Coastguard Worker   int tile_id = 0;
202*fb1b10abSAndroid Build Coastguard Worker   int i;
203*fb1b10abSAndroid Build Coastguard Worker 
204*fb1b10abSAndroid Build Coastguard Worker   // Allocating the threads for the tiles
205*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < num_workers; i++) {
206*fb1b10abSAndroid Build Coastguard Worker     multi_thread_ctxt->thread_id_to_tile_id[i] = tile_id++;
207*fb1b10abSAndroid Build Coastguard Worker     if (tile_id == tile_cols) tile_id = 0;
208*fb1b10abSAndroid Build Coastguard Worker   }
209*fb1b10abSAndroid Build Coastguard Worker }
210*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_job_queue_status(MultiThreadHandle * multi_thread_ctxt,int cur_tile_id)211*fb1b10abSAndroid Build Coastguard Worker int vp9_get_job_queue_status(MultiThreadHandle *multi_thread_ctxt,
212*fb1b10abSAndroid Build Coastguard Worker                              int cur_tile_id) {
213*fb1b10abSAndroid Build Coastguard Worker   RowMTInfo *row_mt_info;
214*fb1b10abSAndroid Build Coastguard Worker   JobQueueHandle *job_queue_hndl;
215*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
216*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_t *mutex;
217*fb1b10abSAndroid Build Coastguard Worker #endif
218*fb1b10abSAndroid Build Coastguard Worker   int num_jobs_remaining;
219*fb1b10abSAndroid Build Coastguard Worker 
220*fb1b10abSAndroid Build Coastguard Worker   row_mt_info = &multi_thread_ctxt->row_mt_info[cur_tile_id];
221*fb1b10abSAndroid Build Coastguard Worker   job_queue_hndl = &row_mt_info->job_queue_hdl;
222*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
223*fb1b10abSAndroid Build Coastguard Worker   mutex = &row_mt_info->job_mutex;
224*fb1b10abSAndroid Build Coastguard Worker #endif
225*fb1b10abSAndroid Build Coastguard Worker 
226*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
227*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_lock(mutex);
228*fb1b10abSAndroid Build Coastguard Worker #endif
229*fb1b10abSAndroid Build Coastguard Worker   num_jobs_remaining =
230*fb1b10abSAndroid Build Coastguard Worker       multi_thread_ctxt->jobs_per_tile_col - job_queue_hndl->num_jobs_acquired;
231*fb1b10abSAndroid Build Coastguard Worker #if CONFIG_MULTITHREAD
232*fb1b10abSAndroid Build Coastguard Worker   pthread_mutex_unlock(mutex);
233*fb1b10abSAndroid Build Coastguard Worker #endif
234*fb1b10abSAndroid Build Coastguard Worker 
235*fb1b10abSAndroid Build Coastguard Worker   return (num_jobs_remaining);
236*fb1b10abSAndroid Build Coastguard Worker }
237*fb1b10abSAndroid Build Coastguard Worker 
vp9_prepare_job_queue(VP9_COMP * cpi,JOB_TYPE job_type)238*fb1b10abSAndroid Build Coastguard Worker void vp9_prepare_job_queue(VP9_COMP *cpi, JOB_TYPE job_type) {
239*fb1b10abSAndroid Build Coastguard Worker   VP9_COMMON *const cm = &cpi->common;
240*fb1b10abSAndroid Build Coastguard Worker   MultiThreadHandle *multi_thread_ctxt = &cpi->multi_thread_ctxt;
241*fb1b10abSAndroid Build Coastguard Worker   JobQueue *job_queue = multi_thread_ctxt->job_queue;
242*fb1b10abSAndroid Build Coastguard Worker   const int tile_cols = 1 << cm->log2_tile_cols;
243*fb1b10abSAndroid Build Coastguard Worker   int job_row_num, jobs_per_tile, jobs_per_tile_col = 0, total_jobs;
244*fb1b10abSAndroid Build Coastguard Worker   const int sb_rows = mi_cols_aligned_to_sb(cm->mi_rows) >> MI_BLOCK_SIZE_LOG2;
245*fb1b10abSAndroid Build Coastguard Worker   int tile_col, i;
246*fb1b10abSAndroid Build Coastguard Worker 
247*fb1b10abSAndroid Build Coastguard Worker   switch (job_type) {
248*fb1b10abSAndroid Build Coastguard Worker     case ENCODE_JOB: jobs_per_tile_col = sb_rows; break;
249*fb1b10abSAndroid Build Coastguard Worker     case FIRST_PASS_JOB: jobs_per_tile_col = cm->mb_rows; break;
250*fb1b10abSAndroid Build Coastguard Worker     case ARNR_JOB:
251*fb1b10abSAndroid Build Coastguard Worker       jobs_per_tile_col = ((cm->mi_rows + TF_ROUND) >> TF_SHIFT);
252*fb1b10abSAndroid Build Coastguard Worker       break;
253*fb1b10abSAndroid Build Coastguard Worker     default: assert(0);
254*fb1b10abSAndroid Build Coastguard Worker   }
255*fb1b10abSAndroid Build Coastguard Worker 
256*fb1b10abSAndroid Build Coastguard Worker   total_jobs = jobs_per_tile_col * tile_cols;
257*fb1b10abSAndroid Build Coastguard Worker 
258*fb1b10abSAndroid Build Coastguard Worker   multi_thread_ctxt->jobs_per_tile_col = jobs_per_tile_col;
259*fb1b10abSAndroid Build Coastguard Worker   // memset the entire job queue buffer to zero
260*fb1b10abSAndroid Build Coastguard Worker   memset(job_queue, 0, total_jobs * sizeof(JobQueue));
261*fb1b10abSAndroid Build Coastguard Worker 
262*fb1b10abSAndroid Build Coastguard Worker   // Job queue preparation
263*fb1b10abSAndroid Build Coastguard Worker   for (tile_col = 0; tile_col < tile_cols; tile_col++) {
264*fb1b10abSAndroid Build Coastguard Worker     RowMTInfo *tile_ctxt = &multi_thread_ctxt->row_mt_info[tile_col];
265*fb1b10abSAndroid Build Coastguard Worker     JobQueue *job_queue_curr, *job_queue_temp;
266*fb1b10abSAndroid Build Coastguard Worker     int tile_row = 0;
267*fb1b10abSAndroid Build Coastguard Worker 
268*fb1b10abSAndroid Build Coastguard Worker     tile_ctxt->job_queue_hdl.next = (void *)job_queue;
269*fb1b10abSAndroid Build Coastguard Worker     tile_ctxt->job_queue_hdl.num_jobs_acquired = 0;
270*fb1b10abSAndroid Build Coastguard Worker 
271*fb1b10abSAndroid Build Coastguard Worker     job_queue_curr = job_queue;
272*fb1b10abSAndroid Build Coastguard Worker     job_queue_temp = job_queue;
273*fb1b10abSAndroid Build Coastguard Worker 
274*fb1b10abSAndroid Build Coastguard Worker     // loop over all the vertical rows
275*fb1b10abSAndroid Build Coastguard Worker     for (job_row_num = 0, jobs_per_tile = 0; job_row_num < jobs_per_tile_col;
276*fb1b10abSAndroid Build Coastguard Worker          job_row_num++, jobs_per_tile++) {
277*fb1b10abSAndroid Build Coastguard Worker       job_queue_curr->job_info.vert_unit_row_num = job_row_num;
278*fb1b10abSAndroid Build Coastguard Worker       job_queue_curr->job_info.tile_col_id = tile_col;
279*fb1b10abSAndroid Build Coastguard Worker       job_queue_curr->job_info.tile_row_id = tile_row;
280*fb1b10abSAndroid Build Coastguard Worker       job_queue_curr->next = (void *)(job_queue_temp + 1);
281*fb1b10abSAndroid Build Coastguard Worker       job_queue_curr = ++job_queue_temp;
282*fb1b10abSAndroid Build Coastguard Worker 
283*fb1b10abSAndroid Build Coastguard Worker       if (ENCODE_JOB == job_type) {
284*fb1b10abSAndroid Build Coastguard Worker         if (jobs_per_tile >=
285*fb1b10abSAndroid Build Coastguard Worker             multi_thread_ctxt->num_tile_vert_sbs[tile_row] - 1) {
286*fb1b10abSAndroid Build Coastguard Worker           tile_row++;
287*fb1b10abSAndroid Build Coastguard Worker           jobs_per_tile = -1;
288*fb1b10abSAndroid Build Coastguard Worker         }
289*fb1b10abSAndroid Build Coastguard Worker       }
290*fb1b10abSAndroid Build Coastguard Worker     }
291*fb1b10abSAndroid Build Coastguard Worker 
292*fb1b10abSAndroid Build Coastguard Worker     // Set the last pointer to NULL
293*fb1b10abSAndroid Build Coastguard Worker     job_queue_curr += -1;
294*fb1b10abSAndroid Build Coastguard Worker     job_queue_curr->next = (void *)NULL;
295*fb1b10abSAndroid Build Coastguard Worker 
296*fb1b10abSAndroid Build Coastguard Worker     // Move to the next tile
297*fb1b10abSAndroid Build Coastguard Worker     job_queue += jobs_per_tile_col;
298*fb1b10abSAndroid Build Coastguard Worker   }
299*fb1b10abSAndroid Build Coastguard Worker 
300*fb1b10abSAndroid Build Coastguard Worker   for (i = 0; i < cpi->num_workers; i++) {
301*fb1b10abSAndroid Build Coastguard Worker     EncWorkerData *thread_data;
302*fb1b10abSAndroid Build Coastguard Worker     thread_data = &cpi->tile_thr_data[i];
303*fb1b10abSAndroid Build Coastguard Worker     thread_data->thread_id = i;
304*fb1b10abSAndroid Build Coastguard Worker 
305*fb1b10abSAndroid Build Coastguard Worker     for (tile_col = 0; tile_col < tile_cols; tile_col++)
306*fb1b10abSAndroid Build Coastguard Worker       thread_data->tile_completion_status[tile_col] = 0;
307*fb1b10abSAndroid Build Coastguard Worker   }
308*fb1b10abSAndroid Build Coastguard Worker }
309*fb1b10abSAndroid Build Coastguard Worker 
vp9_get_tiles_proc_status(MultiThreadHandle * multi_thread_ctxt,int * tile_completion_status,int * cur_tile_id,int tile_cols)310*fb1b10abSAndroid Build Coastguard Worker int vp9_get_tiles_proc_status(MultiThreadHandle *multi_thread_ctxt,
311*fb1b10abSAndroid Build Coastguard Worker                               int *tile_completion_status, int *cur_tile_id,
312*fb1b10abSAndroid Build Coastguard Worker                               int tile_cols) {
313*fb1b10abSAndroid Build Coastguard Worker   int tile_col;
314*fb1b10abSAndroid Build Coastguard Worker   int tile_id = -1;  // Stores the tile ID with minimum proc done
315*fb1b10abSAndroid Build Coastguard Worker   int max_num_jobs_remaining = 0;
316*fb1b10abSAndroid Build Coastguard Worker   int num_jobs_remaining;
317*fb1b10abSAndroid Build Coastguard Worker 
318*fb1b10abSAndroid Build Coastguard Worker   // Mark the completion to avoid check in the loop
319*fb1b10abSAndroid Build Coastguard Worker   tile_completion_status[*cur_tile_id] = 1;
320*fb1b10abSAndroid Build Coastguard Worker   // Check for the status of all the tiles
321*fb1b10abSAndroid Build Coastguard Worker   for (tile_col = 0; tile_col < tile_cols; tile_col++) {
322*fb1b10abSAndroid Build Coastguard Worker     if (tile_completion_status[tile_col] == 0) {
323*fb1b10abSAndroid Build Coastguard Worker       num_jobs_remaining =
324*fb1b10abSAndroid Build Coastguard Worker           vp9_get_job_queue_status(multi_thread_ctxt, tile_col);
325*fb1b10abSAndroid Build Coastguard Worker       // Mark the completion to avoid checks during future switches across tiles
326*fb1b10abSAndroid Build Coastguard Worker       if (num_jobs_remaining == 0) tile_completion_status[tile_col] = 1;
327*fb1b10abSAndroid Build Coastguard Worker       if (num_jobs_remaining > max_num_jobs_remaining) {
328*fb1b10abSAndroid Build Coastguard Worker         max_num_jobs_remaining = num_jobs_remaining;
329*fb1b10abSAndroid Build Coastguard Worker         tile_id = tile_col;
330*fb1b10abSAndroid Build Coastguard Worker       }
331*fb1b10abSAndroid Build Coastguard Worker     }
332*fb1b10abSAndroid Build Coastguard Worker   }
333*fb1b10abSAndroid Build Coastguard Worker 
334*fb1b10abSAndroid Build Coastguard Worker   if (-1 == tile_id) {
335*fb1b10abSAndroid Build Coastguard Worker     return 1;
336*fb1b10abSAndroid Build Coastguard Worker   } else {
337*fb1b10abSAndroid Build Coastguard Worker     // Update the cur ID to the next tile ID that will be processed,
338*fb1b10abSAndroid Build Coastguard Worker     // which will be the least processed tile
339*fb1b10abSAndroid Build Coastguard Worker     *cur_tile_id = tile_id;
340*fb1b10abSAndroid Build Coastguard Worker     return 0;
341*fb1b10abSAndroid Build Coastguard Worker   }
342*fb1b10abSAndroid Build Coastguard Worker }
343