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 ******************************************************************************
23 * \file ihevce_hle_interface.c
24 *
25 * \brief
26 *    This file contains all the functions related High level enocder
27 *    Interface layer
28 *
29 * \date
30 *    18/09/2012
31 *
32 * \author
33 *    Ittiam
34 *
35 * List of Functions
36 *    <TODO: TO BE ADDED>
37 *
38 ******************************************************************************
39 */
40 
41 /*****************************************************************************/
42 /* File Includes                                                             */
43 /*****************************************************************************/
44 /* System include files */
45 #include <stdio.h>
46 #include <string.h>
47 #include <stdlib.h>
48 #include <assert.h>
49 #include <stdarg.h>
50 #include <math.h>
51 #include <time.h>
52 
53 /* User include files */
54 #include "ihevc_typedefs.h"
55 #include "itt_video_api.h"
56 #include "ihevce_api.h"
57 
58 #include "rc_cntrl_param.h"
59 #include "rc_frame_info_collector.h"
60 #include "rc_look_ahead_params.h"
61 
62 #include "ihevc_defs.h"
63 #include "ihevc_macros.h"
64 #include "ihevc_debug.h"
65 #include "ihevc_structs.h"
66 #include "ihevc_platform_macros.h"
67 #include "ihevc_deblk.h"
68 #include "ihevc_itrans_recon.h"
69 #include "ihevc_chroma_itrans_recon.h"
70 #include "ihevc_chroma_intra_pred.h"
71 #include "ihevc_intra_pred.h"
72 #include "ihevc_inter_pred.h"
73 #include "ihevc_mem_fns.h"
74 #include "ihevc_padding.h"
75 #include "ihevc_weighted_pred.h"
76 #include "ihevc_sao.h"
77 #include "ihevc_resi_trans.h"
78 #include "ihevc_quant_iquant_ssd.h"
79 #include "ihevc_cabac_tables.h"
80 #include "ihevc_trans_tables.h"
81 #include "ihevc_trans_macros.h"
82 
83 #include "ihevce_defs.h"
84 #include "ihevce_hle_interface.h"
85 #include "ihevce_hle_q_func.h"
86 #include "ihevce_buffer_que_interface.h"
87 #include "ihevce_lap_enc_structs.h"
88 #include "ihevce_multi_thrd_structs.h"
89 #include "ihevce_multi_thrd_funcs.h"
90 #include "ihevce_me_common_defs.h"
91 #include "ihevce_had_satd.h"
92 #include "ihevce_error_codes.h"
93 #include "ihevce_error_checks.h"
94 #include "ihevce_bitstream.h"
95 #include "ihevce_cabac.h"
96 #include "ihevce_rdoq_macros.h"
97 #include "ihevce_function_selector.h"
98 #include "ihevce_enc_structs.h"
99 #include "ihevce_cmn_utils_instr_set_router.h"
100 #include "ihevce_memory_init.h"
101 #include "ihevce_lap_interface.h"
102 #include "ihevce_entropy_cod.h"
103 #include "ihevce_entropy_structs.h"
104 #include "ihevce_frame_process_utils.h"
105 #include "ihevce_frame_process.h"
106 #include "ihevce_profile.h"
107 #include "ihevce_global_tables.h"
108 #include "ihevce_dep_mngr_interface.h"
109 #include "ihevce_common_utils.h"
110 #include "hme_datatype.h"
111 #include "hme_interface.h"
112 #include "hme_common_defs.h"
113 #include "hme_defs.h"
114 #include "ihevce_coarse_me_pass.h"
115 #include "ihevce_me_pass.h"
116 #include "ihevce_enc_loop_structs.h"
117 #include "ihevce_enc_loop_pass.h"
118 
119 #include "cast_types.h"
120 #include "osal.h"
121 #include "osal_defaults.h"
122 
123 /*****************************************************************************/
124 /* Function Definitions                                                      */
125 /*****************************************************************************/
126 /*!
127 ******************************************************************************
128 * \if Function name : ihevce_context_reset \endif
129 *
130 * \brief
131 *    Encoder reset function
132 *
133 * \param[in] Encoder context pointer
134 *
135 * \return
136 *    None
137 *
138 * \author
139 *  Ittiam
140 *
141 *****************************************************************************
142 */
ihevce_context_reset(enc_ctxt_t * ps_enc_ctxt)143 void ihevce_context_reset(enc_ctxt_t *ps_enc_ctxt)
144 {
145     ps_enc_ctxt->i4_end_flag = 0;
146 
147     /* set the queue related pointer and buffer to default value */
148     ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl = NULL;
149 
150     /* Reset the i/o queues created status to 0 */
151     ps_enc_ctxt->i4_io_queues_created = 0;
152 
153     /* reset the frame limit flag to 0 */
154     ps_enc_ctxt->i4_frame_limit_reached = 0;
155 
156     return;
157 }
158 
159 /*!
160 ******************************************************************************
161 * \if Function name : ihevce_hle_interface_create \endif
162 *
163 * \brief
164 *    High level Encoder create function
165 *
166 * \param[in]  High level enocder interface context pointer
167 *
168 * \return
169 *    success or fail
170 *
171 * \author
172 *  Ittiam
173 *
174 *****************************************************************************
175 */
ihevce_hle_interface_create(ihevce_hle_ctxt_t * ps_hle_ctxt)176 IV_API_CALL_STATUS_T ihevce_hle_interface_create(ihevce_hle_ctxt_t *ps_hle_ctxt)
177 {
178     /* local variables */
179     enc_ctxt_t *ps_enc_ctxt;
180     iv_mem_rec_t s_memtab;
181     ihevce_static_cfg_params_t *ps_enc_static_cfg_params;
182     WORD32 i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
183     WORD32 i4_look_ahead_frames_in_first_pass = -1;
184     WORD32 i4_total_cores = 0, ctr, i4_mres_flag = 0;
185     ihevce_sys_api_t *ps_sys_api = &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api;
186 
187     WORD32 status = 0;
188     WORD32 i;
189     WORD32 *pi4_active_res_id = NULL;
190 
191     /* OSAL Init */
192     status = ihevce_osal_init((void *)ps_hle_ctxt);
193 
194     if(status != 0)
195         return (IV_FAIL);
196 
197     /* --------------------------------------------------------------------- */
198     /*              High Level Encoder Init                                  */
199     /* --------------------------------------------------------------------- */
200 
201     if(i4_num_resolutions > 1)
202         i4_mres_flag = 1;
203     /* set no error in the output */
204     ps_hle_ctxt->i4_error_code = 0;
205 
206     /* Error checks on the static parameters passed */
207     ps_hle_ctxt->i4_error_code = ihevce_hle_validate_static_params(ps_hle_ctxt->ps_static_cfg_prms);
208 
209     /*memory for static cfg params for encoder, which can be overwritten if encoder wants
210         encoder should use this for all its usage*/
211     s_memtab.i4_size = sizeof(iv_mem_rec_t);
212     s_memtab.i4_mem_alignment = 4;
213     s_memtab.i4_mem_size = sizeof(ihevce_static_cfg_params_t);
214     s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
215 
216     ps_hle_ctxt->ihevce_mem_alloc(
217         ps_hle_ctxt->pv_mem_mgr_hdl, &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api, &s_memtab);
218     if(s_memtab.pv_base == NULL)
219     {
220         return (IV_FAIL);
221     }
222     ps_enc_static_cfg_params = (ihevce_static_cfg_params_t *)s_memtab.pv_base;
223     memcpy(
224         ps_enc_static_cfg_params,
225         ps_hle_ctxt->ps_static_cfg_prms,
226         (sizeof(ihevce_static_cfg_params_t)));
227 
228     i4_total_cores = ps_enc_static_cfg_params->s_multi_thrd_prms.i4_max_num_cores;
229 
230     /* check for validity of memory control flag (only 0,1,2 modes are allowed) */
231     if((ps_enc_static_cfg_params->s_multi_thrd_prms.i4_memory_alloc_ctrl_flag > 2) ||
232        (ps_enc_static_cfg_params->s_multi_thrd_prms.i4_memory_alloc_ctrl_flag < 0))
233     {
234         ps_hle_ctxt->i4_error_code = IHEVCE_INVALID_MEM_CTRL_FLAG;
235     }
236 
237     if((i4_mres_flag == 1) &&
238        (ps_enc_static_cfg_params->s_multi_thrd_prms.i4_use_thrd_affinity == 1))
239     {
240         ps_sys_api->ihevce_printf(
241             ps_sys_api->pv_cb_handle,
242             "\nIHEVCE WARNING: Enabling thread affinity in multiresolution encoding will affect "
243             "performance\n");
244     }
245     if((ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset ==
246         IHEVCE_QUALITY_P6) &&
247        (ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc))
248     {
249         ps_sys_api->ihevce_printf(
250             ps_sys_api->pv_cb_handle,
251             "\nIHEVCE WARNING: Disabling CU level QP modulation for P6 preset\n");
252         ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc = 0;
253     }
254     if((ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset ==
255         IHEVCE_QUALITY_P7) &&
256        (ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc))
257     {
258         ps_sys_api->ihevce_printf(
259             ps_sys_api->pv_cb_handle,
260             "\nIHEVCE WARNING: Disabling CU level QP modulation for P7 preset\n");
261         ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc = 0;
262     }
263 
264     if(0 != ps_hle_ctxt->i4_error_code)
265     {
266         ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
267         return (IV_FAIL);
268     }
269     ps_hle_ctxt->ai4_num_core_per_res[0] = i4_total_cores;
270 
271     if(1 == ps_enc_static_cfg_params->s_tgt_lyr_prms.i4_mres_single_out)
272     {
273         /*    Memory Allocation of pi4_active_res_id */
274         s_memtab.i4_size = sizeof(iv_mem_rec_t);
275         s_memtab.i4_mem_alignment = 4;
276         s_memtab.i4_mem_size = sizeof(WORD32) * (IHEVCE_MAX_NUM_RESOLUTIONS + 1);
277         s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
278 
279         ps_hle_ctxt->ihevce_mem_alloc(
280             ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_static_cfg_params->s_sys_api, &s_memtab);
281         if(s_memtab.pv_base == NULL)
282         {
283             return (IV_FAIL);
284         }
285 
286         pi4_active_res_id = (WORD32 *)s_memtab.pv_base;
287     }
288     /* --------------------------------------------------------------------- */
289     /*    Context and Memory Initialization of Encoder ctxt                  */
290     /* --------------------------------------------------------------------- */
291     for(ctr = 0; ctr < i4_num_resolutions; ctr++)
292     {
293         WORD32 i4_br_id;
294         s_memtab.i4_size = sizeof(iv_mem_rec_t);
295         s_memtab.i4_mem_alignment = 4;
296         s_memtab.i4_mem_size = sizeof(enc_ctxt_t);
297         s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
298 
299         ps_hle_ctxt->ihevce_mem_alloc(
300             ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_static_cfg_params->s_sys_api, &s_memtab);
301         if(s_memtab.pv_base == NULL)
302         {
303             return (IV_FAIL);
304         }
305 
306         ps_enc_ctxt = (enc_ctxt_t *)s_memtab.pv_base;
307 
308         ps_enc_ctxt->ps_stat_prms = ps_enc_static_cfg_params;
309 
310         /* check of number of cores to decide the num threads active */
311         ps_enc_ctxt->s_multi_thrd.i4_all_thrds_active_flag = 1;
312 
313         if(1 == ps_enc_static_cfg_params->s_tgt_lyr_prms.i4_mres_single_out)
314         {
315             pi4_active_res_id[ctr] = 0;
316             ps_enc_ctxt->s_multi_thrd.pi4_active_res_id = pi4_active_res_id;
317         }
318 
319         /*store num bit-rate instances in the encoder context */
320         ps_enc_ctxt->i4_num_bitrates =
321             ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[ctr].i4_num_bitrate_instances;
322         if(BLU_RAY_SUPPORT == ps_enc_static_cfg_params->s_out_strm_prms.i4_interop_flags)
323         {
324             ps_enc_ctxt->i4_blu_ray_spec = 1;
325         }
326         else
327         {
328             ps_enc_ctxt->i4_blu_ray_spec = 0;
329         }
330 
331         /* if all threads are required to be active */
332         if(1 == ps_enc_ctxt->s_multi_thrd.i4_all_thrds_active_flag)
333         {
334             /* store the number of threads to be created as passed by app with HT flag */
335             ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds =
336                 ps_hle_ctxt->ai4_num_core_per_res[ctr];
337 
338             /* pre enc threads are doubled if HT is ON */
339             ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds =
340                 ps_hle_ctxt->ai4_num_core_per_res[ctr];
341         }
342         else
343         {
344             // TODO: distribute threads across stages
345         }
346 
347         /*Keep track of resolution id, this is used to differentiate from other encoder instance*/
348         ps_enc_ctxt->i4_resolution_id = ctr;
349         /* store hle ctxt in enc ctxt */
350         ps_enc_ctxt->pv_hle_ctxt = (void *)ps_hle_ctxt;
351         ps_enc_ctxt->pv_rc_mutex_lock_hdl = NULL;
352         ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl = NULL;
353         ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl = NULL;
354         ps_enc_ctxt->i4_look_ahead_frames_in_first_pass = i4_look_ahead_frames_in_first_pass;
355 
356         ps_enc_ctxt->ai4_is_past_pic_complex[0] = 0;
357         ps_enc_ctxt->ai4_is_past_pic_complex[1] = 0;
358         ps_enc_ctxt->i4_is_I_reset_done = 1;
359         ps_enc_ctxt->i4_past_RC_reset_count = 0;
360         ps_enc_ctxt->i4_future_RC_reset = 0;
361         ps_enc_ctxt->i4_past_RC_scd_reset_count = 0;
362         ps_enc_ctxt->i4_future_RC_scd_reset = 0;
363         ps_enc_ctxt->i4_active_scene_num = -1;
364         for(i = 0; i < IHEVCE_MAX_NUM_BITRATES; i++)
365         {
366             ps_enc_ctxt->ai4_rc_query[i] = 0;
367         }
368         ps_enc_ctxt->i4_active_enc_frame_id = 0;
369         ps_enc_ctxt->u1_is_popcnt_available = 1;
370 
371 #ifndef ARM
372         ps_enc_ctxt->e_arch_type = ARCH_X86_GENERIC;
373         ps_enc_ctxt->u1_is_popcnt_available = 0;
374 #else
375         if(ps_enc_static_cfg_params->e_arch_type == ARCH_NA)
376             ps_enc_ctxt->e_arch_type = ihevce_default_arch();
377         else
378             ps_enc_ctxt->e_arch_type = ps_enc_static_cfg_params->e_arch_type;
379         ps_enc_ctxt->u1_is_popcnt_available = 0;
380 #endif
381 
382         {
383             ps_enc_static_cfg_params->e_arch_type = ps_enc_ctxt->e_arch_type;
384 
385             ihevce_init_function_ptr(ps_enc_ctxt, ps_enc_ctxt->e_arch_type);
386         }
387 
388         ihevce_mem_manager_init(ps_enc_ctxt, ps_hle_ctxt);
389 
390         if(0 != ps_hle_ctxt->i4_error_code)
391         {
392             return (IV_FAIL);
393         }
394 
395         /* mutex lock for RC calls */
396         ps_enc_ctxt->pv_rc_mutex_lock_hdl = osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
397         if(NULL == ps_enc_ctxt->pv_rc_mutex_lock_hdl)
398         {
399             return IV_FAIL;
400         }
401 
402         /* mutex lock for Sub pic RC calls */
403         ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl =
404             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
405         if(NULL == ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl)
406         {
407             return IV_FAIL;
408         }
409 
410         ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl =
411             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
412         if(NULL == ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl)
413         {
414             return IV_FAIL;
415         }
416 
417         /* reset the encoder context */
418         ihevce_context_reset(ps_enc_ctxt);
419 
420         /* register the Encoder context in HLE interface ctxt */
421         ps_hle_ctxt->apv_enc_hdl[ctr] = ps_enc_ctxt;
422     }
423     /* init profile */
424     PROFILE_INIT(&ps_hle_ctxt->profile_hle);
425     for(ctr = 0; ctr < i4_num_resolutions; ctr++)
426     {
427         WORD32 i4_br_id;
428 
429         PROFILE_INIT(&ps_hle_ctxt->profile_enc_me[ctr]);
430         PROFILE_INIT(&ps_hle_ctxt->profile_pre_enc_l1l2[ctr]);
431         PROFILE_INIT(&ps_hle_ctxt->profile_pre_enc_l0ipe[ctr]);
432         for(i4_br_id = 0; i4_br_id < ps_enc_ctxt->i4_num_bitrates; i4_br_id++)
433         {
434             PROFILE_INIT(&ps_hle_ctxt->profile_enc[ctr][i4_br_id]);
435             PROFILE_INIT(&ps_hle_ctxt->profile_entropy[ctr][i4_br_id]);
436         }
437     }
438     if(1 == ps_enc_static_cfg_params->s_tgt_lyr_prms.i4_mres_single_out)
439         pi4_active_res_id[i4_num_resolutions] = 0;
440 
441     return (IV_SUCCESS);
442 }
443 
444 /*!
445 ******************************************************************************
446 * \if Function name : ihevce_query_io_buf_req \endif
447 *
448 * \brief
449 *    High level Encoder IO buffers query function
450 *
451 * \param[in] High level encoder interface context pointer
452 * \param[out] Input buffer requirment stucture pointer.
453 * \param[out] Output buffer requirment stucture pointer.
454 *
455 * \return
456 *    success or fail
457 *
458 * \author
459 *  Ittiam
460 *
461 *****************************************************************************
462 */
ihevce_query_io_buf_req(ihevce_hle_ctxt_t * ps_hle_ctxt,iv_input_bufs_req_t * ps_input_bufs_req,iv_res_layer_output_bufs_req_t * ps_res_layer_output_bufs_req,iv_res_layer_recon_bufs_req_t * ps_res_layer_recon_bufs_req)463 IV_API_CALL_STATUS_T ihevce_query_io_buf_req(
464     ihevce_hle_ctxt_t *ps_hle_ctxt,
465     iv_input_bufs_req_t *ps_input_bufs_req,
466     iv_res_layer_output_bufs_req_t *ps_res_layer_output_bufs_req,
467     iv_res_layer_recon_bufs_req_t *ps_res_layer_recon_bufs_req)
468 {
469     /* local variables */
470     enc_ctxt_t *ps_enc_ctxt;
471     ihevce_src_params_t *ps_src_prms;
472     WORD32 ctb_align_pic_wd;
473     WORD32 ctb_align_pic_ht, i4_resolution_id = 0, i4_num_resolutions, i4_num_bitrate_instances;
474     WORD32 i4_resolution_id_ctr, br_ctr;
475 
476     ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[i4_resolution_id];
477     ps_src_prms = &ps_hle_ctxt->ps_static_cfg_prms->s_src_prms;
478     i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
479     /* set no error in the output */
480     ps_hle_ctxt->i4_error_code = 0;
481 
482     /* ------- populate the Input buffer requirements -------- */
483     /* get the number of buffers required for LAP */
484     ps_input_bufs_req->i4_min_num_yuv_bufs =
485         ihevce_lap_get_num_ip_bufs(&ps_enc_ctxt->s_lap_stat_prms);
486 
487     ps_input_bufs_req->i4_min_num_synch_ctrl_bufs = ps_input_bufs_req->i4_min_num_yuv_bufs;
488 
489     ps_input_bufs_req->i4_min_num_asynch_ctrl_bufs = NUM_AYSNC_CMD_BUFS;
490 
491     /* buffer sizes are populated based on create time parameters */
492     ctb_align_pic_wd =
493         ps_src_prms->i4_width +
494         SET_CTB_ALIGN(ps_src_prms->i4_width, ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
495 
496     ctb_align_pic_ht =
497         ps_src_prms->i4_height +
498         SET_CTB_ALIGN(ps_src_prms->i4_height, ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
499 
500     if(ps_src_prms->i4_input_bit_depth > 8)
501     {
502         ps_input_bufs_req->i4_min_size_y_buf = ctb_align_pic_wd * ctb_align_pic_ht * 2;
503 
504         ps_input_bufs_req->i4_min_size_uv_buf = ps_input_bufs_req->i4_min_size_y_buf >> 1;
505     }
506     else
507     {
508         ps_input_bufs_req->i4_min_size_y_buf = ctb_align_pic_wd * ctb_align_pic_ht;
509 
510         ps_input_bufs_req->i4_min_size_uv_buf = (ctb_align_pic_wd * ctb_align_pic_ht) >> 1;
511     }
512 
513     ps_input_bufs_req->i4_min_size_uv_buf <<=
514         ((ps_src_prms->i4_chr_format == IV_YUV_422SP_UV) ? 1 : 0);
515 
516     ps_input_bufs_req->i4_yuv_format = ps_src_prms->i4_chr_format;
517 
518     ps_input_bufs_req->i4_min_size_synch_ctrl_bufs =
519         ((MAX_SEI_PAYLOAD_PER_TLV + 16) * MAX_NUMBER_OF_SEI_PAYLOAD) + 16;
520 
521     ps_input_bufs_req->i4_min_size_asynch_ctrl_bufs =
522         ((MAX_SEI_PAYLOAD_PER_TLV + 16) * (MAX_NUMBER_OF_SEI_PAYLOAD - 6)) + 16;
523 
524     for(i4_resolution_id_ctr = 0; i4_resolution_id_ctr < i4_num_resolutions; i4_resolution_id_ctr++)
525     {
526         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[i4_resolution_id_ctr];
527 
528         i4_num_bitrate_instances = ps_enc_ctxt->s_runtime_tgt_params.i4_num_bitrate_instances;
529 
530         /* buffer sizes are populated based on create time parameters */
531         ctb_align_pic_wd = ps_enc_ctxt->s_runtime_tgt_params.i4_width +
532                            SET_CTB_ALIGN(
533                                ps_enc_ctxt->s_runtime_tgt_params.i4_width,
534                                ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
535 
536         ctb_align_pic_ht = ps_enc_ctxt->s_runtime_tgt_params.i4_height +
537                            SET_CTB_ALIGN(
538                                ps_enc_ctxt->s_runtime_tgt_params.i4_height,
539                                ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size);
540 
541         for(br_ctr = 0; br_ctr < i4_num_bitrate_instances; br_ctr++)
542         {
543             /* ------- populate the Output buffer requirements -------- */
544             ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr]
545                 .i4_min_num_out_bufs = NUM_OUTPUT_BUFS;
546 
547             ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr]
548                 .i4_min_size_bitstream_buf = (ctb_align_pic_wd * ctb_align_pic_ht);
549 
550             if((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth == 12) ||
551                ((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth > 8) &&
552                 (ps_src_prms->i4_chr_format == IV_YUV_422SP_UV)))
553             {
554                 ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr]
555                     .i4_min_size_bitstream_buf *= 2;
556             }
557 
558             if((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth == 10) &&
559                (ps_src_prms->i4_chr_format == IV_YUV_420SP_UV))
560             {
561                 ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr]
562                     .i4_min_size_bitstream_buf *= 3;
563                 ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr]
564                     .i4_min_size_bitstream_buf >>= 1;
565             }
566 
567             //recon_dump
568             /* ------- populate the Recon buffer requirements -------- */
569             if(ps_enc_ctxt->ps_stat_prms->i4_save_recon == 0)
570             {
571                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
572                     .i4_min_num_recon_bufs = 0;
573 
574                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
575                     .i4_min_size_y_buf = 0;
576 
577                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
578                     .i4_min_size_uv_buf = 0;
579             }
580             else
581             {
582                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
583                     .i4_min_num_recon_bufs = 2 * HEVCE_MAX_REF_PICS + 1;
584 
585                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
586                     .i4_min_size_y_buf =
587                     ctb_align_pic_wd * ctb_align_pic_ht *
588                     ((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth > 8)
589                          ? 2
590                          : 1);
591 
592                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
593                     .i4_min_size_uv_buf =
594                     (ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
595                          .i4_min_size_y_buf >>
596                      1);
597                 ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr]
598                     .i4_min_size_uv_buf <<=
599                     ((ps_src_prms->i4_chr_format == IV_YUV_422SP_UV) ? 1 : 0);
600             }
601         }
602     }
603 
604     return (IV_SUCCESS);
605 }
606 
607 /*!
608 ******************************************************************************
609 * \if Function name : ihevce_create_ports \endif
610 *
611 * \brief
612 *    High level Encoder IO ports Create function
613 *
614 * \param[in] High level encoder interface context pointer
615 * \param[in] Input data buffer descriptor
616 * \param[in] Input control buffer descriptor
617 * \param[in] Output data buffer descriptor
618 * \param[in] Output control status buffer descriptor
619 * \param[out] Pointer to store the ID for Input data Que
620 * \param[out] Pointer to store the ID for Input control Que
621 * \param[out] Pointer to store the ID for Output data Que
622 * \param[out] Pointer to store the ID for Output control status Que
623 *
624 * \return
625 *  success or fail
626 *
627 * \author
628 *  Ittiam
629 *
630 *****************************************************************************
631 */
ihevce_create_ports(ihevce_hle_ctxt_t * ps_hle_ctxt,iv_input_data_ctrl_buffs_desc_t * ps_input_data_ctrl_buffs_desc,iv_input_asynch_ctrl_buffs_desc_t * ps_input_asynch_ctrl_buffs_desc,iv_res_layer_output_data_buffs_desc_t * ps_mres_output_data_buffs_desc,iv_res_layer_recon_data_buffs_desc_t * ps_mres_recon_data_buffs_desc)632 IV_API_CALL_STATUS_T ihevce_create_ports(
633     ihevce_hle_ctxt_t *ps_hle_ctxt,
634     iv_input_data_ctrl_buffs_desc_t *ps_input_data_ctrl_buffs_desc,
635     iv_input_asynch_ctrl_buffs_desc_t *ps_input_asynch_ctrl_buffs_desc,
636     iv_res_layer_output_data_buffs_desc_t *ps_mres_output_data_buffs_desc,
637     iv_res_layer_recon_data_buffs_desc_t *ps_mres_recon_data_buffs_desc)
638 {
639     /* local varaibles */
640     enc_ctxt_t *ps_enc_ctxt;
641     WORD32 res_ctr,
642         i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
643     void *pv_q_mutex_hdl = NULL;
644 
645     /* set no error in the output */
646     ps_hle_ctxt->i4_error_code = 0;
647 
648     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
649     {
650         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
651         /* check on buffer sizes provided by applciation needs to be checked */
652 
653         /* call the memory manager que init function , pass the op data , status, recon for the first bitrate, internally we will increment*/
654         ihevce_mem_manager_que_init(
655             ps_enc_ctxt,
656             ps_hle_ctxt,
657             ps_input_data_ctrl_buffs_desc,
658             ps_input_asynch_ctrl_buffs_desc,
659             &ps_mres_output_data_buffs_desc->s_output_data_buffs[res_ctr][0],
660             &ps_mres_recon_data_buffs_desc->s_recon_data_buffs[res_ctr][0]);
661 
662         /* set the number of Queues */
663         ps_enc_ctxt->s_enc_ques.i4_num_queues = IHEVCE_MAX_NUM_QUEUES;
664 
665         /* allocate a mutex to take care of handling multiple threads accesing Queues */
666         /*my understanding, this is common semaphore for all the queue. Since main input is still
667         common across all instance fo encoder. Hence common semaphore is a must*/
668         if(0 == res_ctr)
669         {
670             ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl = osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
671             /* store it in local variable for allocating it to other instances */
672             pv_q_mutex_hdl = ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl;
673             if(NULL == pv_q_mutex_hdl)
674             {
675                 return IV_FAIL;
676             }
677         }
678         else
679         {
680             ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl = pv_q_mutex_hdl;
681         }
682 
683         /* Set the i/o queues created status to 1 */
684         ps_enc_ctxt->i4_io_queues_created = 1;
685     }
686     return (IV_SUCCESS);
687 }
688 
689 /*!
690 ******************************************************************************
691 * \if Function name : ihevce_hle_interface_thrd \endif
692 *
693 * \brief
694 *    High level encoder thread interface function
695 *
696 * \param[in] High level interface context pointer
697 *
698 * \return
699 *    None
700 *
701 * \author
702 *  Ittiam
703 *
704 *****************************************************************************
705 */
ihevce_hle_interface_thrd(void * pv_proc_intf_ctxt)706 WORD32 ihevce_hle_interface_thrd(void *pv_proc_intf_ctxt)
707 {
708     /* local variables */
709     WORD32 ctr, res_ctr;
710     ihevce_hle_ctxt_t *ps_hle_ctxt;
711     enc_ctxt_t *ps_enc_ctxt;
712     /* enc ctxt to store 0th instance's params which are required by all instances */
713     enc_ctxt_t *ps_enc_ctxt_base;
714     void *pv_lap_sem_hdl;
715     void *pv_enc_frame_process_sem_hdl;
716     void *pv_pre_enc_frame_process_sem_hdl;
717     void *apv_ent_coding_sem_hdl[IHEVCE_MAX_NUM_BITRATES];
718     void *pv_ent_common_mres_sem_hdl = NULL;
719     void *pv_out_common_mres_sem_hdl = NULL;
720 
721     void *pv_inp_data_sem_hdl;
722     void *pv_lap_inp_data_sem_hdl;
723     void *pv_preenc_inp_data_sem_hdl;
724     void *pv_inp_ctrl_sem_hdl;
725     void *apv_out_stream_sem_hdl[IHEVCE_MAX_NUM_BITRATES];
726     void *apv_out_recon_sem_hdl[IHEVCE_MAX_NUM_BITRATES];
727     void *pv_out_ctrl_sts_sem_hdl;
728 
729     lap_intface_t *ps_lap_interface_ctxt;
730     iv_mem_rec_t s_memtab;
731     WORD32 i4_num_bit_rate_instances[IHEVCE_MAX_NUM_RESOLUTIONS], i4_num_resolutions;
732     WORD32 i;  //loop variable
733     WORD32 ai4_proc_count[MAX_NUMBER_PROC_GRPS] = { 0 }, i4_proc_grp_count;
734     WORD32 i4_acc_proc_num = 0;
735 
736     /* Frame Encode processing threads & semaphores */
737     void *apv_enc_frm_proc_hdls[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_ENC];
738     frm_proc_thrd_ctxt_t
739         *aps_enc_frm_proc_thrd_ctxt[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_ENC];
740 
741     /* Pre Frame Encode processing threads & semaphores */
742     void *apv_pre_enc_frm_proc_hdls[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_PRE_ENC];
743     frm_proc_thrd_ctxt_t
744         *aps_pre_enc_frm_proc_thrd_ctxt[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_PRE_ENC];
745 
746     void *apv_entropy_thrd_hdls[IHEVCE_MAX_NUM_RESOLUTIONS][NUM_ENTROPY_THREADS];
747     frm_proc_thrd_ctxt_t *aps_entropy_thrd_ctxt[IHEVCE_MAX_NUM_RESOLUTIONS][NUM_ENTROPY_THREADS];
748 
749     ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_proc_intf_ctxt;
750     ps_enc_ctxt_base = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[0];
751     /* profile start */
752     PROFILE_START(&ps_hle_ctxt->profile_hle);
753     /* store default values of mem tab */
754     s_memtab.i4_size = sizeof(iv_mem_rec_t);
755     s_memtab.i4_mem_alignment = 4;
756 
757     i4_num_resolutions = ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.i4_num_res_layers;
758     memset(
759         apv_entropy_thrd_hdls,
760         0,
761         IHEVCE_MAX_NUM_RESOLUTIONS * NUM_ENTROPY_THREADS * sizeof(void *));
762     memset(
763         apv_entropy_thrd_hdls,
764         0,
765         IHEVCE_MAX_NUM_RESOLUTIONS * NUM_ENTROPY_THREADS * sizeof(void *));
766     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
767     {
768         i4_num_bit_rate_instances[res_ctr] =
769             ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr]
770                 .i4_num_bitrate_instances;
771     }
772     /* --------------------------------------------------------------------- */
773     /*        Init number of threads for each stage                          */
774     /* --------------------------------------------------------------------- */
775 
776     {
777         for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
778         {
779             ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
780             /* all the threads created will be made active */
781             ps_enc_ctxt->s_multi_thrd.i4_num_active_enc_thrds =
782                 ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds;
783 
784             ps_enc_ctxt->s_multi_thrd.i4_num_active_pre_enc_thrds =
785                 ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds;
786         }
787     }
788 
789     /* --------------------------------------------------------------------- */
790     /*            Multiple processing Threads Semaphores init                */
791     /* --------------------------------------------------------------------- */
792     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
793     {
794         osal_sem_attr_t attr = OSAL_DEFAULT_SEM_ATTR;
795 
796         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
797 
798         attr.value = SEM_START_VALUE;
799 
800         /* Create Semaphore handle for LAP thread   */
801         if(0 == ps_enc_ctxt->i4_resolution_id)
802         {
803             pv_lap_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
804             if(NULL == pv_lap_sem_hdl)
805             {
806                 return IV_FAIL;
807             }
808         }
809         else
810         {
811             /*NOTE: Tile workspace assigned this to null. Confirm this*/
812             pv_lap_sem_hdl = ps_enc_ctxt_base->s_thrd_sem_ctxt.pv_lap_sem_handle;
813         }
814         /* Create Semaphore for encode frame process thread */
815         pv_enc_frame_process_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
816         if(NULL == pv_enc_frame_process_sem_hdl)
817         {
818             return IV_FAIL;
819         }
820 
821         /* Create Semaphore for pre_encode frame process thread */
822         pv_pre_enc_frame_process_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
823         if(NULL == pv_pre_enc_frame_process_sem_hdl)
824         {
825             return IV_FAIL;
826         }
827 
828         /* Create Semaphore for input frame data q function */
829         if(0 == ps_enc_ctxt->i4_resolution_id)
830         {
831             pv_inp_data_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
832             if(NULL == pv_inp_data_sem_hdl)
833             {
834                 return IV_FAIL;
835             }
836         }
837         else
838         {
839             pv_inp_data_sem_hdl = ps_enc_ctxt_base->s_thrd_sem_ctxt.pv_inp_data_sem_handle;
840         }
841 
842         /*creating new input queue owned by encoder*/
843         /* Create Semaphore for input frame data q function */
844         pv_lap_inp_data_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
845         if(NULL == pv_lap_inp_data_sem_hdl)
846         {
847             return IV_FAIL;
848         }
849 
850         /* Create Semaphore for input frame data q function */
851         pv_preenc_inp_data_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
852         if(NULL == pv_preenc_inp_data_sem_hdl)
853         {
854             return IV_FAIL;
855         }
856 
857         /* Create Semaphore for input conrol data q function */
858         if(0 == ps_enc_ctxt->i4_resolution_id)
859         {
860             pv_inp_ctrl_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
861             if(NULL == pv_inp_ctrl_sem_hdl)
862             {
863                 return IV_FAIL;
864             }
865         }
866         else
867         { /*Inp ctrl queue is same for all resolutions between app and lap*/
868             pv_inp_ctrl_sem_hdl = ps_enc_ctxt_base->s_thrd_sem_ctxt.pv_inp_ctrl_sem_handle;
869         }
870 
871         /* Create Semaphore for output control status data q function */
872         pv_out_ctrl_sts_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
873         if(NULL == pv_out_ctrl_sts_sem_hdl)
874         {
875             return IV_FAIL;
876         }
877 
878         /* Multi res single output case singel output queue is used for all output resolutions */
879         if(1 == ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out)
880         {
881             ps_enc_ctxt->s_enc_ques.apv_q_hdl[IHEVCE_OUTPUT_DATA_Q] =
882                 ps_enc_ctxt_base->s_enc_ques.apv_q_hdl[IHEVCE_OUTPUT_DATA_Q];
883             if(0 == ps_enc_ctxt->i4_resolution_id)
884             {
885                 /* Create Semaphore for enropy coding thread   */
886                 pv_ent_common_mres_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
887                 if(NULL == pv_ent_common_mres_sem_hdl)
888                 {
889                     return IV_FAIL;
890                 }
891 
892                 /* Create Semaphore for output stream data q function */
893                 pv_out_common_mres_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
894                 if(NULL == pv_out_common_mres_sem_hdl)
895                 {
896                     return IV_FAIL;
897                 }
898             }
899             ps_enc_ctxt->s_thrd_sem_ctxt.pv_ent_common_mres_sem_hdl = pv_ent_common_mres_sem_hdl;
900             ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_common_mres_sem_hdl = pv_out_common_mres_sem_hdl;
901         }
902 
903         /*create entropy and output semaphores for each thread.
904         Each thread will correspond to each bit-rate instance running */
905         for(i = 0; i < i4_num_bit_rate_instances[res_ctr]; i++)
906         {
907             /* Create Semaphore for enropy coding thread   */
908             apv_ent_coding_sem_hdl[i] = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
909             if(NULL == apv_ent_coding_sem_hdl[i])
910             {
911                 return IV_FAIL;
912             }
913 
914             /* Create Semaphore for output stream data q function */
915             apv_out_stream_sem_hdl[i] = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
916             if(NULL == apv_out_stream_sem_hdl[i])
917             {
918                 return IV_FAIL;
919             }
920 
921             /* Create Semaphore for output recon data q function */
922             apv_out_recon_sem_hdl[i] = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr);
923             if(NULL == apv_out_recon_sem_hdl[i])
924             {
925                 return IV_FAIL;
926             }
927         }
928 
929         /* update the semaphore handles and the thread creates status */
930 
931         ps_enc_ctxt->s_thrd_sem_ctxt.pv_enc_frm_proc_sem_handle = pv_enc_frame_process_sem_hdl;
932         ps_enc_ctxt->s_thrd_sem_ctxt.pv_pre_enc_frm_proc_sem_handle =
933             pv_pre_enc_frame_process_sem_hdl;
934         ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_sem_handle = pv_lap_sem_hdl;
935         ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_data_sem_handle = pv_inp_data_sem_hdl;
936         ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_inp_data_sem_hdl = pv_lap_inp_data_sem_hdl;
937         ps_enc_ctxt->s_thrd_sem_ctxt.pv_preenc_inp_data_sem_hdl = pv_preenc_inp_data_sem_hdl;
938         ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_ctrl_sem_handle = pv_inp_ctrl_sem_hdl;
939         ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_ctrl_sem_handle = pv_out_ctrl_sts_sem_hdl;
940         for(i = 0; i < i4_num_bit_rate_instances[res_ctr]; i++)
941         {
942             ps_enc_ctxt->s_thrd_sem_ctxt.apv_ent_cod_sem_handle[i] = apv_ent_coding_sem_hdl[i];
943             ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_strm_sem_handle[i] = apv_out_stream_sem_hdl[i];
944             ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_recon_sem_handle[i] = apv_out_recon_sem_hdl[i];
945         }
946     }
947 
948     /* --------------------------------------------------------------------- */
949     /*            Multiple processing Threads Mutex init                     */
950     /* --------------------------------------------------------------------- */
951     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
952     {
953         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
954 
955         /* create a mutex lock for Job Queue access accross slave threads of encode frame processing */
956         ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_me =
957             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
958         if(NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_me)
959         {
960             return IV_FAIL;
961         }
962 
963         /* create a mutex lock for Job Queue access accross slave threads of encode frame processing */
964         ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_enc_loop =
965             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
966         if(NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_enc_loop)
967         {
968             return IV_FAIL;
969         }
970 
971         /* create mutex for enc thread group */
972         for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
973         {
974             ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i] =
975                 osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
976             if(NULL == ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i])
977             {
978                 return IV_FAIL;
979             }
980 
981             ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i] =
982                 osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
983             if(NULL == ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i])
984             {
985                 return IV_FAIL;
986             }
987         }
988 
989         for(i = 0; i < MAX_NUM_ENC_LOOP_PARALLEL; i++)
990         {
991             ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i] =
992                 osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
993             if(NULL == ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i])
994             {
995                 return IV_FAIL;
996             }
997 
998             ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i] =
999                 osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1000             if(NULL == ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i])
1001             {
1002                 return IV_FAIL;
1003             }
1004         }
1005 
1006         /*initialize mutex for pre-enc group */
1007         ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_init =
1008             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1009 
1010         ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_decomp_deinit =
1011             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1012 
1013         ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_init =
1014             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1015 
1016         ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit =
1017             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1018 
1019         ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_deinit =
1020             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1021 
1022         ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_l0_ipe_init =
1023             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1024 
1025         ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_decomp =
1026             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1027 
1028         ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_hme =
1029             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1030 
1031         ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_l0ipe =
1032             osal_mutex_create(ps_hle_ctxt->pv_osal_handle);
1033 
1034         if(NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_init ||
1035            NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_decomp_deinit ||
1036            NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_init ||
1037            NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit ||
1038            NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_deinit ||
1039            NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_l0_ipe_init ||
1040            NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_decomp ||
1041            NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_hme ||
1042            NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_l0ipe)
1043         {
1044             return IV_FAIL;
1045         }
1046     }
1047 
1048     /* --------------------------------------------------------------------- */
1049     /*            Multiple processing Threads Context init                   */
1050     /* --------------------------------------------------------------------- */
1051 
1052     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1053     {
1054         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1055         ps_enc_ctxt_base = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[0];
1056 
1057         /*initialize multi-thread context for enc group*/
1058         ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done = 0;
1059         ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p = 0;
1060         ps_enc_ctxt->s_multi_thrd.i4_last_inp_buf = 0;
1061 
1062         {
1063             /* For all the ME frames in Parallel */
1064             WORD32 i4_frm_idx;
1065 
1066             for(i4_frm_idx = 0; i4_frm_idx < MAX_NUM_ME_PARALLEL; i4_frm_idx++)
1067             {
1068                 ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_frm_idx] = 0;
1069                 ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_frm_idx] = 0;
1070                 ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_frm_idx] = 0;
1071             }
1072         }
1073 
1074         {
1075             WORD32 i4_frm_idx;
1076             ps_enc_ctxt->s_multi_thrd.num_thrds_done = 0;
1077             ps_enc_ctxt->s_multi_thrd.num_thrds_exited_for_reenc = 0;
1078             for(i4_frm_idx = 0; i4_frm_idx < MAX_NUM_ENC_LOOP_PARALLEL; i4_frm_idx++)
1079             {
1080                 ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_frm_idx] = 0;
1081 
1082                 ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_frm_idx] = 0;
1083 
1084                 for(i = 0; i < i4_num_bit_rate_instances[res_ctr]; i++)
1085                 {
1086                     /*reset the entropy buffer produced status */
1087                     ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_frm_idx][i] = 1;
1088                     ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_frm_idx][i] = NULL;
1089 
1090                     ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_frm_idx][i] = NULL;
1091                 }
1092             }
1093         }
1094         ps_enc_ctxt->s_multi_thrd.i4_seq_mode_enabled_flag = 0;
1095 
1096         /* Set prev_frame_done = 1 to indicate that all the threads are in same frame*/
1097         for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel; i++)
1098         {
1099             ihevce_dmgr_set_done_frm_frm_sync(
1100                 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i]);
1101         }
1102         /* Set prev_frame_done = 1 to indicate that all the threads are in same frame*/
1103         ihevce_dmgr_set_done_frm_frm_sync(
1104             ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_enc_done_for_reenc);
1105         /*to enable the dependency manager to wait when first reached*/
1106         ihevce_dmgr_set_prev_done_frm_frm_sync(
1107             ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_enc_done_for_reenc);
1108         for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel; i++)
1109         {
1110             ihevce_dmgr_set_done_frm_frm_sync(
1111                 ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i]);
1112         }
1113 
1114         /* initialize multi-thread context for pre enc group */
1115 
1116         ps_enc_ctxt->s_multi_thrd.i4_ctrl_blocking_mode = BUFF_QUE_BLOCKING_MODE;
1117 
1118         for(ctr = 0; ctr < MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME; ctr++)
1119         {
1120             ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_init_done[ctr] = 0;
1121             ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_hme_init_done[ctr] = 0;
1122             ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_deinit_done[ctr] = 1;
1123             ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_decomp[ctr] = 0;
1124             ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_coarse_me[ctr] = 0;
1125             ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_pre_enc[ctr] = 0;
1126 
1127             ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_L0_ipe_qp_init[ctr] = 0;
1128             ps_enc_ctxt->s_multi_thrd.ai4_decomp_coarse_me_complete_flag[ctr] = 1;
1129             ps_enc_ctxt->s_multi_thrd.ai4_end_flag_pre_enc[ctr] = 0;
1130         }
1131 
1132         /* Set prev_frame_done = 1 to indicate that all the threads are in same frame*/
1133         ihevce_dmgr_set_done_frm_frm_sync(
1134             ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l1);
1135 
1136         ihevce_dmgr_set_done_frm_frm_sync(
1137             ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_coarse_me);
1138 
1139         ihevce_dmgr_set_done_frm_frm_sync(
1140             ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l0);
1141 
1142         {
1143             /**init idx for handling delay between pre-me and l0-ipe*/
1144             ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe = 0;
1145             ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe =
1146                 MIN_L1_L0_STAGGER_NON_SEQ +
1147                 ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics + 1;
1148             if(ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics)
1149             {
1150                 ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe =
1151                     MIN_L1_L0_STAGGER_NON_SEQ +
1152                     ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics;
1153             }
1154             ps_enc_ctxt->s_multi_thrd.i4_qp_update_l0_ipe = -1;
1155         }
1156     }
1157 
1158     /** Get Number of Processor Groups **/
1159     i4_proc_grp_count = ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups;
1160     /*** Enc threads are allocated based on the assumption that there can be only 2 processor groups **/
1161     ASSERT(i4_proc_grp_count <= MAX_NUMBER_PROC_GRPS);
1162     /** Get Number of logical processors in Each Group **/
1163     for(ctr = 0; ctr < i4_proc_grp_count; ctr++)
1164     {
1165         ai4_proc_count[ctr] =
1166             ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.ai4_num_cores_per_grp[ctr];
1167     }
1168 
1169     /* --------------------------------------------------------------------- */
1170     /*            Create a LAP thread                                        */
1171     /* --------------------------------------------------------------------- */
1172     /* LAP thread will run on  0th resolution instance context */
1173     {
1174         s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1175         s_memtab.i4_mem_size = sizeof(lap_intface_t);
1176 
1177         /* initialise the interface strucure parameters */
1178         ps_hle_ctxt->ihevce_mem_alloc(
1179             ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab);
1180         if(s_memtab.pv_base == NULL)
1181         {
1182             return (IV_FAIL);
1183         }
1184 
1185         ps_lap_interface_ctxt = (lap_intface_t *)s_memtab.pv_base;
1186 
1187         /* populate the params */
1188         ps_lap_interface_ctxt->pv_hle_ctxt = ps_hle_ctxt;
1189         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[0];
1190         ps_lap_interface_ctxt->pv_lap_module_ctxt = ps_enc_ctxt->s_module_ctxt.pv_lap_ctxt;
1191         ps_lap_interface_ctxt->i4_ctrl_in_que_id = IHEVCE_INPUT_ASYNCH_CTRL_Q;
1192         ps_lap_interface_ctxt->i4_ctrl_out_que_id = IHEVCE_OUTPUT_STATUS_Q;
1193         ps_lap_interface_ctxt->i4_ctrl_cmd_buf_size = ENC_COMMAND_BUFF_SIZE;
1194         ps_lap_interface_ctxt->i4_ctrl_in_que_blocking_mode = BUFF_QUE_BLOCKING_MODE;
1195         ps_lap_interface_ctxt->ps_sys_api = &ps_enc_ctxt_base->ps_stat_prms->s_sys_api;
1196         ps_enc_ctxt_base->pv_lap_interface_ctxt = (void *)ps_lap_interface_ctxt;
1197         ps_lap_interface_ctxt->ihevce_dyn_bitrate_cb = ihevce_dyn_bitrate;
1198     }
1199 
1200     /* --------------------------------------------------------------------- */
1201     /*          Create Entropy Coding threads                             */
1202     /* --------------------------------------------------------------------- */
1203     /*Create entropy thread for each encoder instance*/
1204     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1205     {
1206         osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR;
1207         WORD32 i4_num_entropy_threads;
1208 
1209         /* derive encoder ctxt from hle handle */
1210         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1211 
1212         i4_num_entropy_threads =
1213             ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr]
1214                 .i4_num_bitrate_instances;
1215 
1216         /* initialise the interface strucure parameters */
1217         for(ctr = 0; ctr < i4_num_entropy_threads; ctr++)
1218         {
1219             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1220             s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t);
1221 
1222             ps_hle_ctxt->ihevce_mem_alloc(
1223                 ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab);
1224             if(s_memtab.pv_base == NULL)
1225             {
1226                 return (IV_FAIL);
1227             }
1228 
1229             aps_entropy_thrd_ctxt[res_ctr][ctr] = (frm_proc_thrd_ctxt_t *)s_memtab.pv_base;
1230 
1231             /* initialise the interface strucure parameters */
1232             aps_entropy_thrd_ctxt[res_ctr][ctr]->i4_thrd_id = ctr;
1233             aps_entropy_thrd_ctxt[res_ctr][ctr]->ps_hle_ctxt = ps_hle_ctxt;
1234             aps_entropy_thrd_ctxt[res_ctr][ctr]->pv_enc_ctxt = (void *)ps_enc_ctxt;
1235 
1236             /* Initialize application thread attributes */
1237             s_thread_attr.exit_code = 0;
1238             s_thread_attr.name = 0;
1239             s_thread_attr.priority_map_flag = 1;
1240             s_thread_attr.priority = OSAL_PRIORITY_DEFAULT;
1241             s_thread_attr.stack_addr = 0;
1242             s_thread_attr.stack_size = THREAD_STACK_SIZE;
1243             s_thread_attr.thread_func = ihevce_ent_coding_thrd;
1244             s_thread_attr.thread_param =
1245                 (void *)(aps_entropy_thrd_ctxt[res_ctr]
1246                                               [ctr]);  //encioder and hle context are derived from this
1247             s_thread_attr.core_affinity_mask = 0;
1248             if(ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)
1249             {
1250                 /* Run ENTROPY thread on last group if there are more than one processor group */
1251                 s_thread_attr.group_num =
1252                     ps_hle_ctxt->ps_static_cfg_prms->s_multi_thrd_prms.i4_num_proc_groups - 1;
1253             }
1254             else
1255             {
1256                 s_thread_attr.group_num = 0;
1257             }
1258 
1259             /* Create entropy coding thread */
1260             apv_entropy_thrd_hdls[res_ctr][ctr] =
1261                 osal_thread_create(ps_hle_ctxt->pv_osal_handle, &s_thread_attr);
1262             if(NULL == apv_entropy_thrd_hdls[res_ctr][ctr])
1263             {
1264                 return IV_FAIL;
1265             }
1266         }
1267     }
1268 
1269     /* --------------------------------------------------------------------- */
1270     /*     Create all Slave Encode Frame processing threads                  */
1271     /* - -------------------------------------------------------------------- */
1272     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1273     {
1274         WORD32 enc_ctr = 0;
1275         WORD32 i4_loop_count;
1276         WORD32 i4_curr_grp_num = 0;
1277         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1278 
1279         i4_acc_proc_num = 0;
1280         /* Calculate the start core number of enc threads for current resolution */
1281         for(i4_loop_count = 0; i4_loop_count < res_ctr; i4_loop_count++)
1282         {
1283             /* Add number of cores taken by each resolution till the curr resolution */
1284             enc_ctr += ps_hle_ctxt->ai4_num_core_per_res[i4_loop_count];
1285         }
1286         if(ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)
1287         {
1288             /* Select the group number for each res based on processors present in each group */
1289             for(i4_loop_count = 0;
1290                 i4_loop_count <
1291                 ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups;
1292                 i4_loop_count++)
1293             {
1294                 i4_acc_proc_num += ai4_proc_count[i4_loop_count];
1295                 if(enc_ctr >= i4_acc_proc_num)
1296                 {
1297                     /* if enc_ctr is greater than proc count for first group,
1298                     then increment group count.This group number will be starting grp num for
1299                     that resolution */
1300                     i4_curr_grp_num++;
1301                 }
1302                 else
1303                     break;
1304             }
1305         }
1306 
1307         for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++)
1308         {
1309             osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR;
1310 
1311             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1312             s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t);
1313 
1314             ps_hle_ctxt->ihevce_mem_alloc(
1315                 ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab);
1316             if(s_memtab.pv_base == NULL)
1317             {
1318                 return (IV_FAIL);
1319             }
1320 
1321             aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr] = (frm_proc_thrd_ctxt_t *)s_memtab.pv_base;
1322 
1323             /* initialise the interface strucure parameters */
1324             aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->i4_thrd_id = ctr;
1325 
1326             aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->ps_hle_ctxt = ps_hle_ctxt;
1327 
1328             ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1329 
1330             aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->pv_enc_ctxt = (void *)ps_enc_ctxt;
1331 
1332             /* Initialize application thread attributes */
1333             s_thread_attr.exit_code = 0;
1334             s_thread_attr.name = 0;
1335             s_thread_attr.priority_map_flag = 1;
1336             s_thread_attr.priority = OSAL_PRIORITY_DEFAULT;
1337             s_thread_attr.stack_addr = 0;
1338             s_thread_attr.stack_size = THREAD_STACK_SIZE;
1339             s_thread_attr.thread_func = ihevce_enc_frm_proc_slave_thrd;
1340             s_thread_attr.thread_param = (void *)(aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]);
1341             s_thread_attr.group_num = i4_curr_grp_num;
1342             if(1 == ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_use_thrd_affinity)
1343             {
1344                 ihevce_static_multi_thread_params_t *ps_multi_thrd_prms =
1345                     &ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms;
1346 
1347                 s_thread_attr.core_affinity_mask = ps_multi_thrd_prms->au8_core_aff_mask[enc_ctr];
1348                 if((enc_ctr >= i4_acc_proc_num) &&
1349                    (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1))
1350                 {
1351                     /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/
1352                     s_thread_attr.group_num++;
1353                     i4_curr_grp_num++;
1354                     /* This takes care of the condition that differnt proc groups can have diff number of cores */
1355                     i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num];
1356                 }
1357             }
1358             else
1359             {
1360                 s_thread_attr.core_affinity_mask = 0;
1361                 if((enc_ctr >= i4_acc_proc_num) &&
1362                    (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1))
1363                 {
1364                     /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/
1365                     s_thread_attr.group_num++;
1366                     i4_curr_grp_num++;
1367                     /* This takes care of the condition that differnt proc groups can have diff number of cores */
1368                     i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num];
1369                 }
1370             }
1371 
1372             /* Create frame processing thread */
1373             apv_enc_frm_proc_hdls[res_ctr][ctr] =
1374                 osal_thread_create(ps_hle_ctxt->pv_osal_handle, &s_thread_attr);
1375             if(NULL == apv_enc_frm_proc_hdls[res_ctr][ctr])
1376             {
1377                 return IV_FAIL;
1378             }
1379             enc_ctr++;
1380         }
1381     }
1382 
1383     /* --------------------------------------------------------------------- */
1384     /*     Create all Pre - Encode Frame processing threads                  */
1385     /* --------------------------------------------------------------------- */
1386     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1387     {
1388         WORD32 pre_enc_ctr = 0;
1389         WORD32 i4_loop_count;
1390         WORD32 i4_curr_grp_num = 0;
1391         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1392 
1393         i4_acc_proc_num = 0;
1394 
1395         for(i4_loop_count = 0; i4_loop_count < res_ctr; i4_loop_count++)
1396             pre_enc_ctr += ps_hle_ctxt->ai4_num_core_per_res[i4_loop_count];
1397         if(ps_enc_ctxt->s_multi_thrd.i4_all_thrds_active_flag)
1398         {
1399             /* If its sequential mode of operation enc and pre-enc threads to be given same core affinity mask */
1400             pre_enc_ctr -= ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds;
1401         }
1402 
1403         if(ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)
1404         {
1405             /* Select the group number for each res based on processors present in each group */
1406             for(i4_loop_count = 0;
1407                 i4_loop_count <
1408                 ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups;
1409                 i4_loop_count++)
1410             {
1411                 i4_acc_proc_num += ai4_proc_count[i4_loop_count];
1412                 if((pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) >=
1413                    i4_acc_proc_num)
1414                 {
1415                     /* if pre_enc_ctr is greater than proc count for first group,
1416                     then increment group count.This group number will be starting grp num for
1417                     that resolution */
1418                     i4_curr_grp_num++;
1419                 }
1420                 else
1421                     break;
1422             }
1423         }
1424 
1425         for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; ctr++)
1426         {
1427             osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR;
1428 
1429             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1430             s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t);
1431 
1432             ps_hle_ctxt->ihevce_mem_alloc(
1433                 ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab);
1434             if(s_memtab.pv_base == NULL)
1435             {
1436                 return (IV_FAIL);
1437             }
1438 
1439             aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr] = (frm_proc_thrd_ctxt_t *)s_memtab.pv_base;
1440 
1441             /* initialise the interface strucure parameters */
1442             aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->i4_thrd_id = ctr;
1443 
1444             aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->ps_hle_ctxt = ps_hle_ctxt;
1445             ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1446             aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->pv_enc_ctxt = (void *)ps_enc_ctxt;
1447 
1448             /* Initialize application thread attributes */
1449             s_thread_attr.exit_code = 0;
1450             s_thread_attr.name = 0;
1451             s_thread_attr.priority_map_flag = 1;
1452             s_thread_attr.priority = OSAL_PRIORITY_DEFAULT;
1453             s_thread_attr.stack_addr = 0;
1454             s_thread_attr.stack_size = THREAD_STACK_SIZE;
1455             s_thread_attr.thread_func = ihevce_pre_enc_process_frame_thrd;
1456             s_thread_attr.thread_param = (void *)(aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]);
1457             s_thread_attr.group_num = i4_curr_grp_num;
1458 
1459             if(1 == ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_use_thrd_affinity)
1460             {
1461                 ihevce_static_multi_thread_params_t *ps_multi_thrd_prms =
1462                     &ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms;
1463 
1464                 s_thread_attr.core_affinity_mask =
1465                     ps_multi_thrd_prms->au8_core_aff_mask
1466                         [pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds];
1467                 if(((pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) >=
1468                     i4_acc_proc_num) &&
1469                    (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1))
1470                 {
1471                     /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/
1472                     s_thread_attr.group_num++;
1473                     i4_curr_grp_num++;
1474                     /* This takes care of the condition that differnt proc groups can have diff number of cores */
1475                     i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num];
1476                 }
1477             }
1478             else
1479             {
1480                 s_thread_attr.core_affinity_mask = 0;
1481 
1482                 if(((pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) >=
1483                     i4_acc_proc_num) &&
1484                    (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1))
1485                 {
1486                     /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/
1487                     s_thread_attr.group_num++;
1488                     i4_curr_grp_num++;
1489                     /* This takes care of the condition that differnt proc groups can have diff number of cores */
1490                     i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num];
1491                 }
1492             }
1493 
1494             /* Create frame processing thread */
1495             apv_pre_enc_frm_proc_hdls[res_ctr][ctr] =
1496                 osal_thread_create(ps_hle_ctxt->pv_osal_handle, &s_thread_attr);
1497             if(NULL == apv_pre_enc_frm_proc_hdls[res_ctr][ctr])
1498             {
1499                 return IV_FAIL;
1500             }
1501             pre_enc_ctr++;
1502         }
1503     }
1504 
1505     /* Set the threads init done Flag */
1506     ps_hle_ctxt->i4_hle_init_done = 1;
1507 
1508     /* --------------------------------------------------------------------- */
1509     /*            Wait and destroy Processing threads                        */
1510     /* --------------------------------------------------------------------- */
1511 
1512     /* --------------------------------------------------------------------- */
1513     /*           Frame process Pre - Encode threads destroy                  */
1514     /* --------------------------------------------------------------------- */
1515     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1516     {
1517         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1518 
1519         for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; ctr++)
1520         {
1521             /* Wait for thread to complete */
1522             osal_thread_wait(apv_pre_enc_frm_proc_hdls[res_ctr][ctr]);
1523 
1524             /* Destroy thread */
1525             osal_thread_destroy(apv_pre_enc_frm_proc_hdls[res_ctr][ctr]);
1526 
1527             s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t);
1528             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1529             s_memtab.pv_base = (void *)aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr];
1530 
1531             /* free the ctxt memory */
1532             ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
1533         }
1534     }
1535 
1536     /* --------------------------------------------------------------------- */
1537     /*           Frame process Encode slave threads destroy                  */
1538     /* --------------------------------------------------------------------- */
1539     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1540     {
1541         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
1542 
1543         for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++)
1544         {
1545             /* Wait for thread to complete */
1546             osal_thread_wait(apv_enc_frm_proc_hdls[res_ctr][ctr]);
1547 
1548             /* Destroy thread */
1549             osal_thread_destroy(apv_enc_frm_proc_hdls[res_ctr][ctr]);
1550 
1551             s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t);
1552             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1553             s_memtab.pv_base = (void *)aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr];
1554 
1555             /* free the ctxt memory */
1556             ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
1557         }
1558     }
1559 
1560     /* --------------------------------------------------------------------- */
1561     /*           Entropy threads destroy                                     */
1562     /* --------------------------------------------------------------------- */
1563     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
1564     {
1565         WORD32 i4_num_bitrates =
1566             ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr]
1567                 .i4_num_bitrate_instances;
1568 
1569         for(ctr = 0; ctr < i4_num_bitrates; ctr++)
1570         {
1571             /* Wait for Entropy Coding thread to complete */
1572             osal_thread_wait(apv_entropy_thrd_hdls[res_ctr][ctr]);
1573 
1574             /* Destroy Entropy Coding thread */
1575             osal_thread_destroy(apv_entropy_thrd_hdls[res_ctr][ctr]);
1576 
1577             //semaphore will come here
1578 
1579             s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t);
1580             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1581             s_memtab.pv_base = (void *)aps_entropy_thrd_ctxt[res_ctr][ctr];
1582 
1583             /* free the ctxt memory */
1584             ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
1585         }
1586     }
1587 
1588     s_memtab.i4_mem_size = sizeof(lap_intface_t);
1589     s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
1590     s_memtab.pv_base = (void *)ps_lap_interface_ctxt;
1591     ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
1592     /* profile stop */
1593     PROFILE_STOP(&ps_hle_ctxt->profile_hle, NULL);
1594     return (0);
1595 }
1596 
1597 /*!
1598 ******************************************************************************
1599 * \if Function name : ihevce_q_get_free_inp_data_buff \endif
1600 *
1601 * \brief
1602 *    Gets a free buffer from the que requested
1603 *
1604 * \param[in] high level encoder context pointer
1605 * \param[in] pointer to return the buffer id
1606 * \param[in] blocking mode / non blocking mode
1607 *
1608 * \return
1609 *    None
1610 *
1611 * \author
1612 *  Ittiam
1613 *
1614 *****************************************************************************
1615 */
ihevce_q_get_free_inp_data_buff(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 * pi4_buff_id,WORD32 i4_blocking_mode)1616 void *ihevce_q_get_free_inp_data_buff(
1617     ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 *pi4_buff_id, WORD32 i4_blocking_mode)
1618 {
1619     void *pv_ptr;
1620     enc_ctxt_t *ps_enc_ctxt;
1621     WORD32 i4_resolution_id = 0;
1622 
1623     ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[i4_resolution_id];
1624     if(ps_enc_ctxt->i4_frame_limit_reached == 1)
1625     {
1626         return (NULL);
1627     }
1628     /*Input buffer is same for all enc handles*/
1629     pv_ptr = ihevce_q_get_free_buff(
1630         ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_DATA_CTRL_Q, pi4_buff_id, i4_blocking_mode);
1631 
1632     return (pv_ptr);
1633 }
1634 
1635 /*!
1636 ******************************************************************************
1637 * \if Function name : ihevce_q_get_free_inp_ctrl_buff \endif
1638 *
1639 * \brief
1640 *    Gets a free buffer from the que requested
1641 *
1642 * \param[in] high level encoder context pointer
1643 * \param[in] pointer to return the buffer id
1644 * \param[in] blocking mode / non blocking mode
1645 *
1646 * \return
1647 *    None
1648 *
1649 * \author
1650 *  Ittiam
1651 *
1652 *****************************************************************************
1653 */
ihevce_q_get_free_inp_ctrl_buff(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 * pi4_buff_id,WORD32 i4_blocking_mode)1654 void *ihevce_q_get_free_inp_ctrl_buff(
1655     ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 *pi4_buff_id, WORD32 i4_blocking_mode)
1656 {
1657     void *pv_ptr;
1658 
1659     /*Input buffer is same for all enc handles*/
1660     pv_ptr = ihevce_q_get_free_buff(
1661         ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_ASYNCH_CTRL_Q, pi4_buff_id, i4_blocking_mode);
1662 
1663     return (pv_ptr);
1664 }
1665 
1666 /*!
1667 ******************************************************************************
1668 * \if Function name : ihevce_q_get_free_out_strm_buff \endif
1669 *
1670 * \brief
1671 *    Gets a free buffer from the que requested
1672 *
1673 * \param[in] high level encoder context pointer
1674 * \param[in] pointer to return the buffer id
1675 * \param[in] blocking mode / non blocking mode
1676 *
1677 * \return
1678 *    None
1679 *
1680 * \author
1681 *  Ittiam
1682 *
1683 *****************************************************************************
1684 */
ihevce_q_get_free_out_strm_buff(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 * pi4_buff_id,WORD32 i4_blocking_mode,WORD32 i4_bitrate_instance,WORD32 i4_res_instance)1685 void *ihevce_q_get_free_out_strm_buff(
1686     ihevce_hle_ctxt_t *ps_hle_ctxt,
1687     WORD32 *pi4_buff_id,
1688     WORD32 i4_blocking_mode,
1689     WORD32 i4_bitrate_instance,
1690     WORD32 i4_res_instance)
1691 {
1692     void *pv_ptr;
1693 
1694     pv_ptr = ihevce_q_get_free_buff(
1695         ps_hle_ctxt->apv_enc_hdl[i4_res_instance],
1696         (IHEVCE_OUTPUT_DATA_Q + i4_bitrate_instance),
1697         pi4_buff_id,
1698         i4_blocking_mode);
1699     return (pv_ptr);
1700 }
1701 
1702 /*!
1703 ******************************************************************************
1704 * \if Function name : ihevce_q_get_free_out_recon_buff \endif
1705 *
1706 * \brief
1707 *    Gets a free buffer from the que requested
1708 *
1709 * \param[in] high level encoder context pointer
1710 * \param[in] pointer to return the buffer id
1711 * \param[in] blocking mode / non blocking mode
1712 *
1713 * \return
1714 *    None
1715 *
1716 * \author
1717 *  Ittiam
1718 *
1719 *****************************************************************************
1720 */
ihevce_q_get_free_out_recon_buff(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 * pi4_buff_id,WORD32 i4_blocking_mode,WORD32 i4_bitrate_instance,WORD32 i4_res_instance)1721 void *ihevce_q_get_free_out_recon_buff(
1722     ihevce_hle_ctxt_t *ps_hle_ctxt,
1723     WORD32 *pi4_buff_id,
1724     WORD32 i4_blocking_mode,
1725     WORD32 i4_bitrate_instance,
1726     WORD32 i4_res_instance)
1727 {
1728     void *pv_ptr;
1729 
1730     pv_ptr = ihevce_q_get_free_buff(
1731         ps_hle_ctxt->apv_enc_hdl[i4_res_instance],
1732         (IHEVCE_RECON_DATA_Q + i4_bitrate_instance),
1733         pi4_buff_id,
1734         i4_blocking_mode);
1735     return (pv_ptr);
1736 }
1737 
1738 /*!
1739 ******************************************************************************
1740 * \if Function name : ihevce_q_set_inp_data_buff_prod \endif
1741 *
1742 * \brief
1743 *    Sets the input data buffer as produced in the que requested
1744 *
1745 * \param[in] high level encoder context pointer
1746 * \param[in] buffer id which needs to be set as produced
1747 *
1748 * \return
1749 *    None
1750 *
1751 * \author
1752 *  Ittiam
1753 *
1754 *****************************************************************************
1755 */
1756 IV_API_CALL_STATUS_T
ihevce_q_set_inp_data_buff_prod(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 i4_buff_id)1757     ihevce_q_set_inp_data_buff_prod(ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 i4_buff_id)
1758 {
1759     IV_API_CALL_STATUS_T ret_status;
1760 
1761     ret_status =
1762         ihevce_q_set_buff_prod(ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_DATA_CTRL_Q, i4_buff_id);
1763 
1764     return (ret_status);
1765 }
1766 
1767 /*!
1768 ******************************************************************************
1769 * \if Function name : ihevce_q_set_inp_ctrl_buff_prod \endif
1770 *
1771 * \brief
1772 *    Sets the input data buffer as produced in the que requested
1773 *
1774 * \param[in] high level encoder context pointer
1775 * \param[in] buffer id which needs to be set as produced
1776 *
1777 * \return
1778 *    None
1779 *
1780 * \author
1781 *  Ittiam
1782 *
1783 *****************************************************************************
1784 */
1785 IV_API_CALL_STATUS_T
ihevce_q_set_inp_ctrl_buff_prod(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 i4_buff_id)1786     ihevce_q_set_inp_ctrl_buff_prod(ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 i4_buff_id)
1787 
1788 {
1789     IV_API_CALL_STATUS_T ret_status;
1790 
1791     ret_status =
1792         ihevce_q_set_buff_prod(ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_ASYNCH_CTRL_Q, i4_buff_id);
1793 
1794     return (ret_status);
1795 }
1796 
1797 /*!
1798 ******************************************************************************
1799 * \if Function name : ihevce_q_set_out_strm_buff_prod \endif
1800 *
1801 * \brief
1802 *    Sets the Output stream buffer as produced in the que requested
1803 *
1804 * \param[in] high level encoder context pointer
1805 * \param[in] buffer id which needs to be set as produced
1806 *
1807 * \return
1808 *    None
1809 *
1810 * \author
1811 *  Ittiam
1812 *
1813 *****************************************************************************
1814 */
ihevce_q_set_out_strm_buff_prod(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 i4_buff_id,WORD32 i4_bitrate_instance_id,WORD32 i4_resolution_id)1815 IV_API_CALL_STATUS_T ihevce_q_set_out_strm_buff_prod(
1816     ihevce_hle_ctxt_t *ps_hle_ctxt,
1817     WORD32 i4_buff_id,
1818     WORD32 i4_bitrate_instance_id,
1819     WORD32 i4_resolution_id)
1820 {
1821     IV_API_CALL_STATUS_T ret_status;
1822 
1823     ret_status = ihevce_q_set_buff_prod(
1824         ps_hle_ctxt->apv_enc_hdl[i4_resolution_id],
1825         (IHEVCE_OUTPUT_DATA_Q + i4_bitrate_instance_id),
1826         i4_buff_id);
1827 
1828     return (ret_status);
1829 }
1830 
1831 /*!
1832 ******************************************************************************
1833 * \if Function name : ihevce_q_set_out_recon_buff_prod \endif
1834 *
1835 * \brief
1836 *    Sets the Output recon buffer as produced in the que requested
1837 *
1838 * \param[in] high level encoder context pointer
1839 * \param[in] buffer id which needs to be set as produced
1840 *
1841 * \return
1842 *    None
1843 *
1844 * \author
1845 *  Ittiam
1846 *
1847 *****************************************************************************
1848 */
ihevce_q_set_out_recon_buff_prod(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 i4_buff_id,WORD32 i4_bitrate_instance_id,WORD32 i4_resolution_id)1849 IV_API_CALL_STATUS_T ihevce_q_set_out_recon_buff_prod(
1850     ihevce_hle_ctxt_t *ps_hle_ctxt,
1851     WORD32 i4_buff_id,
1852     WORD32 i4_bitrate_instance_id,
1853     WORD32 i4_resolution_id)
1854 {
1855     IV_API_CALL_STATUS_T ret_status;
1856 
1857     ret_status = ihevce_q_set_buff_prod(
1858         ps_hle_ctxt->apv_enc_hdl[i4_resolution_id],
1859         (IHEVCE_RECON_DATA_Q + i4_bitrate_instance_id),
1860         i4_buff_id);
1861 
1862     return (ret_status);
1863 }
1864 
1865 //recon_dump
1866 /*!
1867 ******************************************************************************
1868 * \if Function name : ihevce_q_get_filled_recon_buff \endif
1869 *
1870 * \brief
1871 *    Gets a next filled recon buffer from the que requested
1872 *
1873 * \param[in] high level encoder context pointer
1874 * \param[in] pointer to return the buffer id
1875 * \param[in] blocking mode / non blocking mode
1876 *
1877 * \return
1878 *    None
1879 *
1880 * \author
1881 *  Ittiam
1882 *
1883 *****************************************************************************
1884 */
ihevce_q_get_filled_recon_buff(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 * pi4_buff_id,WORD32 i4_blocking_mode,WORD32 i4_bitrate_instance_id,WORD32 i4_resolution_id)1885 void *ihevce_q_get_filled_recon_buff(
1886     ihevce_hle_ctxt_t *ps_hle_ctxt,
1887     WORD32 *pi4_buff_id,
1888     WORD32 i4_blocking_mode,
1889     WORD32 i4_bitrate_instance_id,
1890     WORD32 i4_resolution_id)
1891 {
1892     void *pv_ptr;
1893 
1894     pv_ptr = ihevce_q_get_filled_buff(
1895         ps_hle_ctxt->apv_enc_hdl[i4_resolution_id],
1896         IHEVCE_RECON_DATA_Q + i4_bitrate_instance_id,
1897         pi4_buff_id,
1898         i4_blocking_mode);
1899 
1900     return (pv_ptr);
1901 }
1902 
1903 /*!
1904 ******************************************************************************
1905 * \if Function name : ihevce_q_get_filled_ctrl_sts_buff \endif
1906 *
1907 * \brief
1908 *    Gets a next filled control status buffer from the que requested
1909 *
1910 * \param[in] high level encoder context pointer
1911 * \param[in] pointer to return the buffer id
1912 * \param[in] blocking mode / non blocking mode
1913 *
1914 * \return
1915 *    None
1916 *
1917 * \author
1918 *  Ittiam
1919 *
1920 *****************************************************************************
1921 */
ihevce_q_get_filled_ctrl_sts_buff(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 * pi4_buff_id,WORD32 i4_blocking_mode)1922 void *ihevce_q_get_filled_ctrl_sts_buff(
1923     ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 *pi4_buff_id, WORD32 i4_blocking_mode)
1924 {
1925     void *pv_ptr;
1926     pv_ptr = ihevce_q_get_filled_buff(
1927         ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_OUTPUT_STATUS_Q, pi4_buff_id, i4_blocking_mode);
1928 
1929     return (pv_ptr);
1930 }
1931 
1932 //recon_dump
1933 /*!
1934 ******************************************************************************
1935 * \if Function name : ihevce_q_rel_recon_buf \endif
1936 *
1937 * \brief
1938 *    Frees the recon buffer in the recon buffer que
1939 *
1940 * \param[in] high level encoder context pointer
1941 * \param[in] buffer id which needs to be freed
1942 *
1943 * \return
1944 *    None
1945 *
1946 * \author
1947 *  Ittiam
1948 *
1949 *****************************************************************************
1950 */
ihevce_q_rel_recon_buf(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 i4_buff_id,WORD32 i4_bitrate_instance_id,WORD32 i4_resolution_id)1951 IV_API_CALL_STATUS_T ihevce_q_rel_recon_buf(
1952     ihevce_hle_ctxt_t *ps_hle_ctxt,
1953     WORD32 i4_buff_id,
1954     WORD32 i4_bitrate_instance_id,
1955     WORD32 i4_resolution_id)
1956 {
1957     IV_API_CALL_STATUS_T ret_status;
1958 
1959     ret_status = ihevce_q_rel_buf(
1960         ps_hle_ctxt->apv_enc_hdl[i4_resolution_id],
1961         IHEVCE_RECON_DATA_Q + i4_bitrate_instance_id,
1962         i4_buff_id);
1963 
1964     return (ret_status);
1965 }
1966 
1967 /*!
1968 ******************************************************************************
1969 * \if Function name : ihevce_q_rel_ctrl_sts_buf \endif
1970 *
1971 * \brief
1972 *    Frees the output control sttus buffer in buffer que
1973 *
1974 * \param[in] high level encoder context pointer
1975 * \param[in] buffer id which needs to be freed
1976 *
1977 * \return
1978 *    None
1979 *
1980 * \author
1981 *  Ittiam
1982 *
1983 *****************************************************************************
1984 */
ihevce_q_rel_ctrl_sts_buf(ihevce_hle_ctxt_t * ps_hle_ctxt,WORD32 i4_buff_id)1985 IV_API_CALL_STATUS_T ihevce_q_rel_ctrl_sts_buf(ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 i4_buff_id)
1986 {
1987     IV_API_CALL_STATUS_T ret_status;
1988 
1989     ret_status = ihevce_q_rel_buf(ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_OUTPUT_STATUS_Q, i4_buff_id);
1990 
1991     return (ret_status);
1992 }
1993 
1994 /*!
1995 ******************************************************************************
1996 * \if Function name : ihevce_hle_interface_delete \endif
1997 *
1998 * \brief
1999 *    High leve encoder delete interface
2000 *
2001 * \param[in] high level encoder interface context pointer
2002 *
2003 * \return
2004 *    None
2005 *
2006 * \author
2007 *  Ittiam
2008 *
2009 *****************************************************************************
2010 */
ihevce_hle_interface_delete(ihevce_hle_ctxt_t * ps_hle_ctxt)2011 IV_API_CALL_STATUS_T ihevce_hle_interface_delete(ihevce_hle_ctxt_t *ps_hle_ctxt)
2012 {
2013     /* local varaibles */
2014     enc_ctxt_t *ps_enc_ctxt;
2015     iv_mem_rec_t s_memtab;
2016     WORD32 ctr = 0, i, res_ctr, i4_num_resolutions;
2017     WORD32 ai4_num_bitrate_instances[IHEVCE_MAX_NUM_RESOLUTIONS] = { 1 };
2018 
2019     i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
2020     for(ctr = 0; ctr < i4_num_resolutions; ctr++)
2021     {
2022         ai4_num_bitrate_instances[ctr] =
2023             ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[ctr]
2024                 .i4_num_bitrate_instances;
2025     }
2026 
2027     for(res_ctr = 0; res_ctr < i4_num_resolutions && ps_hle_ctxt->apv_enc_hdl[res_ctr]; res_ctr++)
2028     {
2029         ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr];
2030 
2031         if(res_ctr == 0)
2032         {
2033             osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_sem_handle);
2034             osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_data_sem_handle);
2035             osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_ctrl_sem_handle);
2036             if(1 == ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_mres_single_out)
2037             {
2038                 osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_ent_common_mres_sem_hdl);
2039                 osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_common_mres_sem_hdl);
2040             }
2041         }
2042 
2043         osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_inp_data_sem_hdl);
2044         osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_preenc_inp_data_sem_hdl);
2045 
2046         osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_enc_frm_proc_sem_handle);
2047         osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_pre_enc_frm_proc_sem_handle);
2048 
2049         osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_ctrl_sem_handle);
2050 
2051         for(i = 0; i < ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr]
2052                            .i4_num_bitrate_instances;
2053             i++)
2054         {
2055             osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.apv_ent_cod_sem_handle[i]);
2056             osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_strm_sem_handle[i]);
2057             osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_recon_sem_handle[i]);
2058         }
2059 
2060         /* destroy the mutex  allocated for job queue usage encode group */
2061         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_me);
2062 
2063         /* destroy the mutex  allocated for job queue usage encode group */
2064         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_enc_loop);
2065 
2066         /* destroy the mutexes allocated for enc thread group */
2067         for(i = 0; i < MAX_NUM_ME_PARALLEL; i++)
2068         {
2069             osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i]);
2070 
2071             osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i]);
2072         }
2073 
2074         for(i = 0; i < MAX_NUM_ENC_LOOP_PARALLEL; i++)
2075         {
2076             osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i]);
2077 
2078             osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i]);
2079         }
2080 
2081         /* destroy the mutex  allocated for job queue, init and de-init
2082         usage pre enocde group */
2083         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_decomp);
2084         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_hme);
2085         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_l0ipe);
2086         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_init);
2087         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_decomp_deinit);
2088         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_init);
2089         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit);
2090         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_l0_ipe_init);
2091         osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_deinit);
2092 
2093         /* destroy the EncLoop Module */
2094         /* Note : Only Destroys the resources allocated in the module like */
2095         /* semaphore,etc. Memory free is done separately using memtabs     */
2096         ihevce_enc_loop_delete(ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt);
2097 
2098         /* destroy the Coarse ME Module */
2099         /* Note : Only Destroys the resources allocated in the module like */
2100         /* semaphore,etc. Memory free is done separately using memtabs     */
2101         ihevce_coarse_me_delete(
2102             ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt,
2103             ps_hle_ctxt->ps_static_cfg_prms,
2104             ps_enc_ctxt->i4_resolution_id);
2105         /* destroy semaphores for all the threads in pre-enc and enc */
2106         for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++)
2107         {
2108             osal_sem_destroy(ps_enc_ctxt->s_multi_thrd.apv_enc_thrd_sem_handle[ctr]);
2109         }
2110 
2111         for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; ctr++)
2112         {
2113             osal_sem_destroy(ps_enc_ctxt->s_multi_thrd.apv_pre_enc_thrd_sem_handle[ctr]);
2114         }
2115 
2116         /* destroy the ME-EncLoop Dep Mngr */
2117         /* Note : Only Destroys the resources allocated in the module like */
2118         /* semaphore,etc. Memory free is done separately using memtabs     */
2119         for(ctr = 0; ctr < NUM_ME_ENC_BUFS; ctr++)
2120         {
2121             ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_encloop_dep_me[ctr]);
2122         }
2123         /* destroy the Prev. frame EncLoop Done Dep Mngr */
2124         /* Note : Only Destroys the resources allocated in the module like */
2125         /* semaphore,etc. Memory free is done separately using memtabs     */
2126         for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel; i++)
2127         {
2128             ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i]);
2129         }
2130         /* destroy the Prev. frame EncLoop Done for re-encode Dep Mngr */
2131         ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_enc_done_for_reenc);
2132 
2133         /* destroy the Prev. frame ME Done Dep Mngr */
2134         /* Note : Only Destroys the resources allocated in the module like */
2135         /* semaphore,etc. Memory free is done separately using memtabs     */
2136         for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel; i++)
2137         {
2138             ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i]);
2139         }
2140 
2141         /* destroy the Prev. frame PreEnc L1 Done Dep Mngr */
2142         /* Note : Only Destroys the resources allocated in the module like */
2143         /* semaphore,etc. Memory free is done separately using memtabs     */
2144         ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l1);
2145 
2146         /* destroy the Prev. frame PreEnc HME Done Dep Mngr */
2147         /* Note : Only Destroys the resources allocated in the module like */
2148         /* semaphore,etc. Memory free is done separately using memtabs     */
2149         ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_coarse_me);
2150 
2151         /* destroy the Prev. frame PreEnc L0 Done Dep Mngr */
2152         /* Note : Only Destroys the resources allocated in the module like */
2153         /* semaphore,etc. Memory free is done separately using memtabs     */
2154         ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l0);
2155 
2156         /* destroy the ME-Prev Recon  Dep Mngr    */
2157         /* Note : Only Destroys the resources allocated in the module like */
2158         /* semaphore,etc. Memory free is done separately using memtabs     */
2159         for(ctr = 0; ctr < ps_enc_ctxt->ai4_num_buf_recon_q[0]; ctr++)
2160         {
2161             ihevce_dmgr_del(ps_enc_ctxt->pps_recon_buf_q[0][ctr]->pv_dep_mngr_recon);
2162         }
2163 
2164         /* destroy all the mutex created */
2165         if(res_ctr == 0)
2166         {
2167             if(NULL != ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl)
2168             {
2169                 osal_mutex_destroy(ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl);
2170             }
2171         }
2172 
2173         if(NULL != ps_enc_ctxt->pv_rc_mutex_lock_hdl)
2174         {
2175             osal_mutex_destroy(ps_enc_ctxt->pv_rc_mutex_lock_hdl);
2176         }
2177 
2178         if(NULL != ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl)
2179         {
2180             osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl);
2181         }
2182 
2183         if(NULL != ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl)
2184         {
2185             osal_mutex_destroy(
2186                 ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl);
2187         }
2188 
2189         /* call the memrory free function */
2190         ihevce_mem_manager_free(ps_enc_ctxt, ps_hle_ctxt);
2191         if((1 == ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_mres_single_out) &&
2192            (res_ctr == 0))
2193         {
2194             s_memtab.i4_mem_size = sizeof(WORD32) * IHEVCE_MAX_NUM_RESOLUTIONS;
2195             s_memtab.i4_mem_alignment = 4;
2196             s_memtab.i4_size = sizeof(iv_mem_rec_t);
2197             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
2198             s_memtab.pv_base = ps_enc_ctxt->s_multi_thrd.pi4_active_res_id;
2199             /* free active_res_id memory */
2200             ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
2201         }
2202         if(res_ctr == (i4_num_resolutions - 1))
2203         {
2204             s_memtab.i4_mem_size = sizeof(ihevce_static_cfg_params_t);
2205             s_memtab.i4_mem_alignment = 4;
2206             s_memtab.i4_size = sizeof(iv_mem_rec_t);
2207             s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
2208             s_memtab.pv_base = ps_enc_ctxt->ps_stat_prms;
2209 
2210             /* free the encoder context pointer */
2211             ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
2212         }
2213         s_memtab.i4_mem_size = sizeof(enc_ctxt_t);
2214         s_memtab.i4_mem_alignment = 4;
2215         s_memtab.i4_size = sizeof(iv_mem_rec_t);
2216         s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM;
2217         s_memtab.pv_base = ps_enc_ctxt;
2218 
2219         /* free the encoder context pointer */
2220         ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab);
2221 
2222         /* reset the encoder handle to NULL */
2223         ps_hle_ctxt->apv_enc_hdl[res_ctr] = NULL;
2224     }
2225     /* profile end */
2226     PROFILE_END(&ps_hle_ctxt->profile_hle, "hle interface thread active time");
2227     for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++)
2228     {
2229         WORD32 i4_br_id;
2230 
2231         PROFILE_END(&ps_hle_ctxt->profile_pre_enc_l1l2[res_ctr], "pre enc l1l2 process");
2232         PROFILE_END(&ps_hle_ctxt->profile_pre_enc_l0ipe[res_ctr], "pre enc l0 ipe process");
2233         PROFILE_END(&ps_hle_ctxt->profile_enc_me[res_ctr], "enc me process");
2234         for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[res_ctr]; i4_br_id++)
2235         {
2236             PROFILE_END(&ps_hle_ctxt->profile_enc[res_ctr][i4_br_id], "enc loop process");
2237             PROFILE_END(&ps_hle_ctxt->profile_entropy[res_ctr][i4_br_id], "entropy process");
2238         }
2239     }
2240 
2241     /* OSAL Delete */
2242     ihevce_osal_delete((void *)ps_hle_ctxt);
2243 
2244     return (IV_SUCCESS);
2245 }
2246