2246 lines
85 KiB
C
2246 lines
85 KiB
C
/******************************************************************************
|
|
*
|
|
* 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(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_enc_me[ctr]);
|
|
PROFILE_INIT(&ps_hle_ctxt->profile_pre_enc_l1l2[ctr]);
|
|
PROFILE_INIT(&ps_hle_ctxt->profile_pre_enc_l0ipe[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.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]);
|
|
}
|
|
|
|
/* 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 < 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 =
|
|
MIN_L1_L0_STAGGER_NON_SEQ +
|
|
ps_enc_ctxt->s_lap_stat_prms.s_lap_params.i4_rc_look_ahead_pics + 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_l1l2[res_ctr], "pre enc l1l2 process");
|
|
PROFILE_END(&ps_hle_ctxt->profile_pre_enc_l0ipe[res_ctr], "pre enc l0 ipe process");
|
|
PROFILE_END(&ps_hle_ctxt->profile_enc_me[res_ctr], "enc me 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 loop 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);
|
|
}
|