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