1 /******************************************************************************
2 *
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 /**
21 *******************************************************************************
22 * @file
23 * ihevce_multi_thread_funcs.c
24 *
25 * @brief
26 * Contains functions related to Job Ques and others, required for multi threading
27 *
28 * @author
29 * Ittiam
30 *
31 * @par List of Functions:
32 * <TODO: TO BE ADDED>
33 *
34 * @remarks
35 * None
36 *
37 *******************************************************************************
38 */
39 /*****************************************************************************/
40 /* File Includes */
41 /*****************************************************************************/
42 /* System include files */
43 #include <stdio.h>
44 #include <string.h>
45 #include <stdlib.h>
46 #include <assert.h>
47 #include <stdarg.h>
48 #include <math.h>
49
50 /* User include files */
51 #include "ihevc_typedefs.h"
52 #include "itt_video_api.h"
53 #include "ihevce_api.h"
54
55 #include "rc_cntrl_param.h"
56 #include "rc_frame_info_collector.h"
57 #include "rc_look_ahead_params.h"
58
59 #include "ihevc_defs.h"
60 #include "ihevc_structs.h"
61 #include "ihevc_platform_macros.h"
62 #include "ihevc_deblk.h"
63 #include "ihevc_itrans_recon.h"
64 #include "ihevc_chroma_itrans_recon.h"
65 #include "ihevc_chroma_intra_pred.h"
66 #include "ihevc_intra_pred.h"
67 #include "ihevc_inter_pred.h"
68 #include "ihevc_mem_fns.h"
69 #include "ihevc_padding.h"
70 #include "ihevc_weighted_pred.h"
71 #include "ihevc_sao.h"
72 #include "ihevc_resi_trans.h"
73 #include "ihevc_quant_iquant_ssd.h"
74 #include "ihevc_cabac_tables.h"
75
76 #include "ihevce_defs.h"
77 #include "ihevce_lap_enc_structs.h"
78 #include "ihevce_multi_thrd_structs.h"
79 #include "ihevce_multi_thrd_funcs.h"
80 #include "ihevce_me_common_defs.h"
81 #include "ihevce_had_satd.h"
82 #include "ihevce_error_codes.h"
83 #include "ihevce_bitstream.h"
84 #include "ihevce_cabac.h"
85 #include "ihevce_rdoq_macros.h"
86 #include "ihevce_function_selector.h"
87 #include "ihevce_enc_structs.h"
88 #include "ihevce_entropy_structs.h"
89 #include "ihevce_cmn_utils_instr_set_router.h"
90 #include "ihevce_enc_loop_structs.h"
91 #include "ihevce_bs_compute_ctb.h"
92 #include "ihevce_global_tables.h"
93 #include "ihevce_dep_mngr_interface.h"
94 #include "hme_datatype.h"
95 #include "hme_interface.h"
96 #include "hme_common_defs.h"
97 #include "hme_defs.h"
98 #include "ihevce_me_instr_set_router.h"
99 #include "ihevce_ipe_instr_set_router.h"
100 #include "ihevce_ipe_structs.h"
101 #include "ihevce_coarse_me_pass.h"
102
103 #include "cast_types.h"
104 #include "osal.h"
105 #include "osal_defaults.h"
106
107 /********************************************************************/
108 /*Macros */
109 /********************************************************************/
110 #define MULT_FACT 100
111
112 /*****************************************************************************/
113 /* Function Definitions */
114 /*****************************************************************************/
115
116 /**
117 *******************************************************************************
118 *
119 * @brief Function Pops out the next Job in the appropriate Job Que
120 *
121 * @par Description: Does under mutex lock to ensure thread safe
122 *
123 * @param[inout] pv_multi_thrd_ctxt
124 * Pointer to Multi thread context
125 *
126 * @param[in] i4_job_type
127 * Job type from which a job needs to be popped out
128 *
129 * @param[in] i4_blocking_mode
130 * Mode of operation
131 *
132 * @returns
133 * None
134 *
135 * @remarks
136 *
137 *******************************************************************************
138 */
ihevce_pre_enc_grp_get_next_job(void * pv_multi_thrd_ctxt,WORD32 i4_job_type,WORD32 i4_blocking_mode,WORD32 i4_ping_pong)139 void *ihevce_pre_enc_grp_get_next_job(
140 void *pv_multi_thrd_ctxt, WORD32 i4_job_type, WORD32 i4_blocking_mode, WORD32 i4_ping_pong)
141 {
142 /* Local variables */
143 multi_thrd_ctxt_t *ps_multi_thrd;
144 job_queue_handle_t *ps_job_queue_hdl;
145 void *pv_next = NULL;
146 UWORD8 au1_in_dep_cmp[MAX_IN_DEP] = { 0 };
147 void *pv_job_q_mutex_hdl_pre_enc = NULL;
148
149 /* Derive local variables */
150 ps_multi_thrd = (multi_thrd_ctxt_t *)pv_multi_thrd_ctxt;
151 ps_job_queue_hdl =
152 (job_queue_handle_t *)&ps_multi_thrd->as_job_que_preenc_hdls[i4_ping_pong][i4_job_type];
153
154 /* lock the mutex for Q access */
155 /* As design must facilitate for parallelism in each stage,
156 It is recommended to have seperate mutex for each stage*/
157 if(i4_job_type < ME_JOB_LYR4)
158 {
159 pv_job_q_mutex_hdl_pre_enc = ps_multi_thrd->pv_job_q_mutex_hdl_pre_enc_decomp;
160 }
161 else if(i4_job_type < IPE_JOB_LYR0)
162 {
163 pv_job_q_mutex_hdl_pre_enc = ps_multi_thrd->pv_job_q_mutex_hdl_pre_enc_hme;
164 }
165 else
166 {
167 pv_job_q_mutex_hdl_pre_enc = ps_multi_thrd->pv_job_q_mutex_hdl_pre_enc_l0ipe;
168 }
169
170 osal_mutex_lock(pv_job_q_mutex_hdl_pre_enc);
171 /* Get the next */
172 pv_next = ps_job_queue_hdl->pv_next;
173
174 /* Update the next by checking input dependency */
175 if(NULL != pv_next)
176 {
177 job_queue_t *ps_job_queue = (job_queue_t *)pv_next;
178
179 /* check for input dependencies to be resolved */
180 /* this can be blocking or non blocking based on use case */
181 /* if non blocking then the function returns NULL */
182
183 if(1 == i4_blocking_mode)
184 {
185 volatile WORD32 mem_diff;
186 volatile UWORD8 *pu1_ref_buf = &au1_in_dep_cmp[0];
187 volatile UWORD8 *pu1_curr_buf = &ps_job_queue->au1_in_dep[0];
188
189 mem_diff = memcmp((void *)pu1_ref_buf, (void *)pu1_curr_buf, MAX_IN_DEP);
190
191 /* wait until all dependency is resolved */
192 while(0 != mem_diff)
193 {
194 mem_diff = memcmp((void *)pu1_ref_buf, (void *)pu1_curr_buf, MAX_IN_DEP);
195 }
196
197 /* update the next job in the queue */
198 ps_job_queue_hdl->pv_next = ps_job_queue->pv_next;
199 }
200 else
201 {
202 /* check for input dependency resolved */
203 if((0 != memcmp(&au1_in_dep_cmp[0], &ps_job_queue->au1_in_dep[0], MAX_IN_DEP)))
204 {
205 /* return null */
206 pv_next = NULL;
207 }
208 else
209 {
210 /* update the next job in the queue */
211 ps_job_queue_hdl->pv_next = ps_job_queue->pv_next;
212 }
213 }
214 }
215
216 /* unlock the mutex */
217 osal_mutex_unlock(pv_job_q_mutex_hdl_pre_enc);
218
219 /* Return */
220 return (pv_next);
221
222 } /* End of get_next_job */
223
224 /**
225 *******************************************************************************
226 *
227 * @brief Function Pops out the next Job in the appropriate Job Que
228 *
229 * @par Description: Does under mutex lock to ensure thread safe
230 *
231 * @param[inout] pv_multi_thrd_ctxt
232 * Pointer to Multi thread context
233 *
234 * @param[in] i4_job_type
235 * Job type from which a job needs to be popped out
236 *
237 * @param[in] i4_blocking_mode
238 * Mode of operation
239 *
240 * @returns
241 * None
242 *
243 * @remarks
244 *
245 *******************************************************************************
246 */
ihevce_enc_grp_get_next_job(void * pv_multi_thrd_ctxt,WORD32 i4_job_type,WORD32 i4_blocking_mode,WORD32 i4_curr_frm_id)247 void *ihevce_enc_grp_get_next_job(
248 void *pv_multi_thrd_ctxt, WORD32 i4_job_type, WORD32 i4_blocking_mode, WORD32 i4_curr_frm_id)
249 {
250 /* Local variables */
251 multi_thrd_ctxt_t *ps_multi_thrd;
252 job_queue_handle_t *ps_job_queue_hdl;
253 void *pv_next = NULL;
254 void *pv_job_q_mutex_hdl_enc_grp;
255 UWORD8 au1_in_dep_cmp[MAX_IN_DEP] = { 0 };
256
257 /* Derive local variables */
258 ps_multi_thrd = (multi_thrd_ctxt_t *)pv_multi_thrd_ctxt;
259
260 if(ME_JOB_ENC_LYR == i4_job_type)
261 {
262 pv_job_q_mutex_hdl_enc_grp = ps_multi_thrd->pv_job_q_mutex_hdl_enc_grp_me;
263
264 ps_job_queue_hdl = (job_queue_handle_t *)&ps_multi_thrd->aps_cur_out_me_prms[i4_curr_frm_id]
265 ->as_job_que_enc_hdls[i4_job_type];
266 }
267 else
268 {
269 pv_job_q_mutex_hdl_enc_grp = ps_multi_thrd->pv_job_q_mutex_hdl_enc_grp_enc_loop;
270 ps_job_queue_hdl =
271 (job_queue_handle_t *)&ps_multi_thrd->aps_cur_inp_enc_prms[i4_curr_frm_id]
272 ->as_job_que_enc_hdls[i4_job_type];
273 }
274
275 /* lock the mutex for Q access */
276 osal_mutex_lock(pv_job_q_mutex_hdl_enc_grp);
277
278 /* Get the next */
279 pv_next = ps_job_queue_hdl->pv_next;
280
281 /* Update the next by checking input dependency */
282 if(NULL != pv_next)
283 {
284 job_queue_t *ps_job_queue = (job_queue_t *)pv_next;
285
286 /* check for input dependencies to be resolved */
287 /* this can be blocking or non blocking based on use case */
288 /* if non blocking then the function returns NULL */
289
290 if(1 == i4_blocking_mode)
291 {
292 volatile WORD32 mem_diff;
293 volatile UWORD8 *pu1_ref_buf = &au1_in_dep_cmp[0];
294 volatile UWORD8 *pu1_curr_buf = &ps_job_queue->au1_in_dep[0];
295
296 mem_diff = memcmp((void *)pu1_ref_buf, (void *)pu1_curr_buf, MAX_IN_DEP);
297
298 /* wait until all dependency is resolved */
299 while(0 != mem_diff)
300 {
301 mem_diff = memcmp((void *)pu1_ref_buf, (void *)pu1_curr_buf, MAX_IN_DEP);
302 }
303
304 /* update the next job in the queue */
305 ps_job_queue_hdl->pv_next = ps_job_queue->pv_next;
306 }
307 else
308 {
309 /* check for input dependency resolved */
310 if((0 != memcmp(&au1_in_dep_cmp[0], &ps_job_queue->au1_in_dep[0], MAX_IN_DEP)))
311 {
312 /* return null */
313 pv_next = NULL;
314 }
315 else
316 {
317 /* update the next job in the queue */
318 ps_job_queue_hdl->pv_next = ps_job_queue->pv_next;
319 }
320 }
321 }
322
323 /* unlock the mutex */
324 osal_mutex_unlock(pv_job_q_mutex_hdl_enc_grp);
325
326 /* Return */
327 return (pv_next);
328
329 } /* End of get_next_job */
330
331 /**
332 *******************************************************************************
333 *
334 * @brief Set the output dependency to done state
335 *
336 * @par Description: same as brief
337 *
338 * @param[inout] pv_multi_thrd_ctxt
339 * Pointer to Multi thread context
340 *
341 * @param[in] ps_curr_job
342 * Current finished Job pointer
343 *
344 * @returns
345 * None
346 *
347 * @remarks
348 *
349 *******************************************************************************
350 */
ihevce_pre_enc_grp_job_set_out_dep(void * pv_multi_thrd_ctxt,job_queue_t * ps_curr_job,WORD32 i4_ping_pong)351 void ihevce_pre_enc_grp_job_set_out_dep(
352 void *pv_multi_thrd_ctxt, job_queue_t *ps_curr_job, WORD32 i4_ping_pong)
353 {
354 /* local vareiables */
355 WORD32 ctr;
356 multi_thrd_ctxt_t *ps_multi_thrd;
357
358 ps_multi_thrd = (multi_thrd_ctxt_t *)pv_multi_thrd_ctxt;
359
360 /* loop over number output dependencies */
361 for(ctr = 0; ctr < ps_curr_job->i4_num_output_dep; ctr++)
362 {
363 UWORD8 *pu1_ptr;
364
365 pu1_ptr = (UWORD8 *)ps_multi_thrd->aps_job_q_pre_enc[i4_ping_pong];
366 pu1_ptr += ps_curr_job->au4_out_ofsts[ctr];
367 *pu1_ptr = 0;
368 }
369
370 return;
371 }
372
373 /**
374 *******************************************************************************
375 *
376 * @brief Set the output dependency to done state
377 *
378 * @par Description: same as brief
379 *
380 * @param[inout] pv_multi_thrd_ctxt
381 * Pointer to Multi thread context
382 *
383 * @param[in] ps_curr_job
384 * Current finished Job pointer
385 *
386 * @returns
387 * None
388 *
389 * @remarks
390 *
391 *******************************************************************************
392 */
ihevce_enc_grp_job_set_out_dep(void * pv_multi_thrd_ctxt,job_queue_t * ps_curr_job,WORD32 i4_curr_frm_id)393 void ihevce_enc_grp_job_set_out_dep(
394 void *pv_multi_thrd_ctxt, job_queue_t *ps_curr_job, WORD32 i4_curr_frm_id)
395 {
396 /* local vareiables */
397 WORD32 ctr;
398 UWORD8 *pu1_ptr;
399 multi_thrd_ctxt_t *ps_multi_thrd;
400
401 ps_multi_thrd = (multi_thrd_ctxt_t *)pv_multi_thrd_ctxt;
402
403 if(ME_JOB_ENC_LYR == ps_curr_job->i4_task_type)
404 {
405 pu1_ptr = (UWORD8 *)ps_multi_thrd->aps_cur_out_me_prms[i4_curr_frm_id]->ps_job_q_enc;
406 }
407 else
408 {
409 pu1_ptr = (UWORD8 *)ps_multi_thrd->aps_cur_inp_enc_prms[i4_curr_frm_id]->ps_job_q_enc;
410 }
411
412 /* loop over number output dependencies */
413 for(ctr = 0; ctr < ps_curr_job->i4_num_output_dep; ctr++)
414 {
415 WORD32 i4_off;
416 i4_off = ps_curr_job->au4_out_ofsts[ctr];
417 pu1_ptr[i4_off] = 0;
418 }
419
420 return;
421 }
422
423 /**
424 *******************************************************************************
425 *
426 * @brief Function prepares the Job Queues for all the passes of encoder
427 *
428 * @par Description: Based on picture type sets the input and output dependency
429 *
430 * @param[inout] pv_enc_ctxt
431 * Pointer to encoder context
432 *
433 * @param[in] ps_curr_inp
434 * Current Input buffer pointer
435 *
436 * @returns
437 * None
438 *
439 * @remarks
440 *
441 *******************************************************************************
442 */
ihevce_prepare_job_queue(void * pv_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,WORD32 i4_curr_frm_id)443 void ihevce_prepare_job_queue(
444 void *pv_enc_ctxt, ihevce_lap_enc_buf_t *ps_curr_inp, WORD32 i4_curr_frm_id)
445 {
446 /* local variables */
447 enc_ctxt_t *ps_ctxt;
448 job_queue_t *ps_me_job_queue_lyr0;
449 job_queue_t *ps_enc_loop_job_queue;
450 WORD32 pass;
451 WORD32 num_jobs, col_tile_ctr;
452 WORD32 num_ctb_vert_rows;
453 WORD32 i4_pic_type;
454 WORD32 i; //counter for bitrate
455 WORD32 i4_num_bitrate_instances;
456 WORD32 i4_num_tile_col;
457
458 /* derive local varaibles */
459 ps_ctxt = (enc_ctxt_t *)pv_enc_ctxt;
460 num_ctb_vert_rows = ps_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert;
461 i4_num_bitrate_instances = ps_ctxt->i4_num_bitrates;
462
463 i4_num_tile_col = 1;
464 if(1 == ps_ctxt->ps_tile_params_base->i4_tiles_enabled_flag)
465 {
466 i4_num_tile_col = ps_ctxt->ps_tile_params_base->i4_num_tile_cols;
467 }
468 /* memset the entire job que buffer to zero */
469 memset(
470 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]->ps_job_q_enc,
471 0,
472 MAX_NUM_VERT_UNITS_FRM * NUM_ENC_JOBS_QUES * i4_num_tile_col * sizeof(job_queue_t));
473
474 /* get the start address of Job queues */
475 ps_me_job_queue_lyr0 = ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]->ps_job_q_enc;
476 ps_enc_loop_job_queue = ps_me_job_queue_lyr0 + (i4_num_tile_col * MAX_NUM_VERT_UNITS_FRM);
477
478 /* store the JOB queue in the Job handle */
479 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
480 ->as_job_que_enc_hdls[ME_JOB_ENC_LYR]
481 .pv_next = (void *)ps_me_job_queue_lyr0;
482 /* store the JOB queue in the Job handle for reenc */
483 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
484 ->as_job_que_enc_hdls_reenc[ME_JOB_ENC_LYR]
485 .pv_next = (void *)ps_me_job_queue_lyr0;
486
487 for(i = 0; i < i4_num_bitrate_instances; i++)
488 {
489 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
490 ->as_job_que_enc_hdls[ENC_LOOP_JOB + i]
491 .pv_next = (void *)ps_enc_loop_job_queue;
492 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
493 ->as_job_que_enc_hdls_reenc[ENC_LOOP_JOB + i]
494 .pv_next = (void *)ps_enc_loop_job_queue;
495 ps_enc_loop_job_queue += (i4_num_tile_col * MAX_NUM_VERT_UNITS_FRM);
496 }
497
498 i4_pic_type = ps_curr_inp->s_lap_out.i4_pic_type;
499
500 //prepare ME JOB queue first
501 //for(pass = 0; pass < NUM_ENC_JOBS_QUES; pass++)
502 {
503 job_queue_t *ps_job_queue_curr;
504 job_queue_t *ps_job_queue_next;
505 WORD32 ctr;
506 WORD32 inp_dep;
507 WORD32 out_dep;
508 WORD32 num_vert_units;
509 HEVCE_ENC_JOB_TYPES_T task_type;
510
511 pass = 0; //= ENC_LOOP_JOB
512
513 {
514 /* num_ver_units of finest layer is stored at (num_hme_lyrs - 1)th index */
515 num_vert_units = num_ctb_vert_rows;
516 task_type = ME_JOB_ENC_LYR;
517 ps_job_queue_curr = ps_me_job_queue_lyr0;
518 ps_job_queue_next =
519 (job_queue_t *)ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
520 ->as_job_que_enc_hdls[ENC_LOOP_JOB]
521 .pv_next;
522 inp_dep = 0;
523 out_dep = 1; //set reference bit-rate's input dependency
524 }
525
526 if((ME_JOB_ENC_LYR == pass) &&
527 ((IV_I_FRAME == i4_pic_type) || (IV_IDR_FRAME == i4_pic_type)) && !L0ME_IN_OPENLOOP_MODE)
528 {
529 //continue;
530 }
531 else
532 {
533 /* loop over all the vertical rows */
534 for(num_jobs = 0; num_jobs < num_vert_units; num_jobs++)
535 {
536 /* loop over all the column tiles */
537 for(col_tile_ctr = 0; col_tile_ctr < i4_num_tile_col; col_tile_ctr++)
538 {
539 ULWORD64 u8_temp;
540
541 {
542 ps_job_queue_curr->s_job_info.s_me_job_info.i4_vert_unit_row_no = num_jobs;
543 ps_job_queue_curr->s_job_info.s_me_job_info.i4_tile_col_idx = col_tile_ctr;
544 }
545
546 ps_job_queue_curr->pv_next = (void *)(ps_job_queue_curr + 1);
547
548 ps_job_queue_curr->i4_task_type = task_type;
549
550 ps_job_queue_curr->i4_num_input_dep = inp_dep;
551
552 /* set the entire input dep buffer to default value 0 */
553 memset(&ps_job_queue_curr->au1_in_dep[0], 0, sizeof(UWORD8) * MAX_IN_DEP);
554
555 /* set the input dep buffer to 1 for num inp dep */
556 if(0 != inp_dep)
557 {
558 memset(&ps_job_queue_curr->au1_in_dep[0], 1, sizeof(UWORD8) * inp_dep);
559 }
560
561 ps_job_queue_curr->i4_num_output_dep = out_dep;
562
563 /* set the entire offset buffer to default value */
564 memset(
565 &ps_job_queue_curr->au4_out_ofsts[0], 0xFF, sizeof(UWORD32) * MAX_OUT_DEP);
566
567 for(ctr = 0; ctr < out_dep; ctr++)
568 {
569 /* col tile level dependency b/w ME & EncLoop */
570 u8_temp = (ULWORD64)(
571 &ps_job_queue_next[num_jobs * i4_num_tile_col + col_tile_ctr] -
572 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]->ps_job_q_enc);
573
574 u8_temp *= sizeof(job_queue_t);
575
576 /* store the offset to the array */
577 ps_job_queue_curr->au4_out_ofsts[ctr] = (UWORD32)u8_temp;
578 }
579
580 ps_job_queue_curr++;
581 }
582 } //for ends
583
584 /* set the last pointer to NULL */
585 ps_job_queue_curr--;
586 ps_job_queue_curr->pv_next = (void *)NULL;
587 } //else ends
588 }
589
590 //prepare Enc_loop JOB queue for all bitrate instances
591 //for(pass = 0; pass < NUM_ENC_JOBS_QUES; pass++)
592 for(i = 0; i < i4_num_bitrate_instances; i++)
593 {
594 job_queue_t *ps_job_queue_curr;
595 job_queue_t *ps_job_queue_next;
596 WORD32 ctr;
597 WORD32 inp_dep;
598 WORD32 out_dep;
599 WORD32 num_vert_units;
600 HEVCE_ENC_JOB_TYPES_T task_type;
601
602 /* In case of I or IDR pictures ME will not perform any processing */
603 //if(ENC_LOOP_JOB == pass)
604 {
605 if(((IV_I_FRAME == i4_pic_type) || (IV_IDR_FRAME == i4_pic_type)) &&
606 !L0ME_IN_OPENLOOP_MODE)
607 {
608 inp_dep = 0;
609 }
610 else
611 {
612 inp_dep = 1;
613 }
614
615 task_type = (HEVCE_ENC_JOB_TYPES_T)(ENC_LOOP_JOB + i);
616 ps_job_queue_curr =
617 (job_queue_t *)ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
618 ->as_job_que_enc_hdls[ENC_LOOP_JOB + i]
619 .pv_next;
620 ps_job_queue_next =
621 (job_queue_t *)ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]
622 ->as_job_que_enc_hdls[ENC_LOOP_JOB + i + 1]
623 .pv_next;
624 out_dep = 1; //output dependecny is the next bit-rate instance's input dependency
625 num_vert_units = num_ctb_vert_rows;
626
627 if(i == i4_num_bitrate_instances - 1) //for last bit-rate instance
628 {
629 //clear output dependency
630 ps_job_queue_next = NULL;
631 out_dep = 0;
632 }
633 }
634
635 /* loop over all the vertical rows */
636 for(num_jobs = 0; num_jobs < num_vert_units; num_jobs++)
637 {
638 /* loop over all the column tiles */
639 for(col_tile_ctr = 0; col_tile_ctr < i4_num_tile_col; col_tile_ctr++)
640 {
641 ULWORD64 u8_temp;
642
643 {
644 ps_job_queue_curr->s_job_info.s_enc_loop_job_info.i4_ctb_row_no = num_jobs;
645 ps_job_queue_curr->s_job_info.s_enc_loop_job_info.i4_tile_col_idx =
646 col_tile_ctr;
647 ps_job_queue_curr->s_job_info.s_enc_loop_job_info.i4_bitrate_instance_no = i;
648 }
649
650 ps_job_queue_curr->pv_next = (void *)(ps_job_queue_curr + 1);
651
652 ps_job_queue_curr->i4_task_type = task_type;
653
654 ps_job_queue_curr->i4_num_input_dep = inp_dep;
655
656 /* set the entire input dep buffer to default value 0 */
657 memset(&ps_job_queue_curr->au1_in_dep[0], 0, sizeof(UWORD8) * MAX_IN_DEP);
658
659 /* set the input dep buffer to 1 for num inp dep */
660 if(0 != inp_dep)
661 {
662 memset(&ps_job_queue_curr->au1_in_dep[0], 1, sizeof(UWORD8) * inp_dep);
663 }
664
665 ps_job_queue_curr->i4_num_output_dep = out_dep;
666
667 /* set the entire offset buffer to default value */
668 memset(&ps_job_queue_curr->au4_out_ofsts[0], 0xFF, sizeof(UWORD32) * MAX_OUT_DEP);
669
670 for(ctr = 0; ctr < out_dep; ctr++)
671 {
672 /* col tile level dependency b/w EncLoops of MBR */
673 u8_temp = (ULWORD64)(
674 &ps_job_queue_next[num_jobs * i4_num_tile_col + col_tile_ctr] -
675 ps_ctxt->s_multi_thrd.aps_cur_out_me_prms[i4_curr_frm_id]->ps_job_q_enc);
676
677 u8_temp *= sizeof(job_queue_t);
678
679 /* store the offset to the array */
680 ps_job_queue_curr->au4_out_ofsts[ctr] = (UWORD32)u8_temp;
681 }
682
683 ps_job_queue_curr++;
684 }
685 }
686
687 /* set the last pointer to NULL */
688 ps_job_queue_curr--;
689 ps_job_queue_curr->pv_next = (void *)NULL;
690 }
691
692 return;
693
694 } /* End of ihevce_prepare_job_queue */
695
696 /**
697 *******************************************************************************
698 *
699 * @brief Function prepares the Job Queues for all the passes of pre enc
700 *
701 * @par Description: Based on picture type sets the input and output dependency
702 *
703 * @param[inout] pv_enc_ctxt
704 * Pointer to encoder context
705 *
706 * @param[in] ps_curr_inp
707 * Current Input buffer pointer
708 *
709 * @returns
710 * None
711 *
712 * @remarks
713 *
714 *******************************************************************************
715 */
ihevce_prepare_pre_enc_job_queue(void * pv_enc_ctxt,ihevce_lap_enc_buf_t * ps_curr_inp,WORD32 i4_ping_pong)716 void ihevce_prepare_pre_enc_job_queue(
717 void *pv_enc_ctxt, ihevce_lap_enc_buf_t *ps_curr_inp, WORD32 i4_ping_pong)
718 {
719 /* local variables */
720 enc_ctxt_t *ps_ctxt;
721 job_queue_t *ps_decomp_job_queue_lyr0;
722 job_queue_t *ps_decomp_job_queue_lyr1;
723 job_queue_t *ps_decomp_job_queue_lyr2;
724 job_queue_t *ps_decomp_job_queue_lyr3;
725 job_queue_t *ps_me_job_queue_lyr1;
726 job_queue_t *ps_me_job_queue_lyr2;
727 job_queue_t *ps_me_job_queue_lyr3;
728 job_queue_t *ps_me_job_queue_lyr4;
729 job_queue_t *ps_ipe_job_queue;
730 job_queue_t *aps_me_job_queues[MAX_NUM_HME_LAYERS];
731 multi_thrd_me_job_q_prms_t *ps_me_job_q_prms;
732 WORD32 ai4_decomp_num_vert_units_lyr[MAX_NUM_HME_LAYERS];
733 WORD32 a14_decomp_lyr_unit_size[MAX_NUM_HME_LAYERS];
734 WORD32 layer_no;
735 WORD32 decomp_lyr_cnt;
736 WORD32 num_jobs;
737 WORD32 n_tot_layers;
738 WORD32 a_wd[MAX_NUM_HME_LAYERS];
739 WORD32 a_ht[MAX_NUM_HME_LAYERS];
740 WORD32 a_disp_wd[MAX_NUM_HME_LAYERS];
741 WORD32 a_disp_ht[MAX_NUM_HME_LAYERS];
742 WORD32 u4_log_ctb_size;
743 WORD32 num_ctb_vert_rows;
744 WORD32 pass;
745 WORD32 me_lyr_cnt;
746 WORD32 num_hme_lyrs;
747 WORD32 ai4_me_num_vert_units_lyr[MAX_NUM_HME_LAYERS];
748 WORD32 me_start_lyr_pass;
749 WORD32 ctb_size;
750 WORD32 me_coarsest_lyr_inp_dep = -1;
751
752 (void)ps_curr_inp;
753 /* derive local varaibles */
754 ps_ctxt = (enc_ctxt_t *)pv_enc_ctxt;
755 num_ctb_vert_rows = ps_ctxt->s_frm_ctb_prms.i4_num_ctbs_vert;
756
757 /* CHANGE REQUIRED: change the pointer to the job queue buffer */
758 /* memset the entire job que buffer to zero */
759 memset(
760 ps_ctxt->s_multi_thrd.aps_job_q_pre_enc[i4_ping_pong],
761 0,
762 MAX_NUM_VERT_UNITS_FRM * NUM_PRE_ENC_JOBS_QUES * sizeof(job_queue_t));
763
764 /* Get the number of vertical units in a layer from the resolution of the layer */
765 a_wd[0] = ps_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_wd;
766 a_ht[0] = ps_ctxt->s_frm_ctb_prms.i4_cu_aligned_pic_ht;
767 n_tot_layers = hme_derive_num_layers(1, a_wd, a_ht, a_disp_wd, a_disp_ht);
768 GETRANGE(u4_log_ctb_size, ps_ctxt->s_frm_ctb_prms.i4_ctb_size);
769
770 ASSERT(n_tot_layers >= 3);
771
772 /*
773 * Always force minimum layers as 4 so that we would have both l1 and l2
774 * pre intra analysis
775 */
776 if(n_tot_layers == 3)
777 {
778 n_tot_layers = 4;
779 a_wd[3] = CEIL16(a_wd[2] >> 1);
780 a_ht[3] = CEIL16(a_ht[2] >> 1);
781 }
782
783 for(layer_no = 0; layer_no < n_tot_layers; layer_no++)
784 {
785 ctb_size = 1 << (u4_log_ctb_size - 1 - layer_no);
786 ai4_decomp_num_vert_units_lyr[layer_no] = ((a_ht[layer_no] + ctb_size) & ~(ctb_size - 1)) >>
787 (u4_log_ctb_size - 1 - layer_no);
788 a14_decomp_lyr_unit_size[layer_no] = 1 << (u4_log_ctb_size - 1 - layer_no);
789 }
790
791 /* get the start address of Job queues */
792 ps_decomp_job_queue_lyr0 = ps_ctxt->s_multi_thrd.aps_job_q_pre_enc[i4_ping_pong];
793 ps_decomp_job_queue_lyr1 = ps_decomp_job_queue_lyr0 + MAX_NUM_VERT_UNITS_FRM;
794 ps_decomp_job_queue_lyr2 = ps_decomp_job_queue_lyr1 + MAX_NUM_VERT_UNITS_FRM;
795 ps_decomp_job_queue_lyr3 = ps_decomp_job_queue_lyr2 + MAX_NUM_VERT_UNITS_FRM;
796 ps_me_job_queue_lyr4 = ps_decomp_job_queue_lyr3 + MAX_NUM_VERT_UNITS_FRM;
797 ps_me_job_queue_lyr3 = ps_me_job_queue_lyr4 + MAX_NUM_VERT_UNITS_FRM;
798 ps_me_job_queue_lyr2 = ps_me_job_queue_lyr3 + MAX_NUM_VERT_UNITS_FRM;
799 ps_me_job_queue_lyr1 = ps_me_job_queue_lyr2 + MAX_NUM_VERT_UNITS_FRM;
800
801 ps_ipe_job_queue = ps_me_job_queue_lyr1 + MAX_NUM_VERT_UNITS_FRM;
802
803 /* store the JOB queue in the Job handle */
804 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][DECOMP_JOB_LYR0].pv_next =
805 (void *)ps_decomp_job_queue_lyr0;
806 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][DECOMP_JOB_LYR1].pv_next =
807 (void *)ps_decomp_job_queue_lyr1;
808 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][DECOMP_JOB_LYR2].pv_next =
809 (void *)ps_decomp_job_queue_lyr2;
810 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][DECOMP_JOB_LYR3].pv_next =
811 (void *)ps_decomp_job_queue_lyr3;
812 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][ME_JOB_LYR4].pv_next =
813 (void *)ps_me_job_queue_lyr4;
814 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][ME_JOB_LYR3].pv_next =
815 (void *)ps_me_job_queue_lyr3;
816 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][ME_JOB_LYR2].pv_next =
817 (void *)ps_me_job_queue_lyr2;
818 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][ME_JOB_LYR1].pv_next =
819 (void *)ps_me_job_queue_lyr1;
820 ps_ctxt->s_multi_thrd.as_job_que_preenc_hdls[i4_ping_pong][IPE_JOB_LYR0].pv_next =
821 (void *)ps_ipe_job_queue;
822
823 /* store the ME Jobs que into array */
824 aps_me_job_queues[0] = NULL;
825 aps_me_job_queues[1] = ps_me_job_queue_lyr1;
826 aps_me_job_queues[2] = ps_me_job_queue_lyr2;
827 aps_me_job_queues[3] = ps_me_job_queue_lyr3;
828 aps_me_job_queues[4] = ps_me_job_queue_lyr4;
829 decomp_lyr_cnt = 0;
830 /* Set the me_lyr_cnt to 0 */
831 me_lyr_cnt = 0;
832
833 /* call the ME function which returns the layer properties */
834 ihevce_coarse_me_get_lyr_prms_job_que(
835 ps_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
836 ps_curr_inp,
837 &num_hme_lyrs,
838 &ai4_me_num_vert_units_lyr[0],
839 &ps_ctxt->s_multi_thrd.as_me_job_q_prms[0][0]);
840
841 ps_me_job_q_prms = &ps_ctxt->s_multi_thrd.as_me_job_q_prms[0][0];
842
843 /* derive ME coarsest layer tak type */
844 me_start_lyr_pass = ME_JOB_LYR4 + (MAX_NUM_HME_LAYERS - num_hme_lyrs);
845
846 ps_ctxt->s_multi_thrd.i4_me_coarsest_lyr_type = me_start_lyr_pass;
847
848 /* coarsest HME layer number of units should be less than or equal to max in dep in Job queue */
849 /* this constraint is to take care of Coarsest layer requring entire layer to do FULL search */
850 ASSERT(ai4_me_num_vert_units_lyr[0] <= MAX_IN_DEP);
851 /* loop over all the passes in the encoder */
852 for(pass = 0; pass < NUM_PRE_ENC_JOBS_QUES; pass++)
853 {
854 job_queue_t *ps_pre_enc_job_queue_curr;
855 job_queue_t *ps_pre_enc_job_queue_next;
856 WORD32 inp_dep_pass;
857 WORD32 out_dep_pass;
858 WORD32 num_vert_units;
859 HEVCE_PRE_ENC_JOB_TYPES_T pre_enc_task_type;
860 HEVCE_ENC_JOB_TYPES_T enc_task_type;
861 WORD32 proc_valid_flag = 0;
862
863 // num_vert_units = ai4_decomp_num_vert_units_lyr[decomp_lyr_cnt];
864 /* Initializing the job queues for max no of rows among all the layers. And max would be for last layer*/
865 num_vert_units = ai4_decomp_num_vert_units_lyr[n_tot_layers - 1];
866
867 if(DECOMP_JOB_LYR0 == pass)
868 {
869 proc_valid_flag = 1;
870 pre_enc_task_type = DECOMP_JOB_LYR0;
871 enc_task_type = (HEVCE_ENC_JOB_TYPES_T)-1;
872 ps_pre_enc_job_queue_curr = ps_decomp_job_queue_lyr0;
873
874 inp_dep_pass = 0;
875 decomp_lyr_cnt++;
876
877 /* If all the decomp layers are done next job queue will be ME job queue */
878 if(decomp_lyr_cnt == (n_tot_layers - 1))
879 {
880 /* Assumption : num_hme_lyrs > 1*/
881 ps_pre_enc_job_queue_next = aps_me_job_queues[num_hme_lyrs - 1];
882
883 /* ME coarsest layer is currently made dependent on entire decomp layer */
884 out_dep_pass = ai4_me_num_vert_units_lyr[0];
885 me_coarsest_lyr_inp_dep = num_vert_units;
886 }
887 else
888 {
889 ps_pre_enc_job_queue_next = ps_decomp_job_queue_lyr1;
890 out_dep_pass = 3;
891 }
892 }
893 else if((DECOMP_JOB_LYR1 == pass) && (decomp_lyr_cnt != (n_tot_layers - 1)))
894 {
895 proc_valid_flag = 1;
896 pre_enc_task_type = DECOMP_JOB_LYR1;
897 enc_task_type = (HEVCE_ENC_JOB_TYPES_T)-1;
898 ps_pre_enc_job_queue_curr = ps_decomp_job_queue_lyr1;
899
900 inp_dep_pass = 3;
901 decomp_lyr_cnt++;
902
903 /* If all the decomp layers are done next job queue will be ME job queue */
904 if(decomp_lyr_cnt == (n_tot_layers - 1))
905 {
906 /* Assumption : num_hme_lyrs > 1*/
907 ps_pre_enc_job_queue_next = aps_me_job_queues[num_hme_lyrs - 1];
908
909 /* ME coarsest layer is currently made dependent on entire decomp layer */
910 out_dep_pass = ai4_me_num_vert_units_lyr[0];
911 me_coarsest_lyr_inp_dep = num_vert_units;
912 }
913 else
914 {
915 ps_pre_enc_job_queue_next = ps_decomp_job_queue_lyr2;
916 out_dep_pass = 3;
917 }
918 }
919 else if((DECOMP_JOB_LYR2 == pass) && (decomp_lyr_cnt != (n_tot_layers - 1)))
920 {
921 proc_valid_flag = 1;
922 pre_enc_task_type = DECOMP_JOB_LYR2;
923 enc_task_type = (HEVCE_ENC_JOB_TYPES_T)-1;
924 ps_pre_enc_job_queue_curr = ps_decomp_job_queue_lyr2;
925
926 inp_dep_pass = 3;
927 decomp_lyr_cnt++;
928
929 /* If all the decomp layers are done next job queue will be ME job queue */
930 if(decomp_lyr_cnt == (n_tot_layers - 1))
931 {
932 /* Assumption : num_hme_lyrs > 1*/
933 ps_pre_enc_job_queue_next = aps_me_job_queues[num_hme_lyrs - 1];
934
935 /* ME coarsest layer is currently made dependent on entire decomp layer */
936 out_dep_pass = ai4_me_num_vert_units_lyr[0];
937 me_coarsest_lyr_inp_dep = num_vert_units;
938 }
939 else
940 {
941 /* right now MAX 4 layers worth of JOB queues are prepared */
942 ASSERT(0);
943 }
944 }
945
946 else if(IPE_JOB_LYR0 == pass)
947 {
948 proc_valid_flag = 1;
949 pre_enc_task_type = IPE_JOB_LYR0;
950 enc_task_type = (HEVCE_ENC_JOB_TYPES_T)-1;
951 ps_pre_enc_job_queue_curr = ps_ipe_job_queue;
952 ps_pre_enc_job_queue_next = NULL;
953 num_vert_units = num_ctb_vert_rows;
954 }
955 else if(((pass >= ME_JOB_LYR4) && (pass <= ME_JOB_LYR1)) && (pass >= me_start_lyr_pass))
956 {
957 /* num_ver_units of coarsest layer is stored at 0th index */
958 num_vert_units = ai4_me_num_vert_units_lyr[me_lyr_cnt];
959 proc_valid_flag = 1;
960
961 pre_enc_task_type =
962 (HEVCE_PRE_ENC_JOB_TYPES_T)((WORD32)ME_JOB_LYR1 - (num_hme_lyrs - me_lyr_cnt - 2));
963
964 enc_task_type = (HEVCE_ENC_JOB_TYPES_T)-1;
965
966 /* Assumption : num_hme_lyrs > 1*/
967 ps_pre_enc_job_queue_curr = aps_me_job_queues[num_hme_lyrs - me_lyr_cnt - 1];
968
969 if(me_lyr_cnt == (num_hme_lyrs - 2))
970 {
971 ps_pre_enc_job_queue_next = ps_ipe_job_queue;
972 }
973 else
974 {
975 ps_pre_enc_job_queue_next = aps_me_job_queues[num_hme_lyrs - me_lyr_cnt - 2];
976 }
977 me_lyr_cnt++;
978 }
979
980 /* check for valid processing flag */
981 if(0 == proc_valid_flag)
982 {
983 continue;
984 }
985
986 /* in the loop ps_me_job_q_prms get incremented for every row */
987 /* so at the end of one layer the pointer will be correctly */
988 /* pointing to the start of next layer */
989
990 /* loop over all the vertical rows */
991 for(num_jobs = 0; num_jobs < num_vert_units; num_jobs++)
992 {
993 ULWORD64 u8_temp;
994 WORD32 inp_dep = 0;
995 WORD32 out_dep = 0;
996 WORD32 ctr;
997 WORD32 job_off_ipe;
998
999 if(IPE_JOB_LYR0 == pass)
1000 {
1001 ps_pre_enc_job_queue_curr->s_job_info.s_ipe_job_info.i4_ctb_row_no = num_jobs;
1002 inp_dep = ps_me_job_q_prms->i4_num_inp_dep;
1003 out_dep = 0;
1004 }
1005 else if((pass >= DECOMP_JOB_LYR0) && (pass <= DECOMP_JOB_LYR3))
1006 {
1007 ps_pre_enc_job_queue_curr->s_job_info.s_decomp_job_info.i4_vert_unit_row_no =
1008 num_jobs;
1009
1010 /* Input and output dependencies of 1st row and last row is 1 less than other rows*/
1011 inp_dep = inp_dep_pass;
1012 out_dep = out_dep_pass;
1013
1014 if(pass != DECOMP_JOB_LYR0)
1015 {
1016 if(((num_jobs == 0) || (num_jobs == num_vert_units - 1)))
1017 {
1018 inp_dep = inp_dep_pass - 1;
1019 }
1020 }
1021
1022 if(pass != (DECOMP_JOB_LYR0 + n_tot_layers - 2))
1023 {
1024 if(((num_jobs == 0) || (num_jobs == num_vert_units - 1)))
1025 {
1026 out_dep = out_dep_pass - 1;
1027 }
1028 }
1029 }
1030 else /* remaining all are ME JOBS */
1031 {
1032 ps_pre_enc_job_queue_curr->s_job_info.s_me_job_info.i4_vert_unit_row_no = num_jobs;
1033
1034 if(pass == me_start_lyr_pass)
1035 {
1036 ASSERT(me_coarsest_lyr_inp_dep != -1);
1037 inp_dep = me_coarsest_lyr_inp_dep;
1038 }
1039 else
1040 {
1041 inp_dep = ps_me_job_q_prms->i4_num_inp_dep;
1042 }
1043 out_dep = ps_me_job_q_prms->i4_num_output_dep;
1044 }
1045 ps_pre_enc_job_queue_curr->pv_next = (void *)(ps_pre_enc_job_queue_curr + 1);
1046
1047 ps_pre_enc_job_queue_curr->i4_pre_enc_task_type = pre_enc_task_type;
1048 ps_pre_enc_job_queue_curr->i4_task_type = enc_task_type;
1049
1050 /* Set the input dependencies */
1051 ps_pre_enc_job_queue_curr->i4_num_input_dep = inp_dep;
1052
1053 /* set the entire input dep buffer to default value 0 */
1054 memset(&ps_pre_enc_job_queue_curr->au1_in_dep[0], 0, sizeof(UWORD8) * MAX_IN_DEP);
1055
1056 /* set the input dep buffer to 1 for num inp dep */
1057 if(0 != inp_dep)
1058 {
1059 memset(&ps_pre_enc_job_queue_curr->au1_in_dep[0], 1, sizeof(UWORD8) * inp_dep);
1060 }
1061
1062 /* If decomposition layer ends at this pass the no of out dependencies
1063 * will be based on number of vertical units in the coarsets layer of HME
1064 * This is because the search range in coarsest layer will be almost
1065 * entire frame (search range of +-128 in vert direction is max supported
1066 */
1067 if(pass == (DECOMP_JOB_LYR0 + n_tot_layers - 2))
1068 {
1069 job_off_ipe = 0;
1070 }
1071 else
1072 {
1073 if(num_jobs == 0)
1074 job_off_ipe = num_jobs;
1075
1076 else
1077 job_off_ipe = num_jobs - 1;
1078 }
1079
1080 /* Set the offsets of output dependencies */
1081 ps_pre_enc_job_queue_curr->i4_num_output_dep = out_dep;
1082
1083 /* set the entire offset buffer to default value */
1084 memset(
1085 &ps_pre_enc_job_queue_curr->au4_out_ofsts[0], 0xFF, sizeof(UWORD32) * MAX_OUT_DEP);
1086
1087 for(ctr = 0; ctr < out_dep; ctr++)
1088 {
1089 /* if IPE or DECOMP loop the dep is 1 to 1*/
1090 if(((pass >= DECOMP_JOB_LYR0) && (pass <= DECOMP_JOB_LYR3)) ||
1091 (IPE_JOB_LYR0 == pass))
1092 {
1093 u8_temp = (ULWORD64)(
1094 &ps_pre_enc_job_queue_next[job_off_ipe] -
1095 ps_ctxt->s_multi_thrd.aps_job_q_pre_enc[i4_ping_pong]);
1096
1097 u8_temp *= sizeof(job_queue_t);
1098
1099 /* add the excat inp dep byte for the next layer JOB */
1100 u8_temp += ps_pre_enc_job_queue_next[job_off_ipe].i4_num_input_dep;
1101
1102 /* increment the inp dep number for a given job */
1103 ps_pre_enc_job_queue_next[job_off_ipe].i4_num_input_dep++;
1104
1105 job_off_ipe++;
1106 }
1107 else if((pass >= ME_JOB_LYR4) && (pass <= ME_JOB_LYR1))
1108 {
1109 /* ME layer Jobs */
1110 WORD32 job_off;
1111
1112 job_off = ps_me_job_q_prms->ai4_out_dep_unit_off[ctr];
1113
1114 u8_temp = (ULWORD64)(
1115 &ps_pre_enc_job_queue_next[job_off] -
1116 ps_ctxt->s_multi_thrd.aps_job_q_pre_enc[i4_ping_pong]);
1117
1118 u8_temp *= sizeof(job_queue_t);
1119
1120 /* add the excat inp dep byte for the next layer JOB */
1121 u8_temp += ps_pre_enc_job_queue_next[job_off].i4_num_input_dep;
1122
1123 /* increment the inp dep number for a given job */
1124 ps_pre_enc_job_queue_next[job_off].i4_num_input_dep++;
1125 }
1126 /* store the offset to the array */
1127 ps_pre_enc_job_queue_curr->au4_out_ofsts[ctr] = (UWORD32)u8_temp;
1128 }
1129 /* ME job q params is incremented only for ME jobs */
1130 if(((pass >= ME_JOB_LYR4) && (pass <= ME_JOB_LYR1)) || (IPE_JOB_LYR0 == pass))
1131 {
1132 ps_me_job_q_prms++;
1133 }
1134 ps_pre_enc_job_queue_curr++;
1135 }
1136
1137 /* set the last pointer to NULL */
1138 ps_pre_enc_job_queue_curr--;
1139 ps_pre_enc_job_queue_curr->pv_next = (void *)NULL;
1140 }
1141
1142 /* reset the num ctb processed in every row for IPE sync */
1143 memset(
1144 &ps_ctxt->s_multi_thrd.ai4_ctbs_in_row_proc_ipe_pass[0],
1145 0,
1146 (MAX_NUM_CTB_ROWS_FRM * sizeof(WORD32)));
1147
1148 } /* End of ihevce_prepare_pre_enc_job_queue */
1149