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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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