| /****************************************************************************** |
| * |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ***************************************************************************** |
| * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| */ |
| |
| /*! |
| ****************************************************************************** |
| * \file ihevce_hle_interface.c |
| * |
| * \brief |
| * This file contains all the functions related High level enocder |
| * Interface layer |
| * |
| * \date |
| * 18/09/2012 |
| * |
| * \author |
| * Ittiam |
| * |
| * List of Functions |
| * <TODO: TO BE ADDED> |
| * |
| ****************************************************************************** |
| */ |
| |
| /*****************************************************************************/ |
| /* File Includes */ |
| /*****************************************************************************/ |
| /* System include files */ |
| #include <stdio.h> |
| #include <string.h> |
| #include <stdlib.h> |
| #include <assert.h> |
| #include <stdarg.h> |
| #include <math.h> |
| #include <time.h> |
| |
| /* User include files */ |
| #include "ihevc_typedefs.h" |
| #include "itt_video_api.h" |
| #include "ihevce_api.h" |
| |
| #include "rc_cntrl_param.h" |
| #include "rc_frame_info_collector.h" |
| #include "rc_look_ahead_params.h" |
| |
| #include "ihevc_defs.h" |
| #include "ihevc_macros.h" |
| #include "ihevc_debug.h" |
| #include "ihevc_structs.h" |
| #include "ihevc_platform_macros.h" |
| #include "ihevc_deblk.h" |
| #include "ihevc_itrans_recon.h" |
| #include "ihevc_chroma_itrans_recon.h" |
| #include "ihevc_chroma_intra_pred.h" |
| #include "ihevc_intra_pred.h" |
| #include "ihevc_inter_pred.h" |
| #include "ihevc_mem_fns.h" |
| #include "ihevc_padding.h" |
| #include "ihevc_weighted_pred.h" |
| #include "ihevc_sao.h" |
| #include "ihevc_resi_trans.h" |
| #include "ihevc_quant_iquant_ssd.h" |
| #include "ihevc_cabac_tables.h" |
| #include "ihevc_trans_tables.h" |
| #include "ihevc_trans_macros.h" |
| |
| #include "ihevce_defs.h" |
| #include "ihevce_hle_interface.h" |
| #include "ihevce_hle_q_func.h" |
| #include "ihevce_buffer_que_interface.h" |
| #include "ihevce_lap_enc_structs.h" |
| #include "ihevce_multi_thrd_structs.h" |
| #include "ihevce_multi_thrd_funcs.h" |
| #include "ihevce_me_common_defs.h" |
| #include "ihevce_had_satd.h" |
| #include "ihevce_error_codes.h" |
| #include "ihevce_error_checks.h" |
| #include "ihevce_bitstream.h" |
| #include "ihevce_cabac.h" |
| #include "ihevce_rdoq_macros.h" |
| #include "ihevce_function_selector.h" |
| #include "ihevce_enc_structs.h" |
| #include "ihevce_cmn_utils_instr_set_router.h" |
| #include "ihevce_memory_init.h" |
| #include "ihevce_lap_interface.h" |
| #include "ihevce_entropy_cod.h" |
| #include "ihevce_entropy_structs.h" |
| #include "ihevce_frame_process_utils.h" |
| #include "ihevce_frame_process.h" |
| #include "ihevce_profile.h" |
| #include "ihevce_global_tables.h" |
| #include "ihevce_dep_mngr_interface.h" |
| #include "ihevce_common_utils.h" |
| #include "hme_datatype.h" |
| #include "hme_interface.h" |
| #include "hme_common_defs.h" |
| #include "hme_defs.h" |
| #include "ihevce_coarse_me_pass.h" |
| #include "ihevce_me_pass.h" |
| #include "ihevce_enc_loop_structs.h" |
| #include "ihevce_enc_loop_pass.h" |
| |
| #include "cast_types.h" |
| #include "osal.h" |
| #include "osal_defaults.h" |
| |
| /*****************************************************************************/ |
| /* Function Definitions */ |
| /*****************************************************************************/ |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_context_reset \endif |
| * |
| * \brief |
| * Encoder reset function |
| * |
| * \param[in] Encoder context pointer |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void ihevce_context_reset(enc_ctxt_t *ps_enc_ctxt) |
| { |
| ps_enc_ctxt->i4_end_flag = 0; |
| |
| /* set the queue related pointer and buffer to default value */ |
| ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl = NULL; |
| |
| /* Reset the i/o queues created status to 0 */ |
| ps_enc_ctxt->i4_io_queues_created = 0; |
| |
| /* reset the frame limit flag to 0 */ |
| ps_enc_ctxt->i4_frame_limit_reached = 0; |
| |
| return; |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_hle_interface_create \endif |
| * |
| * \brief |
| * High level Encoder create function |
| * |
| * \param[in] High level enocder interface context pointer |
| * |
| * \return |
| * success or fail |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T ihevce_hle_interface_create(ihevce_hle_ctxt_t *ps_hle_ctxt) |
| { |
| /* local variables */ |
| enc_ctxt_t *ps_enc_ctxt; |
| iv_mem_rec_t s_memtab; |
| ihevce_static_cfg_params_t *ps_enc_static_cfg_params; |
| WORD32 i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers; |
| WORD32 i4_look_ahead_frames_in_first_pass = -1; |
| WORD32 i4_total_cores = 0, ctr, i4_mres_flag = 0; |
| ihevce_sys_api_t *ps_sys_api = &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api; |
| |
| WORD32 status = 0; |
| WORD32 i; |
| WORD32 *pi4_active_res_id = NULL; |
| |
| /* OSAL Init */ |
| status = ihevce_osal_init((void *)ps_hle_ctxt); |
| |
| if(status != 0) |
| return (IV_FAIL); |
| |
| /* --------------------------------------------------------------------- */ |
| /* High Level Encoder Init */ |
| /* --------------------------------------------------------------------- */ |
| |
| if(i4_num_resolutions > 1) |
| i4_mres_flag = 1; |
| /* set no error in the output */ |
| ps_hle_ctxt->i4_error_code = 0; |
| |
| /* Error checks on the static parameters passed */ |
| ps_hle_ctxt->i4_error_code = ihevce_hle_validate_static_params(ps_hle_ctxt->ps_static_cfg_prms); |
| |
| /*memory for static cfg params for encoder, which can be overwritten if encoder wants |
| encoder should use this for all its usage*/ |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.i4_mem_alignment = 4; |
| s_memtab.i4_mem_size = sizeof(ihevce_static_cfg_params_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_hle_ctxt->ps_static_cfg_prms->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| ps_enc_static_cfg_params = (ihevce_static_cfg_params_t *)s_memtab.pv_base; |
| memcpy( |
| ps_enc_static_cfg_params, |
| ps_hle_ctxt->ps_static_cfg_prms, |
| (sizeof(ihevce_static_cfg_params_t))); |
| |
| i4_total_cores = ps_enc_static_cfg_params->s_multi_thrd_prms.i4_max_num_cores; |
| |
| /* check for validity of memory control flag (only 0,1,2 modes are allowed) */ |
| if((ps_enc_static_cfg_params->s_multi_thrd_prms.i4_memory_alloc_ctrl_flag > 2) || |
| (ps_enc_static_cfg_params->s_multi_thrd_prms.i4_memory_alloc_ctrl_flag < 0)) |
| { |
| ps_hle_ctxt->i4_error_code = IHEVCE_INVALID_MEM_CTRL_FLAG; |
| } |
| |
| if((i4_mres_flag == 1) && |
| (ps_enc_static_cfg_params->s_multi_thrd_prms.i4_use_thrd_affinity == 1)) |
| { |
| ps_sys_api->ihevce_printf( |
| ps_sys_api->pv_cb_handle, |
| "\nIHEVCE WARNING: Enabling thread affinity in multiresolution encoding will affect " |
| "performance\n"); |
| } |
| if((ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset == |
| IHEVCE_QUALITY_P6) && |
| (ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc)) |
| { |
| ps_sys_api->ihevce_printf( |
| ps_sys_api->pv_cb_handle, |
| "\nIHEVCE WARNING: Disabling CU level QP modulation for P6 preset\n"); |
| ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc = 0; |
| } |
| if((ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[0].i4_quality_preset == |
| IHEVCE_QUALITY_P7) && |
| (ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc)) |
| { |
| ps_sys_api->ihevce_printf( |
| ps_sys_api->pv_cb_handle, |
| "\nIHEVCE WARNING: Disabling CU level QP modulation for P7 preset\n"); |
| ps_enc_static_cfg_params->s_config_prms.i4_cu_level_rc = 0; |
| } |
| |
| if(0 != ps_hle_ctxt->i4_error_code) |
| { |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| return (IV_FAIL); |
| } |
| ps_hle_ctxt->ai4_num_core_per_res[0] = i4_total_cores; |
| |
| if(1 == ps_enc_static_cfg_params->s_tgt_lyr_prms.i4_mres_single_out) |
| { |
| /* Memory Allocation of pi4_active_res_id */ |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.i4_mem_alignment = 4; |
| s_memtab.i4_mem_size = sizeof(WORD32) * (IHEVCE_MAX_NUM_RESOLUTIONS + 1); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_static_cfg_params->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| |
| pi4_active_res_id = (WORD32 *)s_memtab.pv_base; |
| } |
| /* --------------------------------------------------------------------- */ |
| /* Context and Memory Initialization of Encoder ctxt */ |
| /* --------------------------------------------------------------------- */ |
| for(ctr = 0; ctr < i4_num_resolutions; ctr++) |
| { |
| WORD32 i4_br_id; |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.i4_mem_alignment = 4; |
| s_memtab.i4_mem_size = sizeof(enc_ctxt_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_static_cfg_params->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| |
| ps_enc_ctxt = (enc_ctxt_t *)s_memtab.pv_base; |
| |
| ps_enc_ctxt->ps_stat_prms = ps_enc_static_cfg_params; |
| |
| /* check of number of cores to decide the num threads active */ |
| ps_enc_ctxt->s_multi_thrd.i4_all_thrds_active_flag = 1; |
| |
| if(1 == ps_enc_static_cfg_params->s_tgt_lyr_prms.i4_mres_single_out) |
| { |
| pi4_active_res_id[ctr] = 0; |
| ps_enc_ctxt->s_multi_thrd.pi4_active_res_id = pi4_active_res_id; |
| } |
| |
| /*store num bit-rate instances in the encoder context */ |
| ps_enc_ctxt->i4_num_bitrates = |
| ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[ctr].i4_num_bitrate_instances; |
| |
| if(1 == ps_enc_static_cfg_params->s_config_prms.i4_rate_control_mode) |
| { |
| LWORD64 i8_peak_bitrate; |
| for(i4_br_id = 0; i4_br_id < ps_enc_ctxt->i4_num_bitrates; i4_br_id++) |
| { |
| i8_peak_bitrate = |
| (ULWORD64)(ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[ctr] |
| .ai4_peak_bitrate[i4_br_id]); |
| |
| ps_enc_static_cfg_params->s_tgt_lyr_prms.as_tgt_params[ctr] |
| .ai4_tgt_bitrate[i4_br_id] = (WORD32)( |
| (i8_peak_bitrate * ps_enc_static_cfg_params->s_config_prms.i4_rate_factor) / |
| 1000); |
| } |
| } |
| |
| if(BLU_RAY_SUPPORT == ps_enc_static_cfg_params->s_out_strm_prms.i4_interop_flags) |
| { |
| ps_enc_ctxt->i4_blu_ray_spec = 1; |
| } |
| else |
| { |
| ps_enc_ctxt->i4_blu_ray_spec = 0; |
| } |
| |
| /* if all threads are required to be active */ |
| if(1 == ps_enc_ctxt->s_multi_thrd.i4_all_thrds_active_flag) |
| { |
| /* store the number of threads to be created as passed by app with HT flag */ |
| ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds = |
| ps_hle_ctxt->ai4_num_core_per_res[ctr]; |
| |
| /* pre enc threads are doubled if HT is ON */ |
| ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds = |
| ps_hle_ctxt->ai4_num_core_per_res[ctr]; |
| } |
| else |
| { |
| // TODO: distribute threads across stages |
| } |
| |
| /*Keep track of resolution id, this is used to differentiate from other encoder instance*/ |
| ps_enc_ctxt->i4_resolution_id = ctr; |
| /* store hle ctxt in enc ctxt */ |
| ps_enc_ctxt->pv_hle_ctxt = (void *)ps_hle_ctxt; |
| ps_enc_ctxt->pv_rc_mutex_lock_hdl = NULL; |
| ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl = NULL; |
| ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl = NULL; |
| ps_enc_ctxt->i4_look_ahead_frames_in_first_pass = i4_look_ahead_frames_in_first_pass; |
| |
| ps_enc_ctxt->ai4_is_past_pic_complex[0] = 0; |
| ps_enc_ctxt->ai4_is_past_pic_complex[1] = 0; |
| ps_enc_ctxt->i4_is_I_reset_done = 1; |
| ps_enc_ctxt->i4_past_RC_reset_count = 0; |
| ps_enc_ctxt->i4_future_RC_reset = 0; |
| ps_enc_ctxt->i4_past_RC_scd_reset_count = 0; |
| ps_enc_ctxt->i4_future_RC_scd_reset = 0; |
| ps_enc_ctxt->i4_active_scene_num = -1; |
| for(i = 0; i < IHEVCE_MAX_NUM_BITRATES; i++) |
| { |
| ps_enc_ctxt->ai4_rc_query[i] = 0; |
| } |
| ps_enc_ctxt->i4_active_enc_frame_id = 0; |
| ps_enc_ctxt->u1_is_popcnt_available = 1; |
| |
| #ifndef ARM |
| ps_enc_ctxt->e_arch_type = ARCH_X86_GENERIC; |
| ps_enc_ctxt->u1_is_popcnt_available = 0; |
| #else |
| if(ps_enc_static_cfg_params->e_arch_type == ARCH_NA) |
| ps_enc_ctxt->e_arch_type = ihevce_default_arch(); |
| else |
| ps_enc_ctxt->e_arch_type = ps_enc_static_cfg_params->e_arch_type; |
| ps_enc_ctxt->u1_is_popcnt_available = 0; |
| #endif |
| |
| { |
| ps_enc_static_cfg_params->e_arch_type = ps_enc_ctxt->e_arch_type; |
| |
| ihevce_init_function_ptr(ps_enc_ctxt, ps_enc_ctxt->e_arch_type); |
| } |
| |
| ihevce_mem_manager_init(ps_enc_ctxt, ps_hle_ctxt); |
| |
| if(0 != ps_hle_ctxt->i4_error_code) |
| { |
| return (IV_FAIL); |
| } |
| |
| /* mutex lock for RC calls */ |
| ps_enc_ctxt->pv_rc_mutex_lock_hdl = osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->pv_rc_mutex_lock_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* mutex lock for Sub pic RC calls */ |
| ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* reset the encoder context */ |
| ihevce_context_reset(ps_enc_ctxt); |
| |
| /* register the Encoder context in HLE interface ctxt */ |
| ps_hle_ctxt->apv_enc_hdl[ctr] = ps_enc_ctxt; |
| } |
| /* init profile */ |
| PROFILE_INIT(&ps_hle_ctxt->profile_hle); |
| for(ctr = 0; ctr < i4_num_resolutions; ctr++) |
| { |
| WORD32 i4_br_id; |
| |
| PROFILE_INIT(&ps_hle_ctxt->profile_pre_enc[ctr]); |
| for(i4_br_id = 0; i4_br_id < ps_enc_ctxt->i4_num_bitrates; i4_br_id++) |
| { |
| PROFILE_INIT(&ps_hle_ctxt->profile_enc[ctr][i4_br_id]); |
| PROFILE_INIT(&ps_hle_ctxt->profile_entropy[ctr][i4_br_id]); |
| } |
| } |
| if(1 == ps_enc_static_cfg_params->s_tgt_lyr_prms.i4_mres_single_out) |
| pi4_active_res_id[i4_num_resolutions] = 0; |
| |
| return (IV_SUCCESS); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_query_io_buf_req \endif |
| * |
| * \brief |
| * High level Encoder IO buffers query function |
| * |
| * \param[in] High level encoder interface context pointer |
| * \param[out] Input buffer requirment stucture pointer. |
| * \param[out] Output buffer requirment stucture pointer. |
| * |
| * \return |
| * success or fail |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T 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) |
| { |
| /* local variables */ |
| enc_ctxt_t *ps_enc_ctxt; |
| ihevce_src_params_t *ps_src_prms; |
| WORD32 ctb_align_pic_wd; |
| WORD32 ctb_align_pic_ht, i4_resolution_id = 0, i4_num_resolutions, i4_num_bitrate_instances; |
| WORD32 i4_resolution_id_ctr, br_ctr; |
| |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[i4_resolution_id]; |
| ps_src_prms = &ps_hle_ctxt->ps_static_cfg_prms->s_src_prms; |
| i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers; |
| /* set no error in the output */ |
| ps_hle_ctxt->i4_error_code = 0; |
| |
| /* ------- populate the Input buffer requirements -------- */ |
| /* get the number of buffers required for LAP */ |
| ps_input_bufs_req->i4_min_num_yuv_bufs = |
| ihevce_lap_get_num_ip_bufs(&ps_enc_ctxt->s_lap_stat_prms); |
| |
| ps_input_bufs_req->i4_min_num_synch_ctrl_bufs = ps_input_bufs_req->i4_min_num_yuv_bufs; |
| |
| ps_input_bufs_req->i4_min_num_asynch_ctrl_bufs = NUM_AYSNC_CMD_BUFS; |
| |
| /* buffer sizes are populated based on create time parameters */ |
| ctb_align_pic_wd = |
| ps_src_prms->i4_width + |
| SET_CTB_ALIGN(ps_src_prms->i4_width, ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size); |
| |
| ctb_align_pic_ht = |
| ps_src_prms->i4_height + |
| SET_CTB_ALIGN(ps_src_prms->i4_height, ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size); |
| |
| if(ps_src_prms->i4_input_bit_depth > 8) |
| { |
| ps_input_bufs_req->i4_min_size_y_buf = ctb_align_pic_wd * ctb_align_pic_ht * 2; |
| |
| ps_input_bufs_req->i4_min_size_uv_buf = ps_input_bufs_req->i4_min_size_y_buf >> 1; |
| } |
| else |
| { |
| ps_input_bufs_req->i4_min_size_y_buf = ctb_align_pic_wd * ctb_align_pic_ht; |
| |
| ps_input_bufs_req->i4_min_size_uv_buf = (ctb_align_pic_wd * ctb_align_pic_ht) >> 1; |
| } |
| |
| ps_input_bufs_req->i4_min_size_uv_buf <<= |
| ((ps_src_prms->i4_chr_format == IV_YUV_422SP_UV) ? 1 : 0); |
| |
| ps_input_bufs_req->i4_yuv_format = ps_src_prms->i4_chr_format; |
| |
| ps_input_bufs_req->i4_min_size_synch_ctrl_bufs = |
| ((MAX_SEI_PAYLOAD_PER_TLV + 16) * MAX_NUMBER_OF_SEI_PAYLOAD) + 16; |
| |
| ps_input_bufs_req->i4_min_size_asynch_ctrl_bufs = |
| ((MAX_SEI_PAYLOAD_PER_TLV + 16) * (MAX_NUMBER_OF_SEI_PAYLOAD - 6)) + 16; |
| |
| for(i4_resolution_id_ctr = 0; i4_resolution_id_ctr < i4_num_resolutions; i4_resolution_id_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[i4_resolution_id_ctr]; |
| |
| i4_num_bitrate_instances = ps_enc_ctxt->s_runtime_tgt_params.i4_num_bitrate_instances; |
| |
| /* buffer sizes are populated based on create time parameters */ |
| ctb_align_pic_wd = ps_enc_ctxt->s_runtime_tgt_params.i4_width + |
| SET_CTB_ALIGN( |
| ps_enc_ctxt->s_runtime_tgt_params.i4_width, |
| ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size); |
| |
| ctb_align_pic_ht = ps_enc_ctxt->s_runtime_tgt_params.i4_height + |
| SET_CTB_ALIGN( |
| ps_enc_ctxt->s_runtime_tgt_params.i4_height, |
| ps_enc_ctxt->s_frm_ctb_prms.i4_ctb_size); |
| |
| for(br_ctr = 0; br_ctr < i4_num_bitrate_instances; br_ctr++) |
| { |
| /* ------- populate the Output buffer requirements -------- */ |
| ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_num_out_bufs = NUM_OUTPUT_BUFS; |
| |
| ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_bitstream_buf = (ctb_align_pic_wd * ctb_align_pic_ht); |
| |
| if((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth == 12) || |
| ((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth > 8) && |
| (ps_src_prms->i4_chr_format == IV_YUV_422SP_UV))) |
| { |
| ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_bitstream_buf *= 2; |
| } |
| |
| if((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth == 10) && |
| (ps_src_prms->i4_chr_format == IV_YUV_420SP_UV)) |
| { |
| ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_bitstream_buf *= 3; |
| ps_res_layer_output_bufs_req->s_output_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_bitstream_buf >>= 1; |
| } |
| |
| //recon_dump |
| /* ------- populate the Recon buffer requirements -------- */ |
| if(ps_enc_ctxt->ps_stat_prms->i4_save_recon == 0) |
| { |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_num_recon_bufs = 0; |
| |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_y_buf = 0; |
| |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_uv_buf = 0; |
| } |
| else |
| { |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_num_recon_bufs = 2 * HEVCE_MAX_REF_PICS + 1; |
| |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_y_buf = |
| ctb_align_pic_wd * ctb_align_pic_ht * |
| ((ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_internal_bit_depth > 8) |
| ? 2 |
| : 1); |
| |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_uv_buf = |
| (ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_y_buf >> |
| 1); |
| ps_res_layer_recon_bufs_req->s_recon_buf_req[i4_resolution_id_ctr][br_ctr] |
| .i4_min_size_uv_buf <<= |
| ((ps_src_prms->i4_chr_format == IV_YUV_422SP_UV) ? 1 : 0); |
| } |
| } |
| } |
| |
| return (IV_SUCCESS); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_create_ports \endif |
| * |
| * \brief |
| * High level Encoder IO ports Create function |
| * |
| * \param[in] High level encoder interface context pointer |
| * \param[in] Input data buffer descriptor |
| * \param[in] Input control buffer descriptor |
| * \param[in] Output data buffer descriptor |
| * \param[in] Output control status buffer descriptor |
| * \param[out] Pointer to store the ID for Input data Que |
| * \param[out] Pointer to store the ID for Input control Que |
| * \param[out] Pointer to store the ID for Output data Que |
| * \param[out] Pointer to store the ID for Output control status Que |
| * |
| * \return |
| * success or fail |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T 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) |
| { |
| /* local varaibles */ |
| enc_ctxt_t *ps_enc_ctxt; |
| WORD32 res_ctr, |
| i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers; |
| void *pv_q_mutex_hdl = NULL; |
| |
| /* set no error in the output */ |
| ps_hle_ctxt->i4_error_code = 0; |
| |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| /* check on buffer sizes provided by applciation needs to be checked */ |
| |
| /* call the memory manager que init function , pass the op data , status, recon for the first bitrate, internally we will increment*/ |
| ihevce_mem_manager_que_init( |
| ps_enc_ctxt, |
| ps_hle_ctxt, |
| ps_input_data_ctrl_buffs_desc, |
| ps_input_asynch_ctrl_buffs_desc, |
| &ps_mres_output_data_buffs_desc->s_output_data_buffs[res_ctr][0], |
| &ps_mres_recon_data_buffs_desc->s_recon_data_buffs[res_ctr][0]); |
| |
| /* set the number of Queues */ |
| ps_enc_ctxt->s_enc_ques.i4_num_queues = IHEVCE_MAX_NUM_QUEUES; |
| |
| /* allocate a mutex to take care of handling multiple threads accesing Queues */ |
| /*my understanding, this is common semaphore for all the queue. Since main input is still |
| common across all instance fo encoder. Hence common semaphore is a must*/ |
| if(0 == res_ctr) |
| { |
| ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl = osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| /* store it in local variable for allocating it to other instances */ |
| pv_q_mutex_hdl = ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl; |
| if(NULL == pv_q_mutex_hdl) |
| { |
| return IV_FAIL; |
| } |
| } |
| else |
| { |
| ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl = pv_q_mutex_hdl; |
| } |
| |
| /* Set the i/o queues created status to 1 */ |
| ps_enc_ctxt->i4_io_queues_created = 1; |
| } |
| return (IV_SUCCESS); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_hle_interface_thrd \endif |
| * |
| * \brief |
| * High level encoder thread interface function |
| * |
| * \param[in] High level interface context pointer |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| WORD32 ihevce_hle_interface_thrd(void *pv_proc_intf_ctxt) |
| { |
| /* local variables */ |
| WORD32 ctr, res_ctr; |
| ihevce_hle_ctxt_t *ps_hle_ctxt; |
| enc_ctxt_t *ps_enc_ctxt; |
| /* enc ctxt to store 0th instance's params which are required by all instances */ |
| enc_ctxt_t *ps_enc_ctxt_base; |
| void *pv_lap_sem_hdl; |
| void *pv_enc_frame_process_sem_hdl; |
| void *pv_pre_enc_frame_process_sem_hdl; |
| void *apv_ent_coding_sem_hdl[IHEVCE_MAX_NUM_BITRATES]; |
| void *pv_ent_common_mres_sem_hdl = NULL; |
| void *pv_out_common_mres_sem_hdl = NULL; |
| |
| void *pv_inp_data_sem_hdl; |
| void *pv_lap_inp_data_sem_hdl; |
| void *pv_preenc_inp_data_sem_hdl; |
| void *pv_inp_ctrl_sem_hdl; |
| void *apv_out_stream_sem_hdl[IHEVCE_MAX_NUM_BITRATES]; |
| void *apv_out_recon_sem_hdl[IHEVCE_MAX_NUM_BITRATES]; |
| void *pv_out_ctrl_sts_sem_hdl; |
| |
| lap_intface_t *ps_lap_interface_ctxt; |
| iv_mem_rec_t s_memtab; |
| WORD32 i4_num_bit_rate_instances[IHEVCE_MAX_NUM_RESOLUTIONS], i4_num_resolutions; |
| WORD32 i; //loop variable |
| WORD32 ai4_proc_count[MAX_NUMBER_PROC_GRPS] = { 0 }, i4_proc_grp_count; |
| WORD32 i4_acc_proc_num = 0; |
| |
| /* Frame Encode processing threads & semaphores */ |
| void *apv_enc_frm_proc_hdls[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_ENC]; |
| frm_proc_thrd_ctxt_t |
| *aps_enc_frm_proc_thrd_ctxt[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_ENC]; |
| |
| /* Pre Frame Encode processing threads & semaphores */ |
| void *apv_pre_enc_frm_proc_hdls[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_PRE_ENC]; |
| frm_proc_thrd_ctxt_t |
| *aps_pre_enc_frm_proc_thrd_ctxt[IHEVCE_MAX_NUM_RESOLUTIONS][MAX_NUM_FRM_PROC_THRDS_PRE_ENC]; |
| |
| void *apv_entropy_thrd_hdls[IHEVCE_MAX_NUM_RESOLUTIONS][NUM_ENTROPY_THREADS]; |
| frm_proc_thrd_ctxt_t *aps_entropy_thrd_ctxt[IHEVCE_MAX_NUM_RESOLUTIONS][NUM_ENTROPY_THREADS]; |
| |
| ps_hle_ctxt = (ihevce_hle_ctxt_t *)pv_proc_intf_ctxt; |
| ps_enc_ctxt_base = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[0]; |
| /* profile start */ |
| PROFILE_START(&ps_hle_ctxt->profile_hle); |
| /* store default values of mem tab */ |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.i4_mem_alignment = 4; |
| |
| i4_num_resolutions = ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.i4_num_res_layers; |
| memset( |
| apv_entropy_thrd_hdls, |
| 0, |
| IHEVCE_MAX_NUM_RESOLUTIONS * NUM_ENTROPY_THREADS * sizeof(void *)); |
| memset( |
| apv_entropy_thrd_hdls, |
| 0, |
| IHEVCE_MAX_NUM_RESOLUTIONS * NUM_ENTROPY_THREADS * sizeof(void *)); |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| i4_num_bit_rate_instances[res_ctr] = |
| ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr] |
| .i4_num_bitrate_instances; |
| } |
| /* --------------------------------------------------------------------- */ |
| /* Init number of threads for each stage */ |
| /* --------------------------------------------------------------------- */ |
| |
| { |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| /* all the threads created will be made active */ |
| ps_enc_ctxt->s_multi_thrd.i4_num_active_enc_thrds = |
| ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; |
| |
| ps_enc_ctxt->s_multi_thrd.i4_num_active_pre_enc_thrds = |
| ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Multiple processing Threads Semaphores init */ |
| /* --------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| osal_sem_attr_t attr = OSAL_DEFAULT_SEM_ATTR; |
| |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| attr.value = SEM_START_VALUE; |
| |
| /* Create Semaphore handle for LAP thread */ |
| if(0 == ps_enc_ctxt->i4_resolution_id) |
| { |
| pv_lap_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_lap_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| } |
| else |
| { |
| /*NOTE: Tile workspace assigned this to null. Confirm this*/ |
| pv_lap_sem_hdl = ps_enc_ctxt_base->s_thrd_sem_ctxt.pv_lap_sem_handle; |
| } |
| /* Create Semaphore for encode frame process thread */ |
| pv_enc_frame_process_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_enc_frame_process_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for pre_encode frame process thread */ |
| pv_pre_enc_frame_process_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_pre_enc_frame_process_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for input frame data q function */ |
| if(0 == ps_enc_ctxt->i4_resolution_id) |
| { |
| pv_inp_data_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_inp_data_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| } |
| else |
| { |
| pv_inp_data_sem_hdl = ps_enc_ctxt_base->s_thrd_sem_ctxt.pv_inp_data_sem_handle; |
| } |
| |
| /*creating new input queue owned by encoder*/ |
| /* Create Semaphore for input frame data q function */ |
| pv_lap_inp_data_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_lap_inp_data_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for input frame data q function */ |
| pv_preenc_inp_data_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_preenc_inp_data_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for input conrol data q function */ |
| if(0 == ps_enc_ctxt->i4_resolution_id) |
| { |
| pv_inp_ctrl_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_inp_ctrl_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| } |
| else |
| { /*Inp ctrl queue is same for all resolutions between app and lap*/ |
| pv_inp_ctrl_sem_hdl = ps_enc_ctxt_base->s_thrd_sem_ctxt.pv_inp_ctrl_sem_handle; |
| } |
| |
| /* Create Semaphore for output control status data q function */ |
| pv_out_ctrl_sts_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_out_ctrl_sts_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Multi res single output case singel output queue is used for all output resolutions */ |
| if(1 == ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.i4_mres_single_out) |
| { |
| ps_enc_ctxt->s_enc_ques.apv_q_hdl[IHEVCE_OUTPUT_DATA_Q] = |
| ps_enc_ctxt_base->s_enc_ques.apv_q_hdl[IHEVCE_OUTPUT_DATA_Q]; |
| if(0 == ps_enc_ctxt->i4_resolution_id) |
| { |
| /* Create Semaphore for enropy coding thread */ |
| pv_ent_common_mres_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_ent_common_mres_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for output stream data q function */ |
| pv_out_common_mres_sem_hdl = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == pv_out_common_mres_sem_hdl) |
| { |
| return IV_FAIL; |
| } |
| } |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_ent_common_mres_sem_hdl = pv_ent_common_mres_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_common_mres_sem_hdl = pv_out_common_mres_sem_hdl; |
| } |
| |
| /*create entropy and output semaphores for each thread. |
| Each thread will correspond to each bit-rate instance running */ |
| for(i = 0; i < i4_num_bit_rate_instances[res_ctr]; i++) |
| { |
| /* Create Semaphore for enropy coding thread */ |
| apv_ent_coding_sem_hdl[i] = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == apv_ent_coding_sem_hdl[i]) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for output stream data q function */ |
| apv_out_stream_sem_hdl[i] = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == apv_out_stream_sem_hdl[i]) |
| { |
| return IV_FAIL; |
| } |
| |
| /* Create Semaphore for output recon data q function */ |
| apv_out_recon_sem_hdl[i] = osal_sem_create(ps_hle_ctxt->pv_osal_handle, &attr); |
| if(NULL == apv_out_recon_sem_hdl[i]) |
| { |
| return IV_FAIL; |
| } |
| } |
| |
| /* update the semaphore handles and the thread creates status */ |
| |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_enc_frm_proc_sem_handle = pv_enc_frame_process_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_pre_enc_frm_proc_sem_handle = |
| pv_pre_enc_frame_process_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_sem_handle = pv_lap_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_data_sem_handle = pv_inp_data_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_inp_data_sem_hdl = pv_lap_inp_data_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_preenc_inp_data_sem_hdl = pv_preenc_inp_data_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_ctrl_sem_handle = pv_inp_ctrl_sem_hdl; |
| ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_ctrl_sem_handle = pv_out_ctrl_sts_sem_hdl; |
| for(i = 0; i < i4_num_bit_rate_instances[res_ctr]; i++) |
| { |
| ps_enc_ctxt->s_thrd_sem_ctxt.apv_ent_cod_sem_handle[i] = apv_ent_coding_sem_hdl[i]; |
| ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_strm_sem_handle[i] = apv_out_stream_sem_hdl[i]; |
| ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_recon_sem_handle[i] = apv_out_recon_sem_hdl[i]; |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Multiple processing Threads Mutex init */ |
| /* --------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| /* create a mutex lock for Job Queue access accross slave threads of encode frame processing */ |
| ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_me = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_me) |
| { |
| return IV_FAIL; |
| } |
| |
| /* create a mutex lock for Job Queue access accross slave threads of encode frame processing */ |
| ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_enc_loop = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_enc_loop) |
| { |
| return IV_FAIL; |
| } |
| |
| /* create mutex for enc thread group */ |
| for(i = 0; i < MAX_NUM_ME_PARALLEL; i++) |
| { |
| ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i] = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i]) |
| { |
| return IV_FAIL; |
| } |
| |
| ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i] = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i]) |
| { |
| return IV_FAIL; |
| } |
| } |
| |
| for(i = 0; i < MAX_NUM_ENC_LOOP_PARALLEL; i++) |
| { |
| ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i] = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i]) |
| { |
| return IV_FAIL; |
| } |
| |
| ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i] = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| if(NULL == ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i]) |
| { |
| return IV_FAIL; |
| } |
| } |
| |
| /*initialize mutex for pre-enc group */ |
| ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_init = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_decomp_deinit = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_init = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_deinit = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_l0_ipe_init = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_decomp = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_hme = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_l0ipe = |
| osal_mutex_create(ps_hle_ctxt->pv_osal_handle); |
| |
| if(NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_init || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_decomp_deinit || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_init || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_deinit || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_l0_ipe_init || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_decomp || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_hme || |
| NULL == ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_l0ipe) |
| { |
| return IV_FAIL; |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Multiple processing Threads Context init */ |
| /* --------------------------------------------------------------------- */ |
| |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| ps_enc_ctxt_base = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[0]; |
| |
| /*initialize multi-thread context for enc group*/ |
| ps_enc_ctxt->s_multi_thrd.i4_is_recon_free_done = 0; |
| ps_enc_ctxt->s_multi_thrd.me_end_flag = 0; |
| ps_enc_ctxt->s_multi_thrd.enc_end_flag = 0; |
| ps_enc_ctxt->s_multi_thrd.i4_idx_dvsr_p = 0; |
| ps_enc_ctxt->s_multi_thrd.i4_last_inp_buf = 0; |
| |
| { |
| /* For all the ME frames in Parallel */ |
| WORD32 i4_frm_idx; |
| |
| for(i4_frm_idx = 0; i4_frm_idx < MAX_NUM_ME_PARALLEL; i4_frm_idx++) |
| { |
| ps_enc_ctxt->s_multi_thrd.me_num_thrds_exited[i4_frm_idx] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_me_master_done_flag[i4_frm_idx] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_me_enc_buff_prod_flag[i4_frm_idx] = 0; |
| } |
| } |
| |
| { |
| WORD32 i4_frm_idx; |
| ps_enc_ctxt->s_multi_thrd.num_thrds_done = 0; |
| ps_enc_ctxt->s_multi_thrd.num_thrds_exited_for_reenc = 0; |
| for(i4_frm_idx = 0; i4_frm_idx < MAX_NUM_ENC_LOOP_PARALLEL; i4_frm_idx++) |
| { |
| ps_enc_ctxt->s_multi_thrd.num_thrds_exited[i4_frm_idx] = 0; |
| |
| ps_enc_ctxt->s_multi_thrd.enc_master_done_frame_init[i4_frm_idx] = 0; |
| |
| for(i = 0; i < i4_num_bit_rate_instances[res_ctr]; i++) |
| { |
| /*reset the entropy buffer produced status */ |
| ps_enc_ctxt->s_multi_thrd.ai4_produce_outbuf[i4_frm_idx][i] = 1; |
| ps_enc_ctxt->s_multi_thrd.ps_frm_recon[i4_frm_idx][i] = NULL; |
| |
| ps_enc_ctxt->s_multi_thrd.ps_curr_out_enc_grp[i4_frm_idx][i] = NULL; |
| } |
| } |
| } |
| ps_enc_ctxt->s_multi_thrd.i4_seq_mode_enabled_flag = 0; |
| |
| /* Set prev_frame_done = 1 to indicate that all the threads are in same frame*/ |
| for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel; i++) |
| { |
| ihevce_dmgr_set_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i]); |
| } |
| /* Set prev_frame_done = 1 to indicate that all the threads are in same frame*/ |
| ihevce_dmgr_set_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_enc_done_for_reenc); |
| /*to enable the dependency manager to wait when first reached*/ |
| ihevce_dmgr_set_prev_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_enc_done_for_reenc); |
| for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel; i++) |
| { |
| ihevce_dmgr_set_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i]); |
| } |
| |
| /* reset the completed status & start proc flags of slave encode frame processing threads */ |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++) |
| { |
| ps_enc_ctxt->s_multi_thrd.ai4_enc_frm_proc_start[ctr] = 0; |
| } |
| |
| /* initialize multi-thread context for pre enc group */ |
| |
| ps_enc_ctxt->s_multi_thrd.i4_ctrl_blocking_mode = BUFF_QUE_BLOCKING_MODE; |
| |
| //for (ctr=0; ctr< PING_PONG_BUF; ctr++) |
| for(ctr = 0; ctr < MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME; ctr++) |
| { |
| ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_init_done[ctr] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_hme_init_done[ctr] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_pre_enc_deinit_done[ctr] = 1; |
| ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_decomp[ctr] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_coarse_me[ctr] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_pre_enc[ctr] = 0; |
| |
| ps_enc_ctxt->s_multi_thrd.ai4_num_thrds_processed_L0_ipe_qp_init[ctr] = 0; |
| ps_enc_ctxt->s_multi_thrd.ai4_decomp_coarse_me_complete_flag[ctr] = 1; |
| ps_enc_ctxt->s_multi_thrd.ai4_end_flag_pre_enc[ctr] = 0; |
| } |
| |
| /* Set prev_frame_done = 1 to indicate that all the threads are in same frame*/ |
| ihevce_dmgr_set_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l1); |
| |
| ihevce_dmgr_set_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_coarse_me); |
| |
| ihevce_dmgr_set_done_frm_frm_sync( |
| ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l0); |
| |
| { |
| /**init idx for handling delay between pre-me and l0-ipe*/ |
| ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe = 0; |
| ps_enc_ctxt->s_multi_thrd.i4_max_delay_pre_me_btw_l0_ipe = |
| MAX_PRE_ENC_STAGGER + NUM_BUFS_DECOMP_HME - 1; |
| if(ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics) |
| { |
| ps_enc_ctxt->s_multi_thrd.i4_delay_pre_me_btw_l0_ipe += |
| MIN_L1_L0_STAGGER_NON_SEQ + |
| ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics; |
| } |
| ps_enc_ctxt->s_multi_thrd.i4_qp_update_l0_ipe = -1; |
| } |
| } |
| |
| /** Get Number of Processor Groups **/ |
| i4_proc_grp_count = ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups; |
| /*** Enc threads are allocated based on the assumption that there can be only 2 processor groups **/ |
| ASSERT(i4_proc_grp_count <= MAX_NUMBER_PROC_GRPS); |
| /** Get Number of logical processors in Each Group **/ |
| for(ctr = 0; ctr < i4_proc_grp_count; ctr++) |
| { |
| ai4_proc_count[ctr] = |
| ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.ai4_num_cores_per_grp[ctr]; |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Create a LAP thread */ |
| /* --------------------------------------------------------------------- */ |
| /* LAP thread will run on 0th resolution instance context */ |
| { |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.i4_mem_size = sizeof(lap_intface_t); |
| |
| /* initialise the interface strucure parameters */ |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| |
| ps_lap_interface_ctxt = (lap_intface_t *)s_memtab.pv_base; |
| |
| /* populate the params */ |
| ps_lap_interface_ctxt->pv_hle_ctxt = ps_hle_ctxt; |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[0]; |
| ps_lap_interface_ctxt->pv_lap_module_ctxt = ps_enc_ctxt->s_module_ctxt.pv_lap_ctxt; |
| ps_lap_interface_ctxt->i4_ctrl_in_que_id = IHEVCE_INPUT_ASYNCH_CTRL_Q; |
| ps_lap_interface_ctxt->i4_ctrl_out_que_id = IHEVCE_OUTPUT_STATUS_Q; |
| ps_lap_interface_ctxt->i4_ctrl_cmd_buf_size = ENC_COMMAND_BUFF_SIZE; |
| ps_lap_interface_ctxt->i4_ctrl_in_que_blocking_mode = BUFF_QUE_BLOCKING_MODE; |
| ps_lap_interface_ctxt->ps_sys_api = &ps_enc_ctxt_base->ps_stat_prms->s_sys_api; |
| ps_enc_ctxt_base->pv_lap_interface_ctxt = (void *)ps_lap_interface_ctxt; |
| ps_lap_interface_ctxt->ihevce_dyn_bitrate_cb = ihevce_dyn_bitrate; |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Create Entropy Coding threads */ |
| /* --------------------------------------------------------------------- */ |
| /*Create entropy thread for each encoder instance*/ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR; |
| WORD32 i4_num_entropy_threads; |
| |
| /* derive encoder ctxt from hle handle */ |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| i4_num_entropy_threads = |
| ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr] |
| .i4_num_bitrate_instances; |
| |
| /* initialise the interface strucure parameters */ |
| for(ctr = 0; ctr < i4_num_entropy_threads; ctr++) |
| { |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t); |
| |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| |
| aps_entropy_thrd_ctxt[res_ctr][ctr] = (frm_proc_thrd_ctxt_t *)s_memtab.pv_base; |
| |
| /* initialise the interface strucure parameters */ |
| aps_entropy_thrd_ctxt[res_ctr][ctr]->i4_thrd_id = ctr; |
| aps_entropy_thrd_ctxt[res_ctr][ctr]->ps_hle_ctxt = ps_hle_ctxt; |
| aps_entropy_thrd_ctxt[res_ctr][ctr]->pv_enc_ctxt = (void *)ps_enc_ctxt; |
| |
| /* Initialize application thread attributes */ |
| s_thread_attr.exit_code = 0; |
| s_thread_attr.name = 0; |
| s_thread_attr.priority_map_flag = 1; |
| s_thread_attr.priority = OSAL_PRIORITY_DEFAULT; |
| s_thread_attr.stack_addr = 0; |
| s_thread_attr.stack_size = THREAD_STACK_SIZE; |
| s_thread_attr.thread_func = ihevce_ent_coding_thrd; |
| s_thread_attr.thread_param = |
| (void *)(aps_entropy_thrd_ctxt[res_ctr] |
| [ctr]); //encioder and hle context are derived from this |
| s_thread_attr.core_affinity_mask = 0; |
| if(ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1) |
| { |
| /* Run ENTROPY thread on last group if there are more than one processor group */ |
| s_thread_attr.group_num = |
| ps_hle_ctxt->ps_static_cfg_prms->s_multi_thrd_prms.i4_num_proc_groups - 1; |
| } |
| else |
| { |
| s_thread_attr.group_num = 0; |
| } |
| |
| /* Create entropy coding thread */ |
| apv_entropy_thrd_hdls[res_ctr][ctr] = |
| osal_thread_create(ps_hle_ctxt->pv_osal_handle, &s_thread_attr); |
| if(NULL == apv_entropy_thrd_hdls[res_ctr][ctr]) |
| { |
| return IV_FAIL; |
| } |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Create all Slave Encode Frame processing threads */ |
| /* - -------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| WORD32 enc_ctr = 0; |
| WORD32 i4_loop_count; |
| WORD32 i4_curr_grp_num = 0; |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| i4_acc_proc_num = 0; |
| /* Calculate the start core number of enc threads for current resolution */ |
| for(i4_loop_count = 0; i4_loop_count < res_ctr; i4_loop_count++) |
| { |
| /* Add number of cores taken by each resolution till the curr resolution */ |
| enc_ctr += ps_hle_ctxt->ai4_num_core_per_res[i4_loop_count]; |
| } |
| if(ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1) |
| { |
| /* Select the group number for each res based on processors present in each group */ |
| for(i4_loop_count = 0; |
| i4_loop_count < |
| ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups; |
| i4_loop_count++) |
| { |
| i4_acc_proc_num += ai4_proc_count[i4_loop_count]; |
| if(enc_ctr >= i4_acc_proc_num) |
| { |
| /* if enc_ctr is greater than proc count for first group, |
| then increment group count.This group number will be starting grp num for |
| that resolution */ |
| i4_curr_grp_num++; |
| } |
| else |
| break; |
| } |
| } |
| |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++) |
| { |
| osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR; |
| |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t); |
| |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| |
| aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr] = (frm_proc_thrd_ctxt_t *)s_memtab.pv_base; |
| |
| /* initialise the interface strucure parameters */ |
| aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->i4_thrd_id = ctr; |
| |
| aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->ps_hle_ctxt = ps_hle_ctxt; |
| |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->pv_enc_ctxt = (void *)ps_enc_ctxt; |
| |
| /* Initialize application thread attributes */ |
| s_thread_attr.exit_code = 0; |
| s_thread_attr.name = 0; |
| s_thread_attr.priority_map_flag = 1; |
| s_thread_attr.priority = OSAL_PRIORITY_DEFAULT; |
| s_thread_attr.stack_addr = 0; |
| s_thread_attr.stack_size = THREAD_STACK_SIZE; |
| s_thread_attr.thread_func = ihevce_enc_frm_proc_slave_thrd; |
| s_thread_attr.thread_param = (void *)(aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]); |
| s_thread_attr.group_num = i4_curr_grp_num; |
| if(1 == ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_use_thrd_affinity) |
| { |
| ihevce_static_multi_thread_params_t *ps_multi_thrd_prms = |
| &ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms; |
| |
| s_thread_attr.core_affinity_mask = ps_multi_thrd_prms->au8_core_aff_mask[enc_ctr]; |
| if((enc_ctr >= i4_acc_proc_num) && |
| (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)) |
| { |
| /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/ |
| s_thread_attr.group_num++; |
| i4_curr_grp_num++; |
| /* This takes care of the condition that differnt proc groups can have diff number of cores */ |
| i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num]; |
| } |
| } |
| else |
| { |
| s_thread_attr.core_affinity_mask = 0; |
| if((enc_ctr >= i4_acc_proc_num) && |
| (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)) |
| { |
| /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/ |
| s_thread_attr.group_num++; |
| i4_curr_grp_num++; |
| /* This takes care of the condition that differnt proc groups can have diff number of cores */ |
| i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num]; |
| } |
| } |
| |
| /* Create frame processing thread */ |
| apv_enc_frm_proc_hdls[res_ctr][ctr] = |
| osal_thread_create(ps_hle_ctxt->pv_osal_handle, &s_thread_attr); |
| if(NULL == apv_enc_frm_proc_hdls[res_ctr][ctr]) |
| { |
| return IV_FAIL; |
| } |
| enc_ctr++; |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Create all Pre - Encode Frame processing threads */ |
| /* --------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| WORD32 pre_enc_ctr = 0; |
| WORD32 i4_loop_count; |
| WORD32 i4_curr_grp_num = 0; |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| i4_acc_proc_num = 0; |
| |
| for(i4_loop_count = 0; i4_loop_count < res_ctr; i4_loop_count++) |
| pre_enc_ctr += ps_hle_ctxt->ai4_num_core_per_res[i4_loop_count]; |
| if(ps_enc_ctxt->s_multi_thrd.i4_all_thrds_active_flag) |
| { |
| /* If its sequential mode of operation enc and pre-enc threads to be given same core affinity mask */ |
| pre_enc_ctr -= ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; |
| } |
| |
| if(ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1) |
| { |
| /* Select the group number for each res based on processors present in each group */ |
| for(i4_loop_count = 0; |
| i4_loop_count < |
| ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups; |
| i4_loop_count++) |
| { |
| i4_acc_proc_num += ai4_proc_count[i4_loop_count]; |
| if((pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) >= |
| i4_acc_proc_num) |
| { |
| /* if pre_enc_ctr is greater than proc count for first group, |
| then increment group count.This group number will be starting grp num for |
| that resolution */ |
| i4_curr_grp_num++; |
| } |
| else |
| break; |
| } |
| } |
| |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; ctr++) |
| { |
| osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR; |
| |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t); |
| |
| ps_hle_ctxt->ihevce_mem_alloc( |
| ps_hle_ctxt->pv_mem_mgr_hdl, &ps_enc_ctxt_base->ps_stat_prms->s_sys_api, &s_memtab); |
| if(s_memtab.pv_base == NULL) |
| { |
| return (IV_FAIL); |
| } |
| |
| aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr] = (frm_proc_thrd_ctxt_t *)s_memtab.pv_base; |
| |
| /* initialise the interface strucure parameters */ |
| aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->i4_thrd_id = ctr; |
| |
| aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->ps_hle_ctxt = ps_hle_ctxt; |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]->pv_enc_ctxt = (void *)ps_enc_ctxt; |
| |
| /* Initialize application thread attributes */ |
| s_thread_attr.exit_code = 0; |
| s_thread_attr.name = 0; |
| s_thread_attr.priority_map_flag = 1; |
| s_thread_attr.priority = OSAL_PRIORITY_DEFAULT; |
| s_thread_attr.stack_addr = 0; |
| s_thread_attr.stack_size = THREAD_STACK_SIZE; |
| s_thread_attr.thread_func = ihevce_pre_enc_process_frame_thrd; |
| s_thread_attr.thread_param = (void *)(aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]); |
| s_thread_attr.group_num = i4_curr_grp_num; |
| |
| if(1 == ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_use_thrd_affinity) |
| { |
| ihevce_static_multi_thread_params_t *ps_multi_thrd_prms = |
| &ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms; |
| |
| s_thread_attr.core_affinity_mask = |
| ps_multi_thrd_prms->au8_core_aff_mask |
| [pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds]; |
| if(((pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) >= |
| i4_acc_proc_num) && |
| (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)) |
| { |
| /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/ |
| s_thread_attr.group_num++; |
| i4_curr_grp_num++; |
| /* This takes care of the condition that differnt proc groups can have diff number of cores */ |
| i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num]; |
| } |
| } |
| else |
| { |
| s_thread_attr.core_affinity_mask = 0; |
| |
| if(((pre_enc_ctr + ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds) >= |
| i4_acc_proc_num) && |
| (ps_enc_ctxt_base->ps_stat_prms->s_multi_thrd_prms.i4_num_proc_groups > 1)) |
| { |
| /*** When the cores in the Group0 is exhausted start enc threads in the next Processor Group ***/ |
| s_thread_attr.group_num++; |
| i4_curr_grp_num++; |
| /* This takes care of the condition that differnt proc groups can have diff number of cores */ |
| i4_acc_proc_num += ai4_proc_count[i4_curr_grp_num]; |
| } |
| } |
| |
| /* Create frame processing thread */ |
| apv_pre_enc_frm_proc_hdls[res_ctr][ctr] = |
| osal_thread_create(ps_hle_ctxt->pv_osal_handle, &s_thread_attr); |
| if(NULL == apv_pre_enc_frm_proc_hdls[res_ctr][ctr]) |
| { |
| return IV_FAIL; |
| } |
| pre_enc_ctr++; |
| } |
| } |
| |
| /* Set the threads init done Flag */ |
| ps_hle_ctxt->i4_hle_init_done = 1; |
| |
| /* --------------------------------------------------------------------- */ |
| /* Wait and destroy Processing threads */ |
| /* --------------------------------------------------------------------- */ |
| |
| /* --------------------------------------------------------------------- */ |
| /* Frame process Pre - Encode threads destroy */ |
| /* --------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; ctr++) |
| { |
| /* Wait for thread to complete */ |
| osal_thread_wait(apv_pre_enc_frm_proc_hdls[res_ctr][ctr]); |
| |
| /* Destroy thread */ |
| osal_thread_destroy(apv_pre_enc_frm_proc_hdls[res_ctr][ctr]); |
| |
| s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = (void *)aps_pre_enc_frm_proc_thrd_ctxt[res_ctr][ctr]; |
| |
| /* free the ctxt memory */ |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Frame process Encode slave threads destroy */ |
| /* --------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++) |
| { |
| /* Wait for thread to complete */ |
| osal_thread_wait(apv_enc_frm_proc_hdls[res_ctr][ctr]); |
| |
| /* Destroy thread */ |
| osal_thread_destroy(apv_enc_frm_proc_hdls[res_ctr][ctr]); |
| |
| s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = (void *)aps_enc_frm_proc_thrd_ctxt[res_ctr][ctr]; |
| |
| /* free the ctxt memory */ |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| } |
| } |
| |
| /* --------------------------------------------------------------------- */ |
| /* Entropy threads destroy */ |
| /* --------------------------------------------------------------------- */ |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| WORD32 i4_num_bitrates = |
| ps_enc_ctxt_base->ps_stat_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr] |
| .i4_num_bitrate_instances; |
| |
| for(ctr = 0; ctr < i4_num_bitrates; ctr++) |
| { |
| /* Wait for Entropy Coding thread to complete */ |
| osal_thread_wait(apv_entropy_thrd_hdls[res_ctr][ctr]); |
| |
| /* Destroy Entropy Coding thread */ |
| osal_thread_destroy(apv_entropy_thrd_hdls[res_ctr][ctr]); |
| |
| //semaphore will come here |
| |
| s_memtab.i4_mem_size = sizeof(frm_proc_thrd_ctxt_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = (void *)aps_entropy_thrd_ctxt[res_ctr][ctr]; |
| |
| /* free the ctxt memory */ |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| } |
| } |
| |
| s_memtab.i4_mem_size = sizeof(lap_intface_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = (void *)ps_lap_interface_ctxt; |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| /* profile stop */ |
| PROFILE_STOP(&ps_hle_ctxt->profile_hle, NULL); |
| return (0); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_get_free_inp_data_buff \endif |
| * |
| * \brief |
| * Gets a free buffer from the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] pointer to return the buffer id |
| * \param[in] blocking mode / non blocking mode |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void *ihevce_q_get_free_inp_data_buff( |
| ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 *pi4_buff_id, WORD32 i4_blocking_mode) |
| { |
| void *pv_ptr; |
| enc_ctxt_t *ps_enc_ctxt; |
| WORD32 i4_resolution_id = 0; |
| |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[i4_resolution_id]; |
| if(ps_enc_ctxt->i4_frame_limit_reached == 1) |
| { |
| return (NULL); |
| } |
| /*Input buffer is same for all enc handles*/ |
| pv_ptr = ihevce_q_get_free_buff( |
| ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_DATA_CTRL_Q, pi4_buff_id, i4_blocking_mode); |
| |
| return (pv_ptr); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_get_free_inp_ctrl_buff \endif |
| * |
| * \brief |
| * Gets a free buffer from the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] pointer to return the buffer id |
| * \param[in] blocking mode / non blocking mode |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void *ihevce_q_get_free_inp_ctrl_buff( |
| ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 *pi4_buff_id, WORD32 i4_blocking_mode) |
| { |
| void *pv_ptr; |
| |
| /*Input buffer is same for all enc handles*/ |
| pv_ptr = ihevce_q_get_free_buff( |
| ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_ASYNCH_CTRL_Q, pi4_buff_id, i4_blocking_mode); |
| |
| return (pv_ptr); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_get_free_out_strm_buff \endif |
| * |
| * \brief |
| * Gets a free buffer from the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] pointer to return the buffer id |
| * \param[in] blocking mode / non blocking mode |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void *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) |
| { |
| void *pv_ptr; |
| |
| pv_ptr = ihevce_q_get_free_buff( |
| ps_hle_ctxt->apv_enc_hdl[i4_res_instance], |
| (IHEVCE_OUTPUT_DATA_Q + i4_bitrate_instance), |
| pi4_buff_id, |
| i4_blocking_mode); |
| return (pv_ptr); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_get_free_out_recon_buff \endif |
| * |
| * \brief |
| * Gets a free buffer from the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] pointer to return the buffer id |
| * \param[in] blocking mode / non blocking mode |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void *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) |
| { |
| void *pv_ptr; |
| |
| pv_ptr = ihevce_q_get_free_buff( |
| ps_hle_ctxt->apv_enc_hdl[i4_res_instance], |
| (IHEVCE_RECON_DATA_Q + i4_bitrate_instance), |
| pi4_buff_id, |
| i4_blocking_mode); |
| return (pv_ptr); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_set_inp_data_buff_prod \endif |
| * |
| * \brief |
| * Sets the input data buffer as produced in the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] buffer id which needs to be set as produced |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T |
| ihevce_q_set_inp_data_buff_prod(ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 i4_buff_id) |
| { |
| IV_API_CALL_STATUS_T ret_status; |
| |
| ret_status = |
| ihevce_q_set_buff_prod(ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_DATA_CTRL_Q, i4_buff_id); |
| |
| return (ret_status); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_set_inp_ctrl_buff_prod \endif |
| * |
| * \brief |
| * Sets the input data buffer as produced in the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] buffer id which needs to be set as produced |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T |
| ihevce_q_set_inp_ctrl_buff_prod(ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 i4_buff_id) |
| |
| { |
| IV_API_CALL_STATUS_T ret_status; |
| |
| ret_status = |
| ihevce_q_set_buff_prod(ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_INPUT_ASYNCH_CTRL_Q, i4_buff_id); |
| |
| return (ret_status); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_set_out_strm_buff_prod \endif |
| * |
| * \brief |
| * Sets the Output stream buffer as produced in the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] buffer id which needs to be set as produced |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T 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) |
| { |
| IV_API_CALL_STATUS_T ret_status; |
| |
| ret_status = ihevce_q_set_buff_prod( |
| ps_hle_ctxt->apv_enc_hdl[i4_resolution_id], |
| (IHEVCE_OUTPUT_DATA_Q + i4_bitrate_instance_id), |
| i4_buff_id); |
| |
| return (ret_status); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_set_out_recon_buff_prod \endif |
| * |
| * \brief |
| * Sets the Output recon buffer as produced in the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] buffer id which needs to be set as produced |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T 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) |
| { |
| IV_API_CALL_STATUS_T ret_status; |
| |
| ret_status = ihevce_q_set_buff_prod( |
| ps_hle_ctxt->apv_enc_hdl[i4_resolution_id], |
| (IHEVCE_RECON_DATA_Q + i4_bitrate_instance_id), |
| i4_buff_id); |
| |
| return (ret_status); |
| } |
| |
| //recon_dump |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_get_filled_recon_buff \endif |
| * |
| * \brief |
| * Gets a next filled recon buffer from the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] pointer to return the buffer id |
| * \param[in] blocking mode / non blocking mode |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void *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) |
| { |
| void *pv_ptr; |
| |
| pv_ptr = ihevce_q_get_filled_buff( |
| ps_hle_ctxt->apv_enc_hdl[i4_resolution_id], |
| IHEVCE_RECON_DATA_Q + i4_bitrate_instance_id, |
| pi4_buff_id, |
| i4_blocking_mode); |
| |
| return (pv_ptr); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_get_filled_ctrl_sts_buff \endif |
| * |
| * \brief |
| * Gets a next filled control status buffer from the que requested |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] pointer to return the buffer id |
| * \param[in] blocking mode / non blocking mode |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| void *ihevce_q_get_filled_ctrl_sts_buff( |
| ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 *pi4_buff_id, WORD32 i4_blocking_mode) |
| { |
| void *pv_ptr; |
| pv_ptr = ihevce_q_get_filled_buff( |
| ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_OUTPUT_STATUS_Q, pi4_buff_id, i4_blocking_mode); |
| |
| return (pv_ptr); |
| } |
| |
| //recon_dump |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_rel_recon_buf \endif |
| * |
| * \brief |
| * Frees the recon buffer in the recon buffer que |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] buffer id which needs to be freed |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T 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) |
| { |
| IV_API_CALL_STATUS_T ret_status; |
| |
| ret_status = ihevce_q_rel_buf( |
| ps_hle_ctxt->apv_enc_hdl[i4_resolution_id], |
| IHEVCE_RECON_DATA_Q + i4_bitrate_instance_id, |
| i4_buff_id); |
| |
| return (ret_status); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_q_rel_ctrl_sts_buf \endif |
| * |
| * \brief |
| * Frees the output control sttus buffer in buffer que |
| * |
| * \param[in] high level encoder context pointer |
| * \param[in] buffer id which needs to be freed |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T ihevce_q_rel_ctrl_sts_buf(ihevce_hle_ctxt_t *ps_hle_ctxt, WORD32 i4_buff_id) |
| { |
| IV_API_CALL_STATUS_T ret_status; |
| |
| ret_status = ihevce_q_rel_buf(ps_hle_ctxt->apv_enc_hdl[0], IHEVCE_OUTPUT_STATUS_Q, i4_buff_id); |
| |
| return (ret_status); |
| } |
| |
| /*! |
| ****************************************************************************** |
| * \if Function name : ihevce_hle_interface_delete \endif |
| * |
| * \brief |
| * High leve encoder delete interface |
| * |
| * \param[in] high level encoder interface context pointer |
| * |
| * \return |
| * None |
| * |
| * \author |
| * Ittiam |
| * |
| ***************************************************************************** |
| */ |
| IV_API_CALL_STATUS_T ihevce_hle_interface_delete(ihevce_hle_ctxt_t *ps_hle_ctxt) |
| { |
| /* local varaibles */ |
| enc_ctxt_t *ps_enc_ctxt; |
| iv_mem_rec_t s_memtab; |
| WORD32 ctr = 0, i, res_ctr, i4_num_resolutions; |
| WORD32 ai4_num_bitrate_instances[IHEVCE_MAX_NUM_RESOLUTIONS] = { 1 }; |
| |
| i4_num_resolutions = ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers; |
| for(ctr = 0; ctr < i4_num_resolutions; ctr++) |
| { |
| ai4_num_bitrate_instances[ctr] = |
| ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[ctr] |
| .i4_num_bitrate_instances; |
| } |
| |
| for(res_ctr = 0; res_ctr < i4_num_resolutions && ps_hle_ctxt->apv_enc_hdl[res_ctr]; res_ctr++) |
| { |
| ps_enc_ctxt = (enc_ctxt_t *)ps_hle_ctxt->apv_enc_hdl[res_ctr]; |
| |
| if(res_ctr == 0) |
| { |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_sem_handle); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_data_sem_handle); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_inp_ctrl_sem_handle); |
| if(1 == ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_mres_single_out) |
| { |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_ent_common_mres_sem_hdl); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_common_mres_sem_hdl); |
| } |
| } |
| |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_lap_inp_data_sem_hdl); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_preenc_inp_data_sem_hdl); |
| |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_enc_frm_proc_sem_handle); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_pre_enc_frm_proc_sem_handle); |
| |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.pv_out_ctrl_sem_handle); |
| |
| for(i = 0; i < ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[res_ctr] |
| .i4_num_bitrate_instances; |
| i++) |
| { |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.apv_ent_cod_sem_handle[i]); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_strm_sem_handle[i]); |
| osal_sem_destroy(ps_enc_ctxt->s_thrd_sem_ctxt.apv_out_recon_sem_handle[i]); |
| } |
| |
| /* destroy the mutex allocated for job queue usage encode group */ |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_me); |
| |
| /* destroy the mutex allocated for job queue usage encode group */ |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_enc_grp_enc_loop); |
| |
| /* destroy the mutexes allocated for enc thread group */ |
| for(i = 0; i < MAX_NUM_ME_PARALLEL; i++) |
| { |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle[i]); |
| |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_me_end[i]); |
| } |
| |
| for(i = 0; i < MAX_NUM_ENC_LOOP_PARALLEL; i++) |
| { |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_mutex_handle_frame_init[i]); |
| |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.apv_post_enc_mutex_handle[i]); |
| } |
| |
| /* destroy the mutex allocated for job queue, init and de-init |
| usage pre enocde group */ |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_decomp); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_hme); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_job_q_mutex_hdl_pre_enc_l0ipe); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_init); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_decomp_deinit); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_init); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_hme_deinit); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_l0_ipe_init); |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_mutex_hdl_pre_enc_deinit); |
| |
| /* destroy the EncLoop Module */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| ihevce_enc_loop_delete(ps_enc_ctxt->s_module_ctxt.pv_enc_loop_ctxt); |
| |
| /* destroy the Coarse ME Module */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| ihevce_coarse_me_delete( |
| ps_enc_ctxt->s_module_ctxt.pv_coarse_me_ctxt, |
| ps_hle_ctxt->ps_static_cfg_prms, |
| ps_enc_ctxt->i4_resolution_id); |
| /* destroy semaphores for all the threads in pre-enc and enc */ |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_enc_proc_thrds; ctr++) |
| { |
| osal_sem_destroy(ps_enc_ctxt->s_multi_thrd.apv_enc_thrd_sem_handle[ctr]); |
| } |
| |
| for(ctr = 0; ctr < ps_enc_ctxt->s_multi_thrd.i4_num_pre_enc_proc_thrds; ctr++) |
| { |
| osal_sem_destroy(ps_enc_ctxt->s_multi_thrd.apv_pre_enc_thrd_sem_handle[ctr]); |
| } |
| |
| /* destroy the ME-EncLoop Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| for(ctr = 0; ctr < NUM_ME_ENC_BUFS; ctr++) |
| { |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_encloop_dep_me[ctr]); |
| } |
| /* destroy the Prev. frame EncLoop Done Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_enc_loop_frm_pllel; i++) |
| { |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_done[i]); |
| } |
| /* destroy the Prev. frame EncLoop Done for re-encode Dep Mngr */ |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_enc_done_for_reenc); |
| |
| /* destroy the Prev. frame ME Done Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| for(i = 0; i < ps_enc_ctxt->s_multi_thrd.i4_num_me_frm_pllel; i++) |
| { |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.apv_dep_mngr_prev_frame_me_done[i]); |
| } |
| |
| /* destroy the Prev. frame PreEnc L1 Done Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l1); |
| |
| /* destroy the Prev. frame PreEnc HME Done Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_coarse_me); |
| |
| /* destroy the Prev. frame PreEnc L0 Done Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| ihevce_dmgr_del(ps_enc_ctxt->s_multi_thrd.pv_dep_mngr_prev_frame_pre_enc_l0); |
| |
| /* destroy the ME-Prev Recon Dep Mngr */ |
| /* Note : Only Destroys the resources allocated in the module like */ |
| /* semaphore,etc. Memory free is done separately using memtabs */ |
| for(ctr = 0; ctr < ps_enc_ctxt->ai4_num_buf_recon_q[0]; ctr++) |
| { |
| ihevce_dmgr_del(ps_enc_ctxt->pps_recon_buf_q[0][ctr]->pv_dep_mngr_recon); |
| } |
| |
| /* destroy all the mutex created */ |
| if(res_ctr == 0) |
| { |
| if(NULL != ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl) |
| { |
| osal_mutex_destroy(ps_enc_ctxt->s_enc_ques.pv_q_mutex_hdl); |
| } |
| } |
| |
| if(NULL != ps_enc_ctxt->pv_rc_mutex_lock_hdl) |
| { |
| osal_mutex_destroy(ps_enc_ctxt->pv_rc_mutex_lock_hdl); |
| } |
| |
| if(NULL != ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl) |
| { |
| osal_mutex_destroy(ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_mutex_lock_hdl); |
| } |
| |
| if(NULL != ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl) |
| { |
| osal_mutex_destroy( |
| ps_enc_ctxt->s_multi_thrd.pv_sub_pic_rc_for_qp_update_mutex_lock_hdl); |
| } |
| |
| /* call the memrory free function */ |
| ihevce_mem_manager_free(ps_enc_ctxt, ps_hle_ctxt); |
| if((1 == ps_hle_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_mres_single_out) && |
| (res_ctr == 0)) |
| { |
| s_memtab.i4_mem_size = sizeof(WORD32) * IHEVCE_MAX_NUM_RESOLUTIONS; |
| s_memtab.i4_mem_alignment = 4; |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = ps_enc_ctxt->s_multi_thrd.pi4_active_res_id; |
| /* free active_res_id memory */ |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| } |
| if(res_ctr == (i4_num_resolutions - 1)) |
| { |
| s_memtab.i4_mem_size = sizeof(ihevce_static_cfg_params_t); |
| s_memtab.i4_mem_alignment = 4; |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = ps_enc_ctxt->ps_stat_prms; |
| |
| /* free the encoder context pointer */ |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| } |
| s_memtab.i4_mem_size = sizeof(enc_ctxt_t); |
| s_memtab.i4_mem_alignment = 4; |
| s_memtab.i4_size = sizeof(iv_mem_rec_t); |
| s_memtab.e_mem_type = IV_EXT_CACHEABLE_NORMAL_MEM; |
| s_memtab.pv_base = ps_enc_ctxt; |
| |
| /* free the encoder context pointer */ |
| ps_hle_ctxt->ihevce_mem_free(ps_hle_ctxt->pv_mem_mgr_hdl, &s_memtab); |
| |
| /* reset the encoder handle to NULL */ |
| ps_hle_ctxt->apv_enc_hdl[res_ctr] = NULL; |
| } |
| /* profile end */ |
| PROFILE_END(&ps_hle_ctxt->profile_hle, "hle interface thread active time"); |
| for(res_ctr = 0; res_ctr < i4_num_resolutions; res_ctr++) |
| { |
| WORD32 i4_br_id; |
| |
| PROFILE_END(&ps_hle_ctxt->profile_pre_enc[res_ctr], "pre enc process"); |
| for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[res_ctr]; i4_br_id++) |
| { |
| PROFILE_END(&ps_hle_ctxt->profile_enc[res_ctr][i4_br_id], "enc process"); |
| PROFILE_END(&ps_hle_ctxt->profile_entropy[res_ctr][i4_br_id], "entropy process"); |
| } |
| } |
| |
| /* OSAL Delete */ |
| ihevce_osal_delete((void *)ps_hle_ctxt); |
| |
| return (IV_SUCCESS); |
| } |