/******************************************************************************
*
* 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_plugin.c
*
* \brief
* This file contains wrapper utilities to use hevc encoder library
*
* \date
* 15/04/2014
*
* \author
* Ittiam
*
* List of Functions
*
*
******************************************************************************
*/
/*****************************************************************************/
/* File Includes */
/*****************************************************************************/
/* System include files */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>
#include <stdarg.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 "ihevce_defs.h"
#include "ihevce_lap_enc_structs.h"
#include "ihevce_plugin.h"
#include "ihevce_plugin_priv.h"
#include "ihevce_hle_interface.h"
#include "ihevce_multi_thrd_structs.h"
#include "ihevce_me_common_defs.h"
#include "ihevce_error_codes.h"
#include "ihevce_error_checks.h"
#include "ihevce_function_selector.h"
#include "ihevce_enc_structs.h"
#include "ihevce_global_tables.h"
#include "cast_types.h"
#include "osal.h"
#include "osal_defaults.h"
/*****************************************************************************/
/* Constant Macros */
/*****************************************************************************/
#define CREATE_TIME_ALLOCATION_INPUT 1
#define CREATE_TIME_ALLOCATION_OUTPUT 0
#define MAX_NUM_FRM_IN_GOP 600
/*****************************************************************************/
/* Extern variables */
/*****************************************************************************/
/*****************************************************************************/
/* Function Definitions */
/*****************************************************************************/
/*!
******************************************************************************
* \if Function name : mem_mngr_alloc \endif
*
* \brief
* Memory manager specific alloc function
*
* \param[in] pv_handle : handle to memory manager
* (currently not required can be set to null)
* \param[in] ps_memtab : memory descriptor pointer
*
* \return
* Memory pointer
*
* \author
* Ittiam
*
*****************************************************************************
*/
void mem_mngr_alloc(void *pv_handle, ihevce_sys_api_t *ps_sys_api, iv_mem_rec_t *ps_memtab)
{
#ifndef X86_MINGW
WORD32 error, mem_alignment;
#endif
(void)pv_handle;
#ifdef X86_MINGW
ps_memtab->pv_base = _aligned_malloc(ps_memtab->i4_mem_size, ps_memtab->i4_mem_alignment);
#else
mem_alignment = ps_memtab->i4_mem_alignment;
mem_alignment = (mem_alignment >> 3) << 3;
if(mem_alignment == 0)
{
error = posix_memalign(&ps_memtab->pv_base, sizeof(void *), ps_memtab->i4_mem_size);
}
else
{
error = posix_memalign(&ps_memtab->pv_base, mem_alignment, ps_memtab->i4_mem_size);
}
if(error != 0)
{
ps_sys_api->ihevce_printf(ps_sys_api->pv_cb_handle, "posix_memalign error %d\n", error);
}
#endif
if(ps_memtab->pv_base == NULL)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Unable to allocate memory\n");
ASSERT(0);
}
return;
}
/*!
******************************************************************************
* \if Function name : memory_alloc \endif
*
* \brief
* common memory allocate function should be used across all threads
*
* \param[in] pv_handle : handle to memory manager
* (currently not required can be set to null)
* \param[in] u4_size : size of memory required
*
* \return
* Memory pointer
*
* \author
* Ittiam
*
*****************************************************************************
*/
void *memory_alloc(void *pv_handle, UWORD32 u4_size)
{
(void)pv_handle;
return (malloc(u4_size));
}
/*!
******************************************************************************
* \if Function name : mem_mngr_free \endif
*
* \brief
* Memory manager specific free function
*
* \param[in] pv_handle : handle to memory manager
* (currently not required can be set to null)
* \param[in] ps_memtab : memory descriptor pointer
*
* \return
* Memory pointer
*
* \author
* Ittiam
*
*****************************************************************************
*/
void mem_mngr_free(void *pv_handle, iv_mem_rec_t *ps_memtab)
{
(void)pv_handle;
#ifdef X86_MINGW
_aligned_free(ps_memtab->pv_base);
#else
free(ps_memtab->pv_base);
#endif
return;
}
/*!
******************************************************************************
* \if Function name : memory_free \endif
*
* \brief
* common memory free function should be used across all threads
*
* \param[in] pv_handle : handle to memory manager
* (currently not required can be set to null)
* \param[in] pv_mem : memory to be freed
*
* \return
* Memory pointer
*
* \author
* Ittiam
*
*****************************************************************************
*/
void memory_free(void *pv_handle, void *pv_mem)
{
(void)pv_handle;
free(pv_mem);
return;
}
/*!
******************************************************************************
* \if Function name : ihevce_set_def_params \endif
*
* \brief
* Set default values
*
* \param[in] Static params pointer
*
* \return
* status
*
* \author
* Ittiam
*
*****************************************************************************
*/
IHEVCE_PLUGIN_STATUS_T ihevce_set_def_params(ihevce_static_cfg_params_t *ps_params)
{
WORD32 i, j;
/* sanity checks */
if(NULL == ps_params)
return (IHEVCE_EFAIL);
memset(ps_params, 0, sizeof(*ps_params));
/* initialsie all the parameters to default values */
ps_params->i4_size = sizeof(ihevce_static_cfg_params_t);
ps_params->i4_save_recon = 0;
ps_params->i4_log_dump_level = 0;
ps_params->i4_enable_logo = 0;
ps_params->i4_enable_csv_dump = 0;
/* Control to free the entropy output buffers */
/* 1 for non_blocking mode */
/* and 0 for blocking mode */
ps_params->i4_outbuf_buf_free_control = 1;
/* coding tools parameters */
ps_params->s_coding_tools_prms.i4_size = sizeof(ihevce_coding_params_t);
ps_params->s_coding_tools_prms.i4_cropping_mode = 1;
ps_params->s_coding_tools_prms.i4_deblocking_type = 0;
ps_params->s_coding_tools_prms.i4_enable_entropy_sync = 0;
// New IDR/CDR Params
ps_params->s_coding_tools_prms.i4_max_closed_gop_period = 0;
ps_params->s_coding_tools_prms.i4_min_closed_gop_period = 0;
ps_params->s_coding_tools_prms.i4_max_cra_open_gop_period = 60;
ps_params->s_coding_tools_prms.i4_max_i_open_gop_period = 0;
ps_params->s_coding_tools_prms.i4_max_reference_frames = -1;
ps_params->s_coding_tools_prms.i4_max_temporal_layers = 0;
ps_params->s_coding_tools_prms.i4_slice_type = 0;
ps_params->s_coding_tools_prms.i4_use_default_sc_mtx = 0;
ps_params->s_coding_tools_prms.i4_weighted_pred_enable = 0;
ps_params->s_coding_tools_prms.i4_vqet = 0;
ps_params->e_arch_type = ARCH_NA;
/* config parameters */
ps_params->s_config_prms.i4_size = sizeof(ihevce_config_prms_t);
ps_params->s_config_prms.i4_cu_level_rc = 1;
ps_params->s_config_prms.i4_init_vbv_fullness = 0;
ps_params->s_config_prms.i4_max_frame_qp = 51;
ps_params->s_config_prms.i4_max_log2_cu_size = 6;
ps_params->s_config_prms.i4_max_log2_tu_size = 5;
ps_params->s_config_prms.i4_max_search_range_horz = 512;
ps_params->s_config_prms.i4_max_search_range_vert = 256;
ps_params->s_config_prms.i4_max_tr_tree_depth_I = 1;
ps_params->s_config_prms.i4_max_tr_tree_depth_nI = 3;
ps_params->s_config_prms.i4_min_frame_qp = 1;
ps_params->s_config_prms.i4_min_log2_cu_size = 3;
ps_params->s_config_prms.i4_min_log2_tu_size = 2;
ps_params->s_config_prms.i4_num_frms_to_encode = -1;
ps_params->s_config_prms.i4_rate_factor = 500;
ps_params->s_config_prms.i4_rate_control_mode = 2;
ps_params->s_config_prms.i4_stuffing_enable = 0;
ps_params->s_config_prms.i4_vbr_max_peak_rate_dur = 2000;
/* LAP parameters */
ps_params->s_lap_prms.i4_size = sizeof(ihevce_lap_params_t);
ps_params->s_lap_prms.i4_deinterlacer_enable = 0;
ps_params->s_lap_prms.i4_denoise_enable = 0;
ps_params->s_lap_prms.i4_enable_wts_ofsts = 1;
ps_params->s_lap_prms.i4_rc_look_ahead_pics = 0;
/* Multi Thread parameters */
ps_params->s_multi_thrd_prms.i4_size = sizeof(ihevce_static_multi_thread_params_t);
ps_params->s_multi_thrd_prms.i4_max_num_cores = 1;
ps_params->s_multi_thrd_prms.i4_memory_alloc_ctrl_flag = 0;
ps_params->s_multi_thrd_prms.i4_num_proc_groups = 1;
ps_params->s_multi_thrd_prms.ai4_num_cores_per_grp[0] = -1;
ps_params->s_multi_thrd_prms.i4_use_thrd_affinity = -1; //0;
memset(&ps_params->s_multi_thrd_prms.au8_core_aff_mask[0], 0, sizeof(ULWORD64) * MAX_NUM_CORES);
/* Output Streams parameters */
ps_params->s_out_strm_prms.i4_size = sizeof(ihevce_out_strm_params_t);
ps_params->s_out_strm_prms.i4_aud_enable_flags = 0;
ps_params->s_out_strm_prms.i4_eos_enable_flags = 0;
ps_params->s_out_strm_prms.i4_codec_profile = 1;
ps_params->s_out_strm_prms.i4_codec_tier = 0;
ps_params->s_out_strm_prms.i4_codec_type = 0;
ps_params->s_out_strm_prms.i4_sei_buffer_period_flags = 0;
ps_params->s_out_strm_prms.i4_sei_enable_flag = 0;
ps_params->s_out_strm_prms.i4_sei_payload_enable_flag = 0;
ps_params->s_out_strm_prms.i4_sei_pic_timing_flags = 0;
ps_params->s_out_strm_prms.i4_sei_cll_enable = 0;
ps_params->s_out_strm_prms.u2_sei_avg_cll = 0;
ps_params->s_out_strm_prms.u2_sei_max_cll = 0;
ps_params->s_out_strm_prms.i4_sei_recovery_point_flags = 0;
ps_params->s_out_strm_prms.i4_sei_mastering_disp_colour_vol_flags = 0;
ps_params->s_out_strm_prms.i4_decoded_pic_hash_sei_flag = 0;
ps_params->s_out_strm_prms.i4_sps_at_cdr_enable = 1;
ps_params->s_out_strm_prms.i4_vui_enable = 0;
/*Set the interoperability flag to 0*/
ps_params->s_out_strm_prms.i4_interop_flags = 0;
/* Source parameters */
ps_params->s_src_prms.i4_size = sizeof(ihevce_src_params_t);
ps_params->s_src_prms.inp_chr_format = 1;
ps_params->s_src_prms.i4_chr_format = 11;
ps_params->s_src_prms.i4_field_pic = 0;
ps_params->s_src_prms.i4_frm_rate_denom = 1000;
ps_params->s_src_prms.i4_frm_rate_num = 30000;
ps_params->s_src_prms.i4_height = 0; //1080;
ps_params->s_src_prms.i4_input_bit_depth = 8;
ps_params->s_src_prms.i4_topfield_first = 1;
ps_params->s_src_prms.i4_width = 0; //1920;
ps_params->s_src_prms.i4_orig_width = 0;
ps_params->s_src_prms.i4_orig_height = 0;
/* Target layer parameters */
ps_params->s_tgt_lyr_prms.i4_size = sizeof(ihevce_tgt_layer_params_t);
ps_params->s_tgt_lyr_prms.i4_enable_temporal_scalability = 0;
ps_params->s_tgt_lyr_prms.i4_internal_bit_depth = 8;
ps_params->s_tgt_lyr_prms.i4_mbr_quality_setting = IHEVCE_MBR_HIGH_QUALITY;
ps_params->s_tgt_lyr_prms.i4_multi_res_layer_reuse = 0;
ps_params->s_tgt_lyr_prms.i4_num_res_layers = 1;
ps_params->s_tgt_lyr_prms.i4_mres_single_out = 0;
ps_params->s_tgt_lyr_prms.i4_start_res_id = 0;
ps_params->s_tgt_lyr_prms.pf_scale_chroma = NULL;
ps_params->s_tgt_lyr_prms.pf_scale_luma = NULL;
ps_params->s_tgt_lyr_prms.pv_scaler_handle = NULL;
/* target parameters */
for(i = 0; i < IHEVCE_MAX_NUM_RESOLUTIONS; i++)
{
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_size = sizeof(ihevce_tgt_params_t);
for(j = 0; j < IHEVCE_MAX_NUM_BITRATES; j++)
{
ps_params->s_tgt_lyr_prms.as_tgt_params[i].ai4_frame_qp[j] = 32;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].ai4_tgt_bitrate[j] = 5000000;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].ai4_peak_bitrate[j] = 10000000;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].ai4_max_vbv_buffer_size[j] = -1;
}
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_codec_level = 156;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_frm_rate_scale_factor = 1;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_height = 0;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_num_bitrate_instances = 1;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_quality_preset = IHEVCE_QUALITY_P5;
ps_params->s_tgt_lyr_prms.as_tgt_params[i].i4_width = 0;
}
/* SEI VUI parameters */
ps_params->s_vui_sei_prms.u1_aspect_ratio_info_present_flag = 0;
ps_params->s_vui_sei_prms.au1_aspect_ratio_idc[0] = 255;
ps_params->s_vui_sei_prms.au2_sar_width[0] = 4;
ps_params->s_vui_sei_prms.au2_sar_height[0] = 3;
ps_params->s_vui_sei_prms.u1_overscan_info_present_flag = 0;
ps_params->s_vui_sei_prms.u1_overscan_appropriate_flag = 0;
ps_params->s_vui_sei_prms.u1_video_signal_type_present_flag = 1;
ps_params->s_vui_sei_prms.u1_video_format = 5;
ps_params->s_vui_sei_prms.u1_video_full_range_flag = 1;
ps_params->s_vui_sei_prms.u1_colour_description_present_flag = 0;
ps_params->s_vui_sei_prms.u1_colour_primaries = 2;
ps_params->s_vui_sei_prms.u1_transfer_characteristics = 2;
ps_params->s_vui_sei_prms.u1_matrix_coefficients = 2;
ps_params->s_vui_sei_prms.u1_chroma_loc_info_present_flag = 0;
ps_params->s_vui_sei_prms.u1_chroma_sample_loc_type_top_field = 0;
ps_params->s_vui_sei_prms.u1_chroma_sample_loc_type_bottom_field = 0;
ps_params->s_vui_sei_prms.u1_vui_hrd_parameters_present_flag = 0;
ps_params->s_vui_sei_prms.u1_timing_info_present_flag = 0;
ps_params->s_vui_sei_prms.u1_nal_hrd_parameters_present_flag = 0;
/* Setting sysAPIs to NULL */
memset(&ps_params->s_sys_api, 0, sizeof(ihevce_sys_api_t));
/* Multi pass parameters */
memset(&ps_params->s_pass_prms, 0, sizeof(ihevce_pass_prms_t));
ps_params->s_pass_prms.i4_size = sizeof(ihevce_pass_prms_t);
/* Tile parameters */
ps_params->s_app_tile_params.i4_size = sizeof(ihevce_app_tile_params_t);
ps_params->s_app_tile_params.i4_tiles_enabled_flag = 0;
ps_params->s_app_tile_params.i4_uniform_spacing_flag = 1;
ps_params->s_app_tile_params.i4_num_tile_cols = 1;
ps_params->s_app_tile_params.i4_num_tile_rows = 1;
ps_params->s_slice_params.i4_slice_segment_mode = 0;
ps_params->s_slice_params.i4_slice_segment_argument = 1300;
return (IHEVCE_EOK);
}
/*!
******************************************************************************
* \if Function name : ihevce_cmds_error_report \endif
*
* \brief
* Call back from encoder to report errors
*
* \param[in] pv_error_handling_cb_handle
* \param[in] i4_error_code
* \param[in] i4_cmd_type
* \param[in] i4_id
*
* \return
* None
*
* \author
* Ittiam
*
*****************************************************************************
*/
IV_API_CALL_STATUS_T ihevce_cmds_error_report(
void *pv_cb_handle, WORD32 i4_error_code, WORD32 i4_cmd_type, WORD32 i4_buf_id)
{
/*local variables*/
plugin_ctxt_t *plugin_ctxt = (plugin_ctxt_t *)pv_cb_handle;
ihevce_static_cfg_params_t *ps_static_cfg_params =
((ihevce_hle_ctxt_t *)plugin_ctxt->pv_hle_interface_ctxt)->ps_static_cfg_prms;
if(i4_cmd_type == 0)
ps_static_cfg_params->s_sys_api.ihevce_printf(
ps_static_cfg_params->s_sys_api.pv_cb_handle,
"PLUGIN ERROR: Asynchronous Buffer Error %d in Buffer Id %d",
i4_error_code,
i4_buf_id);
else
ps_static_cfg_params->s_sys_api.ihevce_printf(
ps_static_cfg_params->s_sys_api.pv_cb_handle,
"PLUGIN ERROR: Synchronous Buffer Error %d in Buffer Id %d",
i4_error_code,
i4_buf_id);
return (IV_SUCCESS);
}
/*!
******************************************************************************
* \if Function name : ihevce_strm_fill_done \endif
*
* \brief
* Call back from encoder when Bitstream is ready to consume
*
* \param[in]
* \param[in]
* \param[in]
*
* \return
* None
*
* \author
* Ittiam
*
*****************************************************************************
*/
IV_API_CALL_STATUS_T
ihevce_strm_fill_done(void *pv_ctxt, void *pv_curr_out, WORD32 i4_br_id, WORD32 i4_res_id)
{
/* local variables */
plugin_ctxt_t *ps_ctxt = (plugin_ctxt_t *)pv_ctxt;
app_ctxt_t *ps_app_ctxt = &ps_ctxt->s_app_ctxt;
out_strm_prms_t *ps_out_strm_prms = &ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id];
void *pv_app_out_strm_buf_mutex_hdl = ps_out_strm_prms->pv_app_out_strm_buf_mutex_hdl;
void *pv_app_out_strm_buf_cond_var_hdl = ps_out_strm_prms->pv_app_out_strm_buf_cond_var_hdl;
iv_output_data_buffs_t *ps_curr_out = (iv_output_data_buffs_t *)pv_curr_out;
WORD32 end_flag = ps_curr_out->i4_end_flag;
WORD32 osal_result;
/* ------ output dump stream -- */
if((WORD32)IV_FAIL != ps_curr_out->i4_process_ret_sts)
{
if(0 != ps_curr_out->i4_bytes_generated)
{
/* accumulate the total bits generated */
(ps_out_strm_prms->u8_total_bits) += ps_curr_out->i4_bytes_generated * 8;
(ps_out_strm_prms->u4_num_frms_enc)++;
}
}
/****** Lock the critical section ******/
osal_result = osal_mutex_lock(pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return (IV_FAIL);
/* Update the end flag to communicate with the o/p thread */
ps_app_ctxt->ai4_out_strm_end_flag[i4_res_id][i4_br_id] = end_flag;
/* set the produced status of the buffer */
{
WORD32 idx = ps_curr_out->i4_cb_buf_id;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_timestamp_low =
ps_curr_out->i4_out_timestamp_low;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_timestamp_high =
ps_curr_out->i4_out_timestamp_high;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_bytes_gen =
ps_curr_out->i4_bytes_generated;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_is_key_frame = 0;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_end_flag = end_flag;
if((IV_IDR_FRAME == ps_curr_out->i4_encoded_frame_type) ||
(IV_I_FRAME == ps_curr_out->i4_encoded_frame_type))
{
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_is_key_frame = 1;
}
/* set the buffer as produced */
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][idx].i4_is_prod = 1;
}
/****** Wake ******/
osal_cond_var_signal(pv_app_out_strm_buf_cond_var_hdl);
/****** Unlock the critical section ******/
osal_result = osal_mutex_unlock(pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return (IV_FAIL);
return (IV_SUCCESS);
}
/*!
******************************************************************************
* \if Function name : ihevce_plugin_init \endif
*
* \brief
* Initialises the enocder context and threads
*
* \param[in] Static params pointer
*
* \return
* status
*
* \author
* Ittiam
*
*****************************************************************************
*/
IHEVCE_PLUGIN_STATUS_T ihevce_init(ihevce_static_cfg_params_t *ps_params, void **ppv_ihevce_hdl)
{
/* local variables */
plugin_ctxt_t *ps_ctxt;
app_ctxt_t *ps_app_ctxt;
ihevce_hle_ctxt_t *ps_interface_ctxt;
ihevce_sys_api_t *ps_sys_api;
osal_cb_funcs_t s_cb_funcs;
WORD32 status = 0;
/* sanity checks */
if(NULL == ps_params)
return (IHEVCE_EFAIL);
if(NULL == ppv_ihevce_hdl)
return (IHEVCE_EFAIL);
/* set the handle to null by default */
*ppv_ihevce_hdl = NULL;
/* Initiallizing system apis */
ps_sys_api = &ps_params->s_sys_api;
ihevce_init_sys_api(NULL, ps_sys_api);
/* --------------------------------------------------------------------- */
/* Query and print Encoder version */
/* --------------------------------------------------------------------- */
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "Encoder version %s\n\n", ihevce_get_encoder_version());
/* --------------------------------------------------------------------- */
/* Plugin Handle create */
/* --------------------------------------------------------------------- */
ps_ctxt = (plugin_ctxt_t *)memory_alloc(NULL, sizeof(plugin_ctxt_t));
if(NULL == ps_ctxt)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in Plugin initialization\n");
return (IHEVCE_EFAIL);
}
memset(ps_ctxt, 0, sizeof(plugin_ctxt_t));
/* initialise memory call backs */
ps_ctxt->ihevce_mem_alloc = memory_alloc;
ps_ctxt->ihevce_mem_free = memory_free;
ps_ctxt->u8_num_frames_encoded = 0;
if((0 == ps_params->i4_res_id) && (0 == ps_params->i4_br_id))
{
/* --------------------------------------------------------------------- */
/* OSAL Handle create */
/* --------------------------------------------------------------------- */
ps_ctxt->pv_osal_handle = memory_alloc(NULL, OSAL_HANDLE_SIZE);
/* Initialize OSAL call back functions */
s_cb_funcs.mmr_handle = NULL;
s_cb_funcs.osal_alloc = memory_alloc;
s_cb_funcs.osal_free = memory_free;
status = osal_init(ps_ctxt->pv_osal_handle);
if(OSAL_SUCCESS != status)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in OSAL initialization\n");
return (IHEVCE_EFAIL);
}
status = osal_register_callbacks(ps_ctxt->pv_osal_handle, &s_cb_funcs);
if(OSAL_SUCCESS != status)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in OSAL call back registration\n");
return (IHEVCE_EFAIL);
}
/* --------------------------------------------------------------------- */
/* Thread affinity Initialization */
/* --------------------------------------------------------------------- */
if(ps_params->s_multi_thrd_prms.i4_use_thrd_affinity)
{
WORD32 i4_ctr;
/* loop over all the cores */
for(i4_ctr = 0; i4_ctr < ps_params->s_multi_thrd_prms.i4_max_num_cores; i4_ctr++)
{
/* All cores are logical cores */
ps_params->s_multi_thrd_prms.au8_core_aff_mask[i4_ctr] = ((ULWORD64)1 << i4_ctr);
}
}
/* --------------------------------------------------------------------- */
/* Context Initialization */
/* --------------------------------------------------------------------- */
ps_app_ctxt = &ps_ctxt->s_app_ctxt;
ps_ctxt->ps_static_cfg_prms = (ihevce_static_cfg_params_t *)ps_ctxt->ihevce_mem_alloc(
NULL, sizeof(ihevce_static_cfg_params_t));
if(NULL == ps_ctxt->ps_static_cfg_prms)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in Plugin memory initialization\n");
return (IHEVCE_EFAIL);
}
ps_params->apF_csv_file[0][0] = NULL;
/* set the memory manager handle to NULL */
ps_app_ctxt->pv_mem_mngr_handle = NULL;
/* --------------------------------------------------------------------- */
/* Back up the static params passed by caller */
/* --------------------------------------------------------------------- */
memcpy(ps_ctxt->ps_static_cfg_prms, ps_params, sizeof(ihevce_static_cfg_params_t));
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_orig_width =
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width;
if(HEVCE_MIN_WIDTH > ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width)
{
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width = HEVCE_MIN_WIDTH;
}
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_orig_height =
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_height;
if(HEVCE_MIN_HEIGHT > ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_height)
{
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_height = HEVCE_MIN_HEIGHT;
}
/* setting tgt width and height same as src width and height */
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[0].i4_width =
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width;
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[0].i4_height =
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_height;
/* setting key frame interval */
ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_closed_gop_period =
MIN(MAX_NUM_FRM_IN_GOP,
ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_closed_gop_period);
ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_cra_open_gop_period =
MIN(MAX_NUM_FRM_IN_GOP,
ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_cra_open_gop_period);
ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_i_open_gop_period =
MIN(MAX_NUM_FRM_IN_GOP,
ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_i_open_gop_period);
/* --------------------------------------------------------------------- */
/* High Level Encoder context init */
/* --------------------------------------------------------------------- */
ps_interface_ctxt =
(ihevce_hle_ctxt_t *)ps_ctxt->ihevce_mem_alloc(NULL, sizeof(ihevce_hle_ctxt_t));
if(NULL == ps_interface_ctxt)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle,
"IHEVCE ERROR: Error in Plugin HLE memory initialization\n");
return (IHEVCE_EFAIL);
}
memset(ps_interface_ctxt, 0, sizeof(ihevce_hle_ctxt_t));
ps_interface_ctxt->i4_size = sizeof(ihevce_hle_ctxt_t);
ps_ctxt->pv_hle_interface_ctxt = ps_interface_ctxt;
/* store the static config parameters pointer */
ps_interface_ctxt->ps_static_cfg_prms = ps_ctxt->ps_static_cfg_prms;
/* initialise the interface strucure parameters */
ps_interface_ctxt->pv_inp_cb_handle = (void *)ps_ctxt;
ps_interface_ctxt->pv_out_cb_handle = (void *)ps_ctxt;
ps_interface_ctxt->pv_recon_cb_handle = (void *)ps_ctxt;
ps_interface_ctxt->pv_osal_handle = ps_ctxt->pv_osal_handle;
ps_interface_ctxt->ihevce_mem_alloc = mem_mngr_alloc;
ps_interface_ctxt->ihevce_mem_free = mem_mngr_free;
ps_interface_ctxt->i4_hle_init_done = 0;
ps_interface_ctxt->pv_mem_mgr_hdl = ps_app_ctxt->pv_mem_mngr_handle;
/* reigter the callbacks */
ps_interface_ctxt->ihevce_output_strm_fill_done = ihevce_strm_fill_done;
ps_interface_ctxt->ihevce_output_recon_fill_done = NULL;
ps_interface_ctxt->ihevce_set_free_input_buff = NULL;
/*Added for run time or create time creation*/
ps_interface_ctxt->i4_create_time_input_allocation = (WORD32)CREATE_TIME_ALLOCATION_INPUT;
ps_interface_ctxt->i4_create_time_output_allocation = (WORD32)CREATE_TIME_ALLOCATION_OUTPUT;
ps_interface_ctxt->ihevce_cmds_error_report = ihevce_cmds_error_report;
ps_interface_ctxt->pv_cmd_err_cb_handle = (void *)ps_ctxt;
/* --------------------------------------------------------------------- */
/* High Level Encoder Instance Creation */
/* --------------------------------------------------------------------- */
status = ihevce_hle_interface_create(ps_interface_ctxt);
if((WORD32)IV_FAIL == status)
{
ihevce_hle_interface_delete(ps_interface_ctxt);
memory_free(NULL, ps_interface_ctxt);
/* free static config memory */
ps_ctxt->ihevce_mem_free(NULL, ps_ctxt->ps_static_cfg_prms);
/* free osal handle */
memory_free(NULL, ps_ctxt->pv_osal_handle);
/* free plugin ctxt memory */
memory_free(NULL, ps_ctxt);
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in Plugin HLE create failed\n");
return (IHEVCE_EFAIL);
}
/* --------------------------------------------------------------------- */
/* Input Output and Command buffer allocation */
/* --------------------------------------------------------------------- */
{
WORD32 ctr;
WORD32 buf_size;
UWORD8 *pu1_tmp_buf;
WORD32 i4_res_id;
WORD32 i4_br_id;
WORD32 i4_num_resolutions;
WORD32 ai4_num_bitrate_instances[IHEVCE_MAX_NUM_RESOLUTIONS] = { 1 };
iv_input_bufs_req_t s_input_bufs_req;
iv_res_layer_output_bufs_req_t s_res_layer_output_bufs_req;
iv_res_layer_recon_bufs_req_t s_res_layer_recon_bufs_req;
/* local array of pointers */
void *apv_inp_luma_bufs[MAX_NUM_INP_DATA_BUFS];
void *apv_inp_cb_bufs[MAX_NUM_INP_DATA_BUFS];
void *apv_inp_cr_bufs[MAX_NUM_INP_DATA_BUFS];
void *apv_inp_sync_bufs[MAX_NUM_INP_CTRL_SYNC_BUFS];
void *apv_inp_async_bufs[MAX_NUM_INP_CTRL_ASYNC_BUFS];
void *apv_out_data_bufs[IHEVCE_MAX_NUM_RESOLUTIONS][IHEVCE_MAX_NUM_BITRATES]
[MAX_NUM_OUT_DATA_BUFS];
/* get the number of resolutions */
i4_num_resolutions = ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
/* set the size of the structure */
s_input_bufs_req.i4_size = sizeof(iv_input_bufs_req_t);
s_res_layer_output_bufs_req.i4_size = sizeof(iv_res_layer_output_bufs_req_t);
s_res_layer_recon_bufs_req.i4_size = sizeof(iv_res_layer_recon_bufs_req_t);
/* loop over num resolutions */
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
/* store the number of bitrates */
ai4_num_bitrate_instances[i4_res_id] =
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_res_id]
.i4_num_bitrate_instances;
/* loop over num bitrates */
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id].i4_size =
sizeof(iv_output_bufs_req_t);
}
}
/* call Query I/O buffer */
status = ihevce_query_io_buf_req(
ps_interface_ctxt,
&s_input_bufs_req,
&s_res_layer_output_bufs_req,
&s_res_layer_recon_bufs_req);
/* check on the requirements against the MAX of application */
/* should be present only for debug purpose */
/* --------------- Input data buffers init ---------------------- */
/* allocate memory for input buffers */
if(ps_interface_ctxt->i4_create_time_input_allocation == 1)
{
buf_size = s_input_bufs_req.i4_min_size_uv_buf + s_input_bufs_req.i4_min_size_y_buf;
ps_ctxt->s_memtab_inp_data_buf.i4_size = sizeof(iv_mem_rec_t);
ps_ctxt->s_memtab_inp_data_buf.i4_mem_alignment = 4;
ps_ctxt->s_memtab_inp_data_buf.i4_mem_size =
(s_input_bufs_req.i4_min_num_yuv_bufs + XTRA_INP_DATA_BUFS) * buf_size;
ps_ctxt->s_memtab_inp_data_buf.e_mem_type = IV_EXT_CACHEABLE_NUMA_NODE0_MEM;
mem_mngr_alloc(
ps_app_ctxt->pv_mem_mngr_handle, ps_sys_api, &ps_ctxt->s_memtab_inp_data_buf);
pu1_tmp_buf = (UWORD8 *)ps_ctxt->s_memtab_inp_data_buf.pv_base;
if(NULL == pu1_tmp_buf)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in allocate memory\n");
return (IHEVCE_EFAIL);
}
/* loop to initialise the buffer pointer */
for(ctr = 0; ctr < s_input_bufs_req.i4_min_num_yuv_bufs + XTRA_INP_DATA_BUFS; ctr++)
{
apv_inp_luma_bufs[ctr] = pu1_tmp_buf;
apv_inp_cb_bufs[ctr] = pu1_tmp_buf + s_input_bufs_req.i4_min_size_y_buf;
apv_inp_cr_bufs[ctr] = NULL; /* 420SP case */
/* increment the input buffer pointer to next buffer */
pu1_tmp_buf += buf_size;
}
}
/* --------------- Output data buffers init ---------------------- */
/* loop over num resolutions */
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
buf_size = s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_size_bitstream_buf;
ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id].i4_size =
sizeof(iv_mem_rec_t);
ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id].i4_mem_alignment = 4;
if(!ps_interface_ctxt->i4_create_time_output_allocation)
{
ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id].i4_mem_size =
(s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_num_out_bufs +
XTRA_OUT_DATA_BUFS) *
buf_size;
}
else
{
ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id].i4_mem_size =
(s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_num_out_bufs) *
buf_size;
}
ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id].e_mem_type =
IV_EXT_CACHEABLE_NUMA_NODE1_MEM;
mem_mngr_alloc(
ps_app_ctxt->pv_mem_mngr_handle,
ps_sys_api,
&ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id]);
pu1_tmp_buf =
(UWORD8 *)ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id].pv_base;
if(NULL == pu1_tmp_buf)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in allocate memory\n");
return (IHEVCE_EFAIL);
}
if(ps_interface_ctxt->i4_create_time_output_allocation == 1)
{
/* loop to initialise the buffer pointer */
for(ctr = 0;
ctr < s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_num_out_bufs;
ctr++)
{
apv_out_data_bufs[i4_res_id][i4_br_id][ctr] = pu1_tmp_buf;
pu1_tmp_buf += buf_size;
}
}
else
{
WORD32 i4_num_out_bufs =
s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_num_out_bufs +
XTRA_OUT_DATA_BUFS;
ps_ctxt->i4_num_out_bufs = i4_num_out_bufs;
ps_ctxt->ai4_free_out_buf_idx[i4_res_id][i4_br_id] = 0;
ps_ctxt->i4_prod_out_buf_idx = 0;
/* Assert to make sure ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][] array
has more bufs than ps_ctxt->i4_num_out_bufs. Needed to identify
wrap-around case */
ASSERT(ps_ctxt->i4_num_out_bufs <= MAX_NUM_OUT_DATA_BUFS);
/* loop to initialise the buffer pointer */
for(ctr = 0; ctr < i4_num_out_bufs; ctr++)
{
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ctr].i4_idx = ctr;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ctr].i4_is_free = 1;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ctr].i4_is_prod = 0;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ctr].i4_bytes_gen = 0;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ctr].pu1_buf = pu1_tmp_buf;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ctr].i4_buf_size = buf_size;
pu1_tmp_buf += buf_size;
}
}
/* create mutex for controlling the out strm buf b/w appln and encoder */
ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_mutex_hdl = osal_mutex_create(ps_ctxt->pv_osal_handle);
if(NULL == ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_mutex_hdl)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle,
"IHEVCE ERROR: Error in Plugin initialization\n");
return (IHEVCE_EFAIL);
}
/* create mutex for controlling the out strm buf b/w appln and encoder */
ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_cond_var_hdl =
osal_cond_var_create(ps_ctxt->pv_osal_handle);
if(NULL == ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_cond_var_hdl)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle,
"IHEVCE ERROR: Error in Plugin initialization\n");
return (IHEVCE_EFAIL);
}
}
}
if(ps_interface_ctxt->i4_create_time_input_allocation == 1)
{
/* ------------- Input sync command buffers init -------------------- */
buf_size = s_input_bufs_req.i4_min_size_synch_ctrl_bufs;
ps_ctxt->s_memtab_inp_sync_ctrl_buf.i4_size = sizeof(iv_mem_rec_t);
ps_ctxt->s_memtab_inp_sync_ctrl_buf.i4_mem_alignment = 4;
ps_ctxt->s_memtab_inp_sync_ctrl_buf.i4_mem_size =
(s_input_bufs_req.i4_min_num_yuv_bufs + XTRA_INP_DATA_BUFS) * buf_size;
ps_ctxt->s_memtab_inp_sync_ctrl_buf.e_mem_type = IV_EXT_CACHEABLE_NUMA_NODE0_MEM;
mem_mngr_alloc(
ps_app_ctxt->pv_mem_mngr_handle,
ps_sys_api,
&ps_ctxt->s_memtab_inp_sync_ctrl_buf);
pu1_tmp_buf = (UWORD8 *)ps_ctxt->s_memtab_inp_sync_ctrl_buf.pv_base;
if(NULL == pu1_tmp_buf)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle, "IHEVCE ERROR: Error in allocate memory\n");
return (IHEVCE_EFAIL);
}
/* loop to initialise the buffer pointer */
for(ctr = 0; ctr < s_input_bufs_req.i4_min_num_yuv_bufs + XTRA_INP_DATA_BUFS; ctr++)
{
apv_inp_sync_bufs[ctr] = pu1_tmp_buf;
pu1_tmp_buf += buf_size;
}
}
/* ------------- Input async command buffers init -------------------- */
buf_size = s_input_bufs_req.i4_min_size_asynch_ctrl_bufs;
/* allocate memory for output status buffer */
ps_ctxt->pu1_inp_async_ctrl_buf = (UWORD8 *)ps_ctxt->ihevce_mem_alloc(
NULL, s_input_bufs_req.i4_min_num_asynch_ctrl_bufs * buf_size);
if(ps_ctxt->pu1_inp_async_ctrl_buf == NULL)
{
ps_sys_api->ihevce_printf(
ps_sys_api->pv_cb_handle,
"IHEVCE ERROR: Error in Plugin memory initialization\n");
return (IHEVCE_EFAIL);
}
pu1_tmp_buf = ps_ctxt->pu1_inp_async_ctrl_buf;
/* loop to initialise the buffer pointer */
for(ctr = 0; ctr < s_input_bufs_req.i4_min_num_asynch_ctrl_bufs; ctr++)
{
apv_inp_async_bufs[ctr] = pu1_tmp_buf;
pu1_tmp_buf += buf_size;
}
/* Create IO ports for the buffer allocated */
{
iv_input_data_ctrl_buffs_desc_t s_inp_desc;
iv_input_asynch_ctrl_buffs_desc_t s_inp_ctrl_desc;
iv_res_layer_output_data_buffs_desc_t s_mres_out_desc;
iv_res_layer_recon_data_buffs_desc_t s_mres_recon_desc;
/* set the parameters of the input data control desc */
s_inp_desc.i4_size = sizeof(iv_input_data_ctrl_buffs_desc_t);
s_inp_desc.i4_num_synch_ctrl_bufs = s_input_bufs_req.i4_min_num_synch_ctrl_bufs;
s_inp_desc.i4_num_yuv_bufs =
s_input_bufs_req.i4_min_num_yuv_bufs + XTRA_INP_DATA_BUFS;
s_inp_desc.i4_size_y_buf = s_input_bufs_req.i4_min_size_y_buf;
s_inp_desc.i4_size_uv_buf = s_input_bufs_req.i4_min_size_uv_buf;
s_inp_desc.i4_size_synch_ctrl_bufs = s_input_bufs_req.i4_min_size_synch_ctrl_bufs;
s_inp_desc.ppv_synch_ctrl_bufs = &apv_inp_sync_bufs[0];
s_inp_desc.ppv_y_buf = &apv_inp_luma_bufs[0];
s_inp_desc.ppv_u_buf = &apv_inp_cb_bufs[0];
s_inp_desc.ppv_v_buf = &apv_inp_cr_bufs[0];
/* set the parameters of the input async control desc */
s_inp_ctrl_desc.i4_size = sizeof(iv_input_asynch_ctrl_buffs_desc_t);
s_inp_ctrl_desc.i4_num_asynch_ctrl_bufs =
s_input_bufs_req.i4_min_num_asynch_ctrl_bufs;
s_inp_ctrl_desc.i4_size_asynch_ctrl_bufs =
s_input_bufs_req.i4_min_size_asynch_ctrl_bufs;
s_inp_ctrl_desc.ppv_asynch_ctrl_bufs = &apv_inp_async_bufs[0];
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
/* set the parameters of the output data desc */
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
s_mres_out_desc.s_output_data_buffs[i4_res_id][i4_br_id].i4_size =
sizeof(iv_output_data_buffs_desc_t);
if(!ps_interface_ctxt->i4_create_time_output_allocation)
{
s_mres_out_desc.s_output_data_buffs[i4_res_id][i4_br_id]
.i4_num_bitstream_bufs =
s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_num_out_bufs +
XTRA_OUT_DATA_BUFS;
}
else
{
s_mres_out_desc.s_output_data_buffs[i4_res_id][i4_br_id]
.i4_num_bitstream_bufs =
s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_num_out_bufs;
}
s_mres_out_desc.s_output_data_buffs[i4_res_id][i4_br_id]
.i4_size_bitstream_buf =
s_res_layer_output_bufs_req.s_output_buf_req[i4_res_id][i4_br_id]
.i4_min_size_bitstream_buf;
s_mres_out_desc.s_output_data_buffs[i4_res_id][i4_br_id].ppv_bitstream_bufs =
&apv_out_data_bufs[i4_res_id][i4_br_id][0];
}
}
s_mres_recon_desc.i4_size = sizeof(iv_res_layer_recon_data_buffs_desc_t);
/* call create I/O ports */
status = ihevce_create_ports(
ps_interface_ctxt,
&s_inp_desc,
&s_inp_ctrl_desc,
&s_mres_out_desc,
&s_mres_recon_desc);
}
}
/* --------------------------------------------------------------------- */
/* Create a High level encoder thread */
/* --------------------------------------------------------------------- */
{
osal_thread_attr_t s_thread_attr = OSAL_DEFAULT_THREAD_ATTR;
/* 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_hle_interface_thrd;
s_thread_attr.thread_param = (void *)(ps_interface_ctxt);
s_thread_attr.core_affinity_mask = 0;
s_thread_attr.group_num = 0;
/* Create High level encoder thread */
ps_ctxt->pv_hle_thread_hdl =
osal_thread_create(ps_ctxt->pv_osal_handle, &s_thread_attr);
if(NULL == ps_ctxt->pv_hle_thread_hdl)
{
return IHEVCE_EFAIL;
}
}
/* --------------------------------------------------------------------- */
/* Wait until HLE init is done */
/* --------------------------------------------------------------------- */
{
volatile WORD32 hle_init_done;
volatile WORD32 *pi4_hle_init_done;
pi4_hle_init_done = (volatile WORD32 *)&ps_interface_ctxt->i4_hle_init_done;
do
{
hle_init_done = *pi4_hle_init_done;
} while(0 == hle_init_done);
}
/* reset flush mode */
ps_ctxt->i4_flush_mode_on = 0;
{
WORD32 i4_res_id;
WORD32 i4_br_id;
for(i4_res_id = 0; i4_res_id < IHEVCE_MAX_NUM_RESOLUTIONS; i4_res_id++)
{
for(i4_br_id = 0; i4_br_id < IHEVCE_MAX_NUM_BITRATES; i4_br_id++)
{
/* reset out end flag */
ps_ctxt->ai4_out_end_flag[i4_res_id][i4_br_id] = 0;
}
}
}
/* reset the field id */
ps_ctxt->i4_field_id = 0;
/* based on number of B pics set the DTS value */
ps_ctxt->i8_dts = -1;
if(0 != ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_temporal_layers)
{
ps_ctxt->i8_dts =
(-1) *
(1 << ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_temporal_layers);
}
/* initialsie the buffer stride */
{
WORD32 max_cu_size;
max_cu_size = (1 << ps_ctxt->ps_static_cfg_prms->s_config_prms.i4_max_log2_cu_size);
ps_ctxt->i4_frm_stride =
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width +
SET_CTB_ALIGN(ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width, max_cu_size);
}
}
else
{
/* free plugin ctxt memory */
memory_free(NULL, ps_ctxt);
return (IHEVCE_EFAIL);
}
/* reset the place holders of old bitrate */
memset(&ps_ctxt->ai4_old_bitrate[0][0], 0, sizeof(ps_ctxt->ai4_old_bitrate));
ps_ctxt->ai4_old_bitrate[0][0] = ps_params->s_tgt_lyr_prms.as_tgt_params[0].ai4_tgt_bitrate[0];
/* store the plugin handle before returning */
*ppv_ihevce_hdl = (void *)ps_ctxt;
return (IHEVCE_EOK);
}
static IHEVCE_PLUGIN_STATUS_T
ihevce_receive_out_buffer(plugin_ctxt_t *ps_ctxt, ihevce_out_buf_t *ps_out)
{
app_ctxt_t *ps_app_ctxt = &ps_ctxt->s_app_ctxt;
WORD32 i4_res_id, i4_br_id;
WORD32 i4_num_resolutions;
WORD32 ai4_num_bitrate_instances[IHEVCE_MAX_NUM_RESOLUTIONS] = { 1 };
i4_num_resolutions = ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
ai4_num_bitrate_instances[i4_res_id] =
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_res_id]
.i4_num_bitrate_instances;
}
/* default init */
ps_out->pu1_output_buf = NULL;
ps_out->i4_bytes_generated = 0;
/* ---------------- if any output buffer is available return the buffer back ------------- */
while(1)
{
WORD32 osal_result;
WORD32 buf_present = 0;
WORD32 i4_is_prod = 1;
WORD32 i4_atleast_one_br_prod = 0;
/****** Lock the critical section ******/
osal_result =
osal_mutex_lock(ps_app_ctxt->as_out_strm_prms[0][0].pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return IHEVCE_EFAIL;
/* wait until entropy sends an output */
while(1)
{
i4_is_prod = 1;
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
i4_is_prod &=
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ps_ctxt->i4_prod_out_buf_idx]
.i4_is_prod;
i4_atleast_one_br_prod |=
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ps_ctxt->i4_prod_out_buf_idx]
.i4_is_prod;
}
}
if(!i4_is_prod)
{
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
osal_cond_var_wait(
ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_cond_var_hdl,
ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_mutex_hdl);
}
}
}
else
{
break;
}
}
ASSERT(i4_is_prod == 1);
/* check if the current buffer for all bitrates and resolutions have been produced */
if(1 == i4_is_prod)
{
buf_present = 1;
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
/* set the buffer to free status */
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][ps_ctxt->i4_prod_out_buf_idx]
.i4_is_free = 1;
if((0 == i4_res_id) && (0 == i4_br_id))
{
ps_out->i4_bytes_generated =
ps_ctxt->aaas_out_bufs[0][0][ps_ctxt->i4_prod_out_buf_idx].i4_bytes_gen;
ps_out->pu1_output_buf =
ps_ctxt->aaas_out_bufs[0][0][ps_ctxt->i4_prod_out_buf_idx].pu1_buf;
}
}
}
/* copy the contents to output buffer */
ps_out->i4_is_key_frame =
ps_ctxt->aaas_out_bufs[0][0][ps_ctxt->i4_prod_out_buf_idx].i4_is_key_frame;
ps_out->u8_pts =
ps_ctxt->aaas_out_bufs[0][0][ps_ctxt->i4_prod_out_buf_idx].i4_timestamp_low;
ps_out->u8_pts =
ps_out->u8_pts |
((ULWORD64)(
ps_ctxt->aaas_out_bufs[0][0][ps_ctxt->i4_prod_out_buf_idx].i4_timestamp_high)
<< 32);
ps_out->i4_end_flag =
ps_ctxt->aaas_out_bufs[0][0][ps_ctxt->i4_prod_out_buf_idx].i4_end_flag;
ps_out->i8_dts = ps_ctxt->i8_dts;
/* increment the DTS */
ps_ctxt->i8_dts++;
}
/* check for buffer present */
if(1 == buf_present)
{
ps_ctxt->i4_prod_out_buf_idx++;
/* wrap around case */
if(ps_ctxt->i4_prod_out_buf_idx == ps_ctxt->i4_num_out_bufs)
{
ps_ctxt->i4_prod_out_buf_idx = 0;
}
/****** Unlock the critical section ******/
osal_result = osal_mutex_unlock(
ps_app_ctxt->as_out_strm_prms[0][0].pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return IHEVCE_EFAIL;
/* break while 1 loop */
break;
}
else
{
/* in steady state*/
if(0 == ps_ctxt->i4_flush_mode_on)
{
/****** Unlock the critical section ******/
osal_result = osal_mutex_unlock(
ps_app_ctxt->as_out_strm_prms[0][0].pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return IHEVCE_EFAIL;
if(!i4_atleast_one_br_prod) /*** If atleast one bitrate is produced do not break from loop **/
{ /*** Continue in while loop and Wait for next bitrate ***/
/* break while 1 loop */
break;
}
}
else
{
/* In flush mode is ON then this function must return output
buffers. Otherwise assume that encoding is over and return fail */
/****** Unlock the critical section ******/
osal_result = osal_mutex_unlock(
ps_app_ctxt->as_out_strm_prms[0][0].pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return IHEVCE_EFAIL;
}
}
}
return IHEVCE_EOK;
}
static IHEVCE_PLUGIN_STATUS_T
ihevce_queue_out_buffer(plugin_ctxt_t *ps_ctxt, WORD32 i4_res_id, WORD32 i4_br_id)
{
app_ctxt_t *ps_app_ctxt = &ps_ctxt->s_app_ctxt;
ihevce_hle_ctxt_t *ps_interface_ctxt = (ihevce_hle_ctxt_t *)ps_ctxt->pv_hle_interface_ctxt;
/* --------------------------------------------------------------------- */
/* Free Output buffer Queuing */
/* --------------------------------------------------------------------- */
/* ------- Que in free output buffer if end flag is not set ------ */
if(0 == ps_ctxt->ai4_out_end_flag[i4_res_id][i4_br_id])
{
WORD32 osal_result;
iv_output_data_buffs_t *ps_curr_out;
WORD32 buf_id_strm;
WORD32 free_idx;
free_idx = ps_ctxt->ai4_free_out_buf_idx[i4_res_id][i4_br_id];
if(1 == ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_is_free)
{
/* ---------- get a free desc. from output Q ------ */
ps_curr_out = (iv_output_data_buffs_t *)ihevce_q_get_free_out_strm_buff(
ps_interface_ctxt, &buf_id_strm, BUFF_QUE_NON_BLOCKING_MODE, i4_br_id, i4_res_id);
/* if a free buffer is available */
if(NULL != ps_curr_out)
{
/****** Lock the critical section ******/
osal_result = osal_mutex_lock(ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return IHEVCE_EFAIL;
if(1 == ps_app_ctxt->ai4_out_strm_end_flag[i4_res_id][i4_br_id])
{
ps_curr_out->i4_is_last_buf = 1;
ps_ctxt->ai4_out_end_flag[i4_res_id][i4_br_id] = 1;
}
else
{
ps_curr_out->i4_is_last_buf = 0;
}
ASSERT(ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_is_free == 1);
ASSERT(free_idx == ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_idx);
ps_curr_out->pv_bitstream_bufs =
(void *)ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].pu1_buf;
ps_curr_out->i4_cb_buf_id =
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_idx;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_is_free = 0;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_is_prod = 0;
ps_ctxt->aaas_out_bufs[i4_res_id][i4_br_id][free_idx].i4_bytes_gen = 0;
ps_ctxt->ai4_free_out_buf_idx[i4_res_id][i4_br_id]++;
/* wrap around case */
if(ps_ctxt->ai4_free_out_buf_idx[i4_res_id][i4_br_id] == ps_ctxt->i4_num_out_bufs)
{
ps_ctxt->ai4_free_out_buf_idx[i4_res_id][i4_br_id] = 0;
}
/****** Unlock the critical section ******/
osal_result = osal_mutex_unlock(ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_mutex_hdl);
if(OSAL_SUCCESS != osal_result)
return IHEVCE_EFAIL;
/* ---------- set the buffer as produced ---------- */
ihevce_q_set_out_strm_buff_prod(
ps_interface_ctxt, buf_id_strm, i4_br_id, i4_res_id);
}
}
}
return IHEVCE_EOK;
}
/*!
******************************************************************************
* \if Function name : ihevce_close \endif
*
* \brief
* De-Initialises the enocder context and threads
*
* \param[in] Static params pointer
*
* \return
* status
*
* \author
* Ittiam
*
*****************************************************************************
*/
IHEVCE_PLUGIN_STATUS_T ihevce_close(void *pv_ihevce_hdl)
{
/* local variables */
plugin_ctxt_t *ps_ctxt;
app_ctxt_t *ps_app_ctxt;
ihevce_hle_ctxt_t *ps_interface_ctxt;
WORD32 i4_num_resolutions;
WORD32 i4_res_id;
WORD32 i4_br_id;
WORD32 ai4_num_bitrate_instances[IHEVCE_MAX_NUM_RESOLUTIONS] = { 1 };
ihevce_sys_api_t *ps_sys_api;
/* sanity checks */
if(NULL == pv_ihevce_hdl)
return (IHEVCE_EFAIL);
/* derive local variables */
ps_ctxt = (plugin_ctxt_t *)pv_ihevce_hdl;
ps_sys_api = &ps_ctxt->ps_static_cfg_prms->s_sys_api;
if((0 == ps_ctxt->ps_static_cfg_prms->i4_res_id) &&
(0 == ps_ctxt->ps_static_cfg_prms->i4_br_id))
{
ps_interface_ctxt = (ihevce_hle_ctxt_t *)ps_ctxt->pv_hle_interface_ctxt;
ps_app_ctxt = &ps_ctxt->s_app_ctxt;
i4_num_resolutions = ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
if(1 != ps_ctxt->i4_flush_mode_on)
{
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
ai4_num_bitrate_instances[i4_res_id] =
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_res_id]
.i4_num_bitrate_instances;
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
/* ------- Que in free output buffer if end flag is not set ------ */
ihevce_queue_out_buffer(ps_ctxt, i4_res_id, i4_br_id);
}
}
/* --------------------------------------------------------------------- */
/* Input Processing */
/* --------------------------------------------------------------------- */
{
WORD32 buf_id;
iv_input_data_ctrl_buffs_t *ps_curr_inp;
WORD32 *pi4_ctrl_ptr;
/* ---------- get a free buffer from input Q ------ */
ps_curr_inp = (iv_input_data_ctrl_buffs_t *)ihevce_q_get_free_inp_data_buff(
ps_interface_ctxt, &buf_id, BUFF_QUE_BLOCKING_MODE);
if(NULL != ps_curr_inp)
{
/* flush mode command */
ps_curr_inp->i4_buf_id = buf_id;
/* set the input status to invalid flag */
ps_curr_inp->i4_inp_frm_data_valid_flag = 0;
pi4_ctrl_ptr = (WORD32 *)ps_curr_inp->pv_synch_ctrl_bufs;
*pi4_ctrl_ptr = IHEVCE_SYNCH_API_FLUSH_TAG;
*(pi4_ctrl_ptr + 1) = 0;
*(pi4_ctrl_ptr + 2) = IHEVCE_SYNCH_API_END_TAG;
ps_curr_inp->i4_cmd_buf_size = 4 * 3; /* 4 bytes */
/* ---------- set the buffer as produced ---------- */
ihevce_q_set_inp_data_buff_prod(ps_interface_ctxt, buf_id);
}
else
{
/* Enable flush-mode and internal-flush once limit according to
Eval-version is reached */
ps_ctxt->i4_flush_mode_on = 1;
}
}
}
/* --------------------------------------------------------------------- */
/* Wait and destroy Processing threads */
/* --------------------------------------------------------------------- */
/* Wait for High level encoder thread to complete */
osal_thread_wait(ps_ctxt->pv_hle_thread_hdl);
/* Destroy Hle thread */
osal_thread_destroy(ps_ctxt->pv_hle_thread_hdl);
/* --------------------------------------------------------------------- */
/* Input Output and Command buffers free */
/* --------------------------------------------------------------------- */
/* free output data and control buffer */
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
ai4_num_bitrate_instances[i4_res_id] =
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_res_id]
.i4_num_bitrate_instances;
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
mem_mngr_free(
ps_app_ctxt->pv_mem_mngr_handle,
&ps_ctxt->as_memtab_out_data_buf[i4_res_id][i4_br_id]);
/* free mutex of out strm buf b/w appln and encoder */
osal_mutex_destroy(ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_mutex_hdl);
osal_cond_var_destroy(ps_app_ctxt->as_out_strm_prms[i4_res_id][i4_br_id]
.pv_app_out_strm_buf_cond_var_hdl);
}
}
ps_ctxt->ihevce_mem_free(NULL, ps_ctxt->pu1_out_ctrl_buf);
ps_ctxt->ihevce_mem_free(NULL, ps_ctxt->pu1_inp_async_ctrl_buf);
/* free input data and control buffer */
if(ps_interface_ctxt->i4_create_time_input_allocation == 1)
{
mem_mngr_free(ps_app_ctxt->pv_mem_mngr_handle, &ps_ctxt->s_memtab_inp_data_buf);
mem_mngr_free(ps_app_ctxt->pv_mem_mngr_handle, &ps_ctxt->s_memtab_inp_sync_ctrl_buf);
}
/* --------------------------------------------------------------------- */
/* Encoder Instance Deletion */
/* --------------------------------------------------------------------- */
ihevce_hle_interface_delete(ps_interface_ctxt);
/* free the high level encoder context memory */
ps_ctxt->ihevce_mem_free(NULL, ps_ctxt->pv_hle_interface_ctxt);
if(ps_ctxt->ps_static_cfg_prms->i4_enable_csv_dump)
{
ps_sys_api->s_file_io_api.ihevce_fclose(
(void *)ps_sys_api->pv_cb_handle, ps_ctxt->ps_static_cfg_prms->apF_csv_file[0][0]);
}
/* free static config memory */
ps_ctxt->ihevce_mem_free(NULL, ps_ctxt->ps_static_cfg_prms);
/* free osal handle */
memory_free(NULL, ps_ctxt->pv_osal_handle);
/* free plugin ctxt memory */
memory_free(NULL, pv_ihevce_hdl);
}
else
{
return (IHEVCE_EFAIL);
}
return (IHEVCE_EOK);
}
/*!
******************************************************************************
* \if Function name : ihevce_copy_inp_8bit \endif
*
* \brief
* Input copy function for 8 bit input
*
* \param[in] Source and desdtination buffer descriptors
*
* \return
* None
*
* \author
* Ittiam
*
*****************************************************************************
*/
IV_API_CALL_STATUS_T ihevce_copy_inp_8bit(
iv_input_data_ctrl_buffs_t *ps_curr_inp,
ihevce_inp_buf_t *ps_inp,
WORD32 chroma_format,
WORD32 i4_orig_wd,
WORD32 i4_orig_ht)
{
UWORD8 *pu1_src, *pu1_dst;
WORD32 src_strd, dst_strd;
WORD32 frm_height = i4_orig_ht;
WORD32 frm_width = i4_orig_wd;
WORD32 buf_height = ps_curr_inp->s_input_buf.i4_y_ht;
WORD32 buf_width = ps_curr_inp->s_input_buf.i4_y_wd;
WORD32 rows, cols;
pu1_src = (UWORD8 *)ps_inp->apv_inp_planes[0];
src_strd = ps_inp->ai4_inp_strd[0];
pu1_dst = (UWORD8 *)ps_curr_inp->s_input_buf.pv_y_buf;
dst_strd = ps_curr_inp->s_input_buf.i4_y_strd;
if((ps_inp->ai4_inp_size[0] < (src_strd * frm_height)) || (ps_inp->ai4_inp_size[0] <= 0) ||
(ps_inp->apv_inp_planes[0] == NULL))
{
return (IV_FAIL);
}
/* copy the input luma data into internal buffer */
for(rows = 0; rows < frm_height; rows++)
{
memcpy(pu1_dst, pu1_src, frm_width);
if(buf_width > frm_width)
{
memset(pu1_dst + frm_width, 0x0, buf_width - frm_width);
}
pu1_src += src_strd;
pu1_dst += dst_strd;
}
while(rows < buf_height)
{
memset(pu1_dst, 0x0, buf_width);
pu1_dst += dst_strd;
rows++;
}
if(IV_YUV_420P == chroma_format)
{
UWORD8 *pu1_src_u, *pu1_src_v;
WORD32 src_strd_u, src_strd_v;
pu1_src_u = (UWORD8 *)ps_inp->apv_inp_planes[1];
src_strd_u = ps_inp->ai4_inp_strd[1];
pu1_src_v = (UWORD8 *)ps_inp->apv_inp_planes[2];
src_strd_v = ps_inp->ai4_inp_strd[2];
pu1_dst = (UWORD8 *)ps_curr_inp->s_input_buf.pv_u_buf;
dst_strd = ps_curr_inp->s_input_buf.i4_uv_strd;
frm_width = i4_orig_wd >> 1;
frm_height = i4_orig_ht >> 1;
buf_width = ps_curr_inp->s_input_buf.i4_uv_wd;
buf_height = ps_curr_inp->s_input_buf.i4_uv_ht;
if((ps_inp->ai4_inp_size[1] < (ps_inp->ai4_inp_strd[1] * frm_height)) ||
(ps_inp->ai4_inp_size[1] <= 0) || (pu1_src_u == NULL))
{
return (IV_FAIL);
}
if((ps_inp->ai4_inp_size[2] < (ps_inp->ai4_inp_strd[2] * frm_height)) ||
(ps_inp->ai4_inp_size[2] <= 0) || (pu1_src_v == NULL))
{
return (IV_FAIL);
}
/* copy the input chroma data in pixel interleaved format */
for(rows = 0; rows < frm_height; rows++)
{
for(cols = 0; cols < frm_width; cols++)
{
/* U V alternate */
pu1_dst[(cols << 1)] = pu1_src_u[cols];
pu1_dst[(cols << 1) + 1] = pu1_src_v[cols];
}
if(buf_width > (cols << 1))
{
memset(&pu1_dst[(cols << 1)], 0x80, buf_width - (cols << 1));
}
pu1_src_u += src_strd_u;
pu1_src_v += src_strd_v;
pu1_dst += dst_strd;
}
while(rows < buf_height)
{
memset(pu1_dst, 0x80, buf_width);
pu1_dst += dst_strd;
rows++;
}
}
else if(IV_YUV_420SP_UV == chroma_format)
{
pu1_src = (UWORD8 *)ps_inp->apv_inp_planes[1];
src_strd = ps_inp->ai4_inp_strd[1];
pu1_dst = (UWORD8 *)ps_curr_inp->s_input_buf.pv_u_buf;
dst_strd = ps_curr_inp->s_input_buf.i4_uv_strd;
frm_width = i4_orig_wd;
frm_height = i4_orig_ht >> 1;
buf_width = ps_curr_inp->s_input_buf.i4_uv_wd;
buf_height = ps_curr_inp->s_input_buf.i4_uv_ht;
if((ps_inp->ai4_inp_size[1] < (ps_inp->ai4_inp_strd[1] * frm_height)) ||
(ps_inp->ai4_inp_size[1] <= 0) || (pu1_src == NULL))
{
return (IV_FAIL);
}
/* copy the input luma data into internal buffer */
for(rows = 0; rows < frm_height; rows++)
{
memcpy(pu1_dst, pu1_src, frm_width);
if(buf_width > frm_width)
{
memset(pu1_dst + frm_width, 0x80, buf_width - frm_width);
}
pu1_src += src_strd;
pu1_dst += dst_strd;
}
while(rows < buf_height)
{
memset(pu1_dst, 0x80, buf_width);
pu1_dst += dst_strd;
rows++;
}
}
return (IV_SUCCESS);
}
/*!
******************************************************************************
* \if Function name : ihevce_encode_header \endif
*
* \brief
* Receive sps, pps and vps of the encoded sequence
*
* \param[in] Plugin handle, Output buffer
*
* \return
* Success or Failure
*
* \author
* Ittiam
*
*****************************************************************************
*/
IHEVCE_PLUGIN_STATUS_T ihevce_encode_header(void *pv_ihevce_hdl, ihevce_out_buf_t *ps_out)
{
plugin_ctxt_t *ps_ctxt = (plugin_ctxt_t *)pv_ihevce_hdl;
ihevce_hle_ctxt_t *ps_interface_ctxt;
/* sanity checks */
if(NULL == pv_ihevce_hdl)
return (IHEVCE_EFAIL);
if(NULL == ps_out)
return (IHEVCE_EFAIL);
if((0 == ps_ctxt->ps_static_cfg_prms->i4_res_id) &&
(0 == ps_ctxt->ps_static_cfg_prms->i4_br_id))
{
WORD32 status;
/* ------- Que in free output buffer if end flag is not set ------ */
ihevce_queue_out_buffer(ps_ctxt, 0, 0);
/* ------- API call to encoder header ------- */
ps_interface_ctxt = (ihevce_hle_ctxt_t *)ps_ctxt->pv_hle_interface_ctxt;
status = ihevce_entropy_encode_header(ps_interface_ctxt, 0, 0);
if(status)
return IHEVCE_EFAIL;
/* ------- receive header ------- */
ihevce_receive_out_buffer(ps_ctxt, ps_out);
}
else
{
return (IHEVCE_EFAIL);
}
return (IHEVCE_EOK);
}
/*!
******************************************************************************
* \if Function name : ihevce_encode \endif
*
* \brief
* Frame level processing function
*
* \param[in] Plugin handle, Input buffer, Output buffer
*
* \return
* Success or Failure
*
* \author
* Ittiam
*
*****************************************************************************
*/
IHEVCE_PLUGIN_STATUS_T
ihevce_encode(void *pv_ihevce_hdl, ihevce_inp_buf_t *ps_inp, ihevce_out_buf_t *ps_out)
{
/* local variables */
plugin_ctxt_t *ps_ctxt;
app_ctxt_t *ps_app_ctxt;
ihevce_hle_ctxt_t *ps_interface_ctxt;
WORD32 i4_res_id, i4_br_id;
WORD32 i4_num_resolutions;
WORD32 ai4_num_bitrate_instances[IHEVCE_MAX_NUM_RESOLUTIONS] = { 1 };
UWORD32 u4_latency = 0;
/* sanity checks */
if(NULL == pv_ihevce_hdl)
return (IHEVCE_EFAIL);
if(NULL == ps_out)
return (IHEVCE_EFAIL);
/* derive local variables */
ps_ctxt = (plugin_ctxt_t *)pv_ihevce_hdl;
if((0 == ps_ctxt->ps_static_cfg_prms->i4_res_id) &&
(0 == ps_ctxt->ps_static_cfg_prms->i4_br_id))
{
ps_interface_ctxt = (ihevce_hle_ctxt_t *)ps_ctxt->pv_hle_interface_ctxt;
ps_app_ctxt = &ps_ctxt->s_app_ctxt;
i4_num_resolutions = ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.i4_num_res_layers;
if(ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_temporal_layers)
{
u4_latency +=
(1 << ps_ctxt->ps_static_cfg_prms->s_coding_tools_prms.i4_max_temporal_layers);
}
u4_latency += ps_ctxt->ps_static_cfg_prms->s_lap_prms.i4_rc_look_ahead_pics;
/* Once the internal-flush-flag has been set and codec has issued
end flag, exit encoding by returning IHEVCE_EFAIL */
if(ps_ctxt->i4_internal_flush)
{
if(1 == ps_app_ctxt->ai4_out_strm_end_flag[0][0])
return (IHEVCE_EFAIL);
}
for(i4_res_id = 0; i4_res_id < i4_num_resolutions; i4_res_id++)
{
ai4_num_bitrate_instances[i4_res_id] =
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[i4_res_id]
.i4_num_bitrate_instances;
for(i4_br_id = 0; i4_br_id < ai4_num_bitrate_instances[i4_res_id]; i4_br_id++)
{
/* ------- Que in free output buffer if end flag is not set ------ */
ihevce_queue_out_buffer(ps_ctxt, i4_res_id, i4_br_id);
}
}
/* --------------------------------------------------------------------- */
/* Input Processing */
/* --------------------------------------------------------------------- */
if(0 == ps_ctxt->i4_flush_mode_on)
{
WORD32 frm_stride;
WORD32 frm_width;
WORD32 frm_height;
WORD32 buf_id;
iv_input_data_ctrl_buffs_t *ps_curr_inp;
WORD32 *pi4_ctrl_ptr;
frm_width = ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_width;
frm_height = ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_height;
frm_stride = ps_ctxt->i4_frm_stride;
/* ---------- get a free buffer from input Q ------ */
ps_curr_inp = (iv_input_data_ctrl_buffs_t *)ihevce_q_get_free_inp_data_buff(
ps_interface_ctxt, &buf_id, BUFF_QUE_BLOCKING_MODE);
if(NULL != ps_curr_inp)
{
/* if input buffer is not NULL */
if(NULL != ps_inp)
{
WORD32 result;
pi4_ctrl_ptr = (WORD32 *)ps_curr_inp->pv_synch_ctrl_bufs;
/* ---------- set ip params ---------- */
ps_curr_inp->s_input_buf.i4_size = sizeof(iv_yuv_buf_t);
ps_curr_inp->s_input_buf.i4_y_wd = frm_width;
ps_curr_inp->s_input_buf.i4_y_ht = frm_height;
ps_curr_inp->s_input_buf.i4_y_strd = frm_stride;
ps_curr_inp->s_input_buf.i4_uv_wd = frm_width;
ps_curr_inp->s_input_buf.i4_uv_ht =
frm_height >>
((ps_ctxt->ps_static_cfg_prms->s_src_prms.inp_chr_format == 13) ? 0 : 1);
ps_curr_inp->s_input_buf.i4_uv_strd = frm_stride;
ps_curr_inp->i4_buf_id = buf_id;
ps_curr_inp->i4_inp_frm_data_valid_flag = 1;
ps_curr_inp->i4_topfield_first = 1; /* set to default */
ps_curr_inp->i4_bottom_field = ps_ctxt->i4_field_id;
ps_curr_inp->i4_inp_timestamp_low = (WORD32)(ps_inp->u8_pts & 0xFFFFFFFF);
ps_curr_inp->i4_inp_timestamp_high = (WORD32)(ps_inp->u8_pts >> 32);
/* toggle field id */
ps_ctxt->i4_field_id = !ps_ctxt->i4_field_id;
/* set the cmd to NA */
*pi4_ctrl_ptr = IHEVCE_SYNCH_API_END_TAG;
ps_curr_inp->i4_cmd_buf_size = 4; /* 4 bytes */
/* call the input copy function */
result = ihevce_copy_inp_8bit(
ps_curr_inp,
ps_inp,
ps_ctxt->ps_static_cfg_prms->s_src_prms.inp_chr_format,
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_orig_width,
ps_ctxt->ps_static_cfg_prms->s_src_prms.i4_orig_height);
if(IV_SUCCESS != result)
return (IHEVCE_EFAIL);
if(3 != ps_ctxt->ps_static_cfg_prms->s_config_prms.i4_rate_control_mode)
{
/* Dynamic Change in bitrate not supported for multi res/MBR */
/*** Check for change in bitrate command ***/
if(ps_ctxt->ai4_old_bitrate[0][0] != ps_inp->i4_curr_bitrate)
{
WORD32 buf_id;
WORD32 *pi4_cmd_buf;
iv_input_ctrl_buffs_t *ps_ctrl_buf;
ihevce_dyn_config_prms_t *ps_dyn_br;
WORD32 codec_level_index = ihevce_get_level_index(
ps_ctxt->ps_static_cfg_prms->s_tgt_lyr_prms.as_tgt_params[0]
.i4_codec_level);
WORD32 max_bitrate =
g_as_level_data[codec_level_index].i4_max_bit_rate
[ps_ctxt->ps_static_cfg_prms->s_out_strm_prms.i4_codec_tier] *
1000;
/* ---------- get a free buffer from command Q ------ */
ps_ctrl_buf = (iv_input_ctrl_buffs_t *)ihevce_q_get_free_inp_ctrl_buff(
ps_interface_ctxt, &buf_id, BUFF_QUE_BLOCKING_MODE);
/* store the buffer id */
ps_ctrl_buf->i4_buf_id = buf_id;
/* get the buffer pointer */
pi4_cmd_buf = (WORD32 *)ps_ctrl_buf->pv_asynch_ctrl_bufs;
/* store the set default command, encoder should use create time prms */
*pi4_cmd_buf = IHEVCE_ASYNCH_API_SETBITRATE_TAG;
*(pi4_cmd_buf + 1) = sizeof(ihevce_dyn_config_prms_t);
ps_dyn_br = (ihevce_dyn_config_prms_t *)(pi4_cmd_buf + 2);
ps_dyn_br->i4_size = sizeof(ihevce_dyn_config_prms_t);
ps_dyn_br->i4_tgt_br_id = 0;
ps_dyn_br->i4_tgt_res_id = 0;
ps_dyn_br->i4_new_tgt_bitrate =
MIN(ps_inp->i4_curr_bitrate, max_bitrate);
ps_dyn_br->i4_new_peak_bitrate =
MIN((ps_dyn_br->i4_new_tgt_bitrate << 1), max_bitrate);
pi4_cmd_buf += 2;
pi4_cmd_buf += (sizeof(ihevce_dyn_config_prms_t) >> 2);
*(pi4_cmd_buf) = IHEVCE_ASYNCH_API_END_TAG;
/* ---------- set the buffer as produced ---------- */
ihevce_q_set_inp_ctrl_buff_prod(ps_interface_ctxt, buf_id);
ps_ctxt->ai4_old_bitrate[0][0] = ps_inp->i4_curr_bitrate;
}
}
ps_ctxt->u8_num_frames_queued++;
}
else
{ /* flush mode command */
ps_curr_inp->i4_buf_id = buf_id;
/* set the input status to invalid flag */
ps_curr_inp->i4_inp_frm_data_valid_flag = 0;
pi4_ctrl_ptr = (WORD32 *)ps_curr_inp->pv_synch_ctrl_bufs;
*pi4_ctrl_ptr = IHEVCE_SYNCH_API_FLUSH_TAG;
*(pi4_ctrl_ptr + 1) = 0;
*(pi4_ctrl_ptr + 2) = IHEVCE_SYNCH_API_END_TAG;
ps_curr_inp->i4_cmd_buf_size = 4 * 3; /* 4 bytes */
}
/* ---------- set the buffer as produced ---------- */
ihevce_q_set_inp_data_buff_prod(ps_interface_ctxt, buf_id);
ps_ctxt->u8_num_frames_encoded++;
}
else
{
/* Enable flush-mode and internal-flush once limit according to
Eval-version is reached */
ps_ctxt->i4_flush_mode_on = 1;
ps_ctxt->i4_internal_flush = 1;
}
}
/* set encoder in flush mode if input buffer is NULL */
if(0 == ps_ctxt->i4_flush_mode_on)
{
if(NULL == ps_inp)
{
ps_ctxt->i4_flush_mode_on = 1;
}
}
if((u4_latency < ps_ctxt->u8_num_frames_queued) || (1 == ps_ctxt->i4_flush_mode_on))
{
/* --------------------------------------------------------------------- */
/* Output Processing */
/* --------------------------------------------------------------------- */
ihevce_receive_out_buffer(ps_ctxt, ps_out);
}
}
else //Other bitrate and resolution instances
{
return IHEVCE_EFAIL;
}
return (IHEVCE_EOK);
}