/****************************************************************************** * * Copyright (C) 2019 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 */ #include #include #include #include #include #include #include "ixheaac_type_def.h" #include "ixheaac_error_standards.h" #include "ixheaacd_error_handler.h" #include "ixheaacd_apicmd_standards.h" #include "ixheaacd_memory_standards.h" #include "ixheaacd_aac_config.h" #include "impd_apicmd_standards.h" #include "impd_drc_config_params.h" /* 64*-0.25dB = -16 dB below full scale for mobile conf */ #define DRC_DEFAULT_MOBILE_REF_LEVEL 64 /* maximum compression of dynamic range for mobile conf */ #define DRC_DEFAULT_MOBILE_DRC_CUT 127 /* maximum compression of dynamic range for mobile conf */ #define DRC_DEFAULT_MOBILE_DRC_BOOST 127 /* switch for heavy compression for mobile conf */ #define DRC_DEFAULT_MOBILE_DRC_HEAVY 1 /* encoder target level; -1 => the value is unknown, otherwise dB \ step value (e.g. 64 for -16 dB) */ #define DRC_DEFAULT_MOBILE_ENC_LEVEL (-1) #define MAX_CHANNEL_COUNT 8 #define MAX_MEM_ALLOCS 100 class Codec { public: IA_ERRORCODE initDecoder(const uint8_t* data, size_t size, bool isADTS); IA_ERRORCODE initXAACDecoder(bool isADTS); IA_ERRORCODE initXAACDrc(const uint8_t* data, size_t size); IA_ERRORCODE deInitXAACDecoder(); IA_ERRORCODE deInitMPEGDDDrc(); IA_ERRORCODE configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed); IA_ERRORCODE initMPEGDDDrc(); int configMPEGDDrc(); IA_ERRORCODE decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed, int32_t* outBytes); IA_ERRORCODE getXAACStreamInfo(); IA_ERRORCODE setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, int32_t drcRefLevel, int32_t drcHeavyCompression, int32_t drEffectType); private: void* mXheaacCodecHandle; void* mMpegDDrcHandle; uint32_t mInputBufferSize; uint32_t mOutputFrameLength; int8_t* mInputBuffer; int8_t* mOutputBuffer; int32_t mSampFreq; int32_t mNumChannels; int32_t mPcmWdSz; int32_t mChannelMask; bool mIsCodecInitialized; bool mIsCodecConfigFlushRequired; int8_t* mDrcInBuf; int8_t* mDrcOutBuf; int32_t mMpegDDRCPresent; int32_t mDRCFlag; std::vector mMemoryVec; std::vector mDrcMemoryVec; }; extern "C" IA_ERRORCODE ixheaacd_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx, pVOID pv_value); extern "C" IA_ERRORCODE ia_drc_dec_api(pVOID p_ia_module_obj, WORD32 i_cmd, WORD32 i_idx, pVOID pv_value); extern "C" IA_ERRORCODE ixheaacd_get_config_param(pVOID p_ia_process_api_obj, pWORD32 pi_samp_freq, pWORD32 pi_num_chan, pWORD32 pi_pcm_wd_sz, pWORD32 pi_channel_mask); IA_ERRORCODE Codec::initXAACDecoder(bool isADTS) { /* First part */ /* Error Handler Init */ /* Get Library Name, Library Version and API Version */ /* Initialize API structure + Default config set */ /* Set config params from user */ /* Initialize memory tables */ /* Get memory information and allocate memory */ mInputBufferSize = 0; mInputBuffer = nullptr; mOutputBuffer = nullptr; /* Process struct initing end */ /* ******************************************************************/ /* Initialize API structure and set config params to default */ /* ******************************************************************/ /* API size */ uint32_t pui_api_size; /* Get the API size */ IA_ERRORCODE err_code = ixheaacd_dec_api(nullptr, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size); /* Allocate memory for API */ mXheaacCodecHandle = malloc(pui_api_size); if (!mXheaacCodecHandle) { return IA_FATAL_ERROR; } mMemoryVec.push_back(mXheaacCodecHandle); /* Set the config params to default values */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, nullptr); /* Get the API size */ err_code = ia_drc_dec_api(nullptr, IA_API_CMD_GET_API_SIZE, 0, &pui_api_size); /* Allocate memory for API */ mMpegDDrcHandle = malloc(pui_api_size); if (!mMpegDDrcHandle) { return IA_FATAL_ERROR; } mMemoryVec.push_back(mMpegDDrcHandle); /* Set the config params to default values */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_API_PRE_CONFIG_PARAMS, nullptr); /* ******************************************************************/ /* Set config parameters */ /* ******************************************************************/ uint32_t ui_mp4_flag = isADTS ? 0 : 1; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_ISMP4, &ui_mp4_flag); /* ******************************************************************/ /* Initialize Memory info tables */ /* ******************************************************************/ uint32_t ui_proc_mem_tabs_size; pVOID pv_alloc_ptr; /* Get memory info tables size */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEMTABS_SIZE, 0, &ui_proc_mem_tabs_size); pv_alloc_ptr = malloc(ui_proc_mem_tabs_size); if (!pv_alloc_ptr) { return IA_FATAL_ERROR; } mMemoryVec.push_back(pv_alloc_ptr); /* Set pointer for process memory tables */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEMTABS_PTR, 0, pv_alloc_ptr); /* initialize the API, post config, fill memory tables */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, nullptr); /* ******************************************************************/ /* Allocate Memory with info from library */ /* ******************************************************************/ /* There are four different types of memories, that needs to be allocated */ /* persistent,scratch,input and output */ for (int i = 0; i < 4; i++) { int ui_size = 0, ui_alignment = 0, ui_type = 0; /* Get memory size */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size); /* Get memory alignment */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment); /* Get memory type */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type); pv_alloc_ptr = NULL; ui_alignment = (ui_alignment + sizeof(void *) - 1) / sizeof(void *); ui_alignment = ui_alignment * sizeof(void *); if (0 != posix_memalign(&pv_alloc_ptr, ui_alignment, ui_size)) { return IA_FATAL_ERROR; } if (!pv_alloc_ptr) { return IA_FATAL_ERROR; } mMemoryVec.push_back(pv_alloc_ptr); /* Set the buffer pointer */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr); if (ui_type == IA_MEMTYPE_INPUT) { mInputBuffer = (pWORD8)pv_alloc_ptr; mInputBufferSize = ui_size; } if (ui_type == IA_MEMTYPE_OUTPUT) mOutputBuffer = (pWORD8)pv_alloc_ptr; } /* End first part */ return IA_NO_ERROR; } enum { DRC_TARGET_LEVEL_OFFSET = 6, DRC_ATTENUATION_OFFSET, DRC_BOOST_OFFSET, DRC_COMPRESS_OFFSET, DRC_EFFECT_OFFSET }; IA_ERRORCODE Codec::initXAACDrc(const uint8_t* data, size_t size) { IA_ERRORCODE err_code = IA_NO_ERROR; unsigned int ui_drc_val; // DRC_PRES_MODE_WRAP_DESIRED_TARGET size_t targetLevelOffset = std::min((size_t)DRC_TARGET_LEVEL_OFFSET, size - 1); int32_t targetRefLevel = data[targetLevelOffset]; ui_drc_val = (unsigned int)targetRefLevel; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL, &ui_drc_val); /* Use ui_drc_val from PROP_DRC_OVERRIDE_REF_LEVEL or * DRC_DEFAULT_MOBILE_REF_LEVEL * for IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS too */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS, &ui_drc_val); size_t attenuationOffset = std::min((size_t)DRC_ATTENUATION_OFFSET, size - 1); int32_t attenuationFactor = data[attenuationOffset]; ui_drc_val = (unsigned int)attenuationFactor; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT, &ui_drc_val); // DRC_PRES_MODE_WRAP_DESIRED_BOOST_FACTOR size_t boostOffset = std::min((size_t)DRC_BOOST_OFFSET, size - 1); int32_t boostFactor = data[boostOffset]; ui_drc_val = (unsigned int)boostFactor; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST, &ui_drc_val); // DRC_PRES_MODE_WRAP_DESIRED_HEAVY size_t compressOffset = std::min((size_t)DRC_COMPRESS_OFFSET, size - 1); int32_t compressMode = data[compressOffset]; ui_drc_val = (unsigned int)compressMode; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP, &ui_drc_val); // AAC_UNIDRC_SET_EFFECT size_t effectOffset = std::min((size_t)DRC_EFFECT_OFFSET, size - 1); int32_t effectType = data[effectOffset]; ui_drc_val = (unsigned int)effectType; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &ui_drc_val); return IA_NO_ERROR; } IA_ERRORCODE Codec::deInitXAACDecoder() { /* Error code */ IA_ERRORCODE err_code = IA_NO_ERROR; if (mXheaacCodecHandle) { /* Tell that the input is over in this buffer */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INPUT_OVER, 0, nullptr); } /* Irrespective of error returned in IA_API_CMD_INPUT_OVER, free allocated * memory */ for (void* buf : mMemoryVec) { if (buf) free(buf); } mMemoryVec.clear(); mXheaacCodecHandle = nullptr; return err_code; } IA_ERRORCODE Codec::deInitMPEGDDDrc() { for (void* buf : mDrcMemoryVec) { if (buf) free(buf); } mDrcMemoryVec.clear(); return IA_NO_ERROR; } IA_ERRORCODE Codec::configXAACDecoder(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed) { if (mInputBufferSize < inBufferLength) { inBufferLength = mInputBufferSize; } /* Copy the buffer passed by Android plugin to codec input buffer */ memcpy(mInputBuffer, inBuffer, inBufferLength); /* Set number of bytes to be processed */ IA_ERRORCODE err_code = ixheaacd_dec_api( mXheaacCodecHandle, IA_API_CMD_SET_INPUT_BYTES, 0, &inBufferLength); if (mIsCodecConfigFlushRequired) { /* If codec is already initialized, then GA header is passed again */ /* Need to call the Flush API instead of INIT_PROCESS */ mIsCodecInitialized = false; /* Codec needs to be Reinitialized after flush */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_GA_HDR, nullptr); } else { /* Initialize the process */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_PROCESS, nullptr); } uint32_t ui_init_done; /* Checking for end of initialization */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_DONE_QUERY, &ui_init_done); /* How much buffer is used in input buffers */ err_code = ixheaacd_dec_api( mXheaacCodecHandle, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, bytesConsumed); if (ui_init_done) { err_code = getXAACStreamInfo(); mIsCodecInitialized = true; err_code = configMPEGDDrc(); } return IA_NO_ERROR; } IA_ERRORCODE Codec::initMPEGDDDrc() { IA_ERRORCODE err_code = IA_NO_ERROR; for (int i = 0; i < (WORD32)2; i++) { WORD32 ui_size, ui_alignment, ui_type; pVOID pv_alloc_ptr; /* Get memory size */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_SIZE, i, &ui_size); /* Get memory alignment */ err_code = ia_drc_dec_api( mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_ALIGNMENT, i, &ui_alignment); /* Get memory type */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEM_INFO_TYPE, i, &ui_type); pv_alloc_ptr = malloc(ui_size); if (pv_alloc_ptr == nullptr) { return IA_FATAL_ERROR; } mDrcMemoryVec.push_back(pv_alloc_ptr); /* Set the buffer pointer */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, i, pv_alloc_ptr); } WORD32 ui_size; ui_size = 8192 * 2; mDrcInBuf = (int8_t*)malloc(ui_size); if (mDrcInBuf == nullptr) { return IA_FATAL_ERROR; } mDrcMemoryVec.push_back(mDrcInBuf); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 2, mDrcInBuf); mDrcOutBuf = (int8_t*)malloc(ui_size); if (mDrcOutBuf == nullptr) { return IA_FATAL_ERROR; } mDrcMemoryVec.push_back(mDrcOutBuf); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEM_PTR, 3, mDrcOutBuf); return IA_NO_ERROR; } int Codec::configMPEGDDrc() { IA_ERRORCODE err_code = IA_NO_ERROR; int i_effect_type; int i_loud_norm; int i_target_loudness; unsigned int i_sbr_mode; uint32_t ui_proc_mem_tabs_size = 0; pVOID pv_alloc_ptr = NULL; /* Sampling Frequency */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_SAMP_FREQ, &mSampFreq); /* Total Number of Channels */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels); /* PCM word size */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz); /*Set Effect Type*/ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE, &i_effect_type); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, &i_effect_type); /*Set target loudness */ err_code = ixheaacd_dec_api( mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS, &i_target_loudness); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, &i_target_loudness); /*Set loud_norm_flag*/ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM, &i_loud_norm); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, &i_loud_norm); err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE, &i_sbr_mode); /* Get memory info tables size */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_MEMTABS_SIZE, 0, &ui_proc_mem_tabs_size); pv_alloc_ptr = malloc(ui_proc_mem_tabs_size); if (pv_alloc_ptr == NULL) { return IA_FATAL_ERROR; } memset(pv_alloc_ptr, 0, ui_proc_mem_tabs_size); mMemoryVec.push_back(pv_alloc_ptr); /* Set pointer for process memory tables */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_MEMTABS_PTR, 0, pv_alloc_ptr); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_API_POST_CONFIG_PARAMS, nullptr); /* Free any memory that is allocated for MPEG D Drc so far */ deInitMPEGDDDrc(); err_code = initMPEGDDDrc(); if (err_code != IA_NO_ERROR) { deInitMPEGDDDrc(); return err_code; } /* DRC buffers buf[0] - contains extension element pay load loudness related buf[1] - contains extension element pay load*/ { VOID* p_array[2][16]; WORD32 ii; WORD32 buf_sizes[2][16]; WORD32 num_elements; WORD32 num_config_ext; WORD32 bit_str_fmt = 1; WORD32 uo_num_chan; memset(buf_sizes, 0, 32 * sizeof(WORD32)); err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_BUF_SIZES, &buf_sizes[0][0]); err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_EXT_ELE_PTR, &p_array); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_SET_BUFF_PTR, nullptr); err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_NUM_ELE, &num_elements); err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_NUM_CONFIG_EXT, &num_config_ext); for (ii = 0; ii < num_config_ext; ii++) { /*copy loudness bitstream*/ if (buf_sizes[0][ii] > 0) { memcpy(mDrcInBuf, p_array[0][ii], buf_sizes[0][ii]); /*Set bitstream_split_format */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt); /* Set number of bytes to be processed */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_IL_BS, 0, &buf_sizes[0][ii]); /* Execute process */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_CPY_IL_BSF_BUFF, nullptr); mDRCFlag = 1; } } for (ii = 0; ii < num_elements; ii++) { /*copy config bitstream*/ if (buf_sizes[1][ii] > 0) { memcpy(mDrcInBuf, p_array[1][ii], buf_sizes[1][ii]); /* Set number of bytes to be processed */ /*Set bitstream_split_format */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_IC_BS, 0, &buf_sizes[1][ii]); /* Execute process */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_CPY_IC_BSF_BUFF, nullptr); mDRCFlag = 1; } } if (mDRCFlag == 1) { mMpegDDRCPresent = 1; } else { mMpegDDRCPresent = 0; } /*Read interface buffer config file bitstream*/ if (mMpegDDRCPresent == 1) { WORD32 interface_is_present = 1; if (i_sbr_mode != 0) { if (i_sbr_mode == 1) { mOutputFrameLength = 2048; } else if (i_sbr_mode == 3) { mOutputFrameLength = 4096; } else { mOutputFrameLength = 1024; } } else { mOutputFrameLength = 4096; } err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_FRAME_SIZE, (WORD32*)&mOutputFrameLength); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_INT_PRESENT, &interface_is_present); /* Execute process */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_CPY_IN_BSF_BUFF, nullptr); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_PROCESS, nullptr); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_NUM_CHANNELS, &uo_num_chan); } } return err_code; } IA_ERRORCODE Codec::initDecoder(const uint8_t* data, size_t size, bool isADTS) { IA_ERRORCODE err_code = IA_NO_ERROR; err_code = initXAACDecoder(isADTS); if (err_code != IA_NO_ERROR) { /* Call deInit to free any allocated memory */ deInitXAACDecoder(); return IA_FATAL_ERROR; } err_code = initXAACDrc(data, size); return IA_NO_ERROR; } IA_ERRORCODE Codec::decodeXAACStream(uint8_t* inBuffer, uint32_t inBufferLength, int32_t* bytesConsumed, int32_t* outBytes) { if (mInputBufferSize < inBufferLength) { inBufferLength = mInputBufferSize; } /* If codec is not initialized, call configXAACDecoder decoder again */ if (!mIsCodecInitialized) { configXAACDecoder(inBuffer, inBufferLength, bytesConsumed); } /* Copy the buffer passed by Android plugin to codec input buffer */ memcpy(mInputBuffer, inBuffer, inBufferLength); /* Set number of bytes to be processed */ IA_ERRORCODE err_code = ixheaacd_dec_api( mXheaacCodecHandle, IA_API_CMD_SET_INPUT_BYTES, 0, &inBufferLength); /* Execute process */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, nullptr); /* Checking for end of processing */ uint32_t ui_exec_done; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DONE_QUERY, &ui_exec_done); if (ui_exec_done != 1) { VOID* p_array; // ITTIAM:buffer to handle gain payload WORD32 buf_size = 0; // ITTIAM:gain payload length WORD32 bit_str_fmt = 1; WORD32 gain_stream_flag = 1; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_LEN, &buf_size); err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_GAIN_PAYLOAD_BUF, &p_array); if (buf_size > 0) { /*Set bitstream_split_format */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_PARAM_BITS_FORMAT, &bit_str_fmt); memcpy(mDrcInBuf, p_array, buf_size); /* Set number of bytes to be processed */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES_BS, 0, &buf_size); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_GAIN_STREAM_FLAG, &gain_stream_flag); /* Execute process */ err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_INIT, IA_CMD_TYPE_INIT_CPY_BSF_BUFF, nullptr); mMpegDDRCPresent = 1; } } /* How much buffer is used in input buffers */ err_code = ixheaacd_dec_api( mXheaacCodecHandle, IA_API_CMD_GET_CURIDX_INPUT_BUF, 0, bytesConsumed); /* Get the output bytes */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_OUTPUT_BYTES, 0, outBytes); if (mMpegDDRCPresent == 1) { memcpy(mDrcInBuf, mOutputBuffer, *outBytes); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_INPUT_BYTES, 0, outBytes); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_EXECUTE, IA_CMD_TYPE_DO_EXECUTE, nullptr); memcpy(mOutputBuffer, mDrcOutBuf, *outBytes); } return IA_NO_ERROR; } IA_ERRORCODE Codec::getXAACStreamInfo() { IA_ERRORCODE err_code = IA_NO_ERROR; /* Sampling frequency */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_SAMP_FREQ, &mSampFreq); /* Total Number of Channels */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_NUM_CHANNELS, &mNumChannels); if (mNumChannels > MAX_CHANNEL_COUNT) { return IA_FATAL_ERROR; } /* PCM word size */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_PCM_WDSZ, &mPcmWdSz); if ((mPcmWdSz / 8) != 2) { return IA_FATAL_ERROR; } /* channel mask to tell the arrangement of channels in bit stream */ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MASK, &mChannelMask); /* Channel mode to tell MONO/STEREO/DUAL-MONO/NONE_OF_THESE */ uint32_t ui_channel_mode; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_CHANNEL_MODE, &ui_channel_mode); /* Channel mode to tell SBR PRESENT/NOT_PRESENT */ uint32_t ui_sbr_mode; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_SBR_MODE, &ui_sbr_mode); /* mOutputFrameLength = 1024 * (1 + SBR_MODE) for AAC */ /* For USAC it could be 1024 * 3 , support to query */ /* not yet added in codec */ mOutputFrameLength = 1024 * (1 + ui_sbr_mode); return IA_NO_ERROR; } IA_ERRORCODE Codec::setXAACDRCInfo(int32_t drcCut, int32_t drcBoost, int32_t drcRefLevel, int32_t drcHeavyCompression, int32_t drEffectType) { IA_ERRORCODE err_code = IA_NO_ERROR; int32_t ui_drc_enable = 1; err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_ENABLE, &ui_drc_enable); if (drcCut != -1) { err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_CUT, &drcCut); } if (drcBoost != -1) { err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_BOOST, &drcBoost); } if (drcRefLevel != -1) { err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LEVEL, &drcRefLevel); } if (drcRefLevel != -1) { err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_DRC_TARGET_LOUDNESS, &drcRefLevel); } if (drcHeavyCompression != -1) { err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_HEAVY_COMP, &drcHeavyCompression); } err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_DRC_EFFECT_TYPE, &drEffectType); int32_t i_effect_type, i_target_loudness, i_loud_norm; /*Set Effect Type*/ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_EFFECT_TYPE, &i_effect_type); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_DRC_EFFECT_TYPE, &i_effect_type); /*Set target loudness */ err_code = ixheaacd_dec_api( mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_TARGET_LOUDNESS, &i_target_loudness); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_DRC_TARGET_LOUDNESS, &i_target_loudness); /*Set loud_norm_flag*/ err_code = ixheaacd_dec_api(mXheaacCodecHandle, IA_API_CMD_GET_CONFIG_PARAM, IA_ENHAACPLUS_DEC_CONFIG_PARAM_DRC_LOUD_NORM, &i_loud_norm); err_code = ia_drc_dec_api(mMpegDDrcHandle, IA_API_CMD_SET_CONFIG_PARAM, IA_DRC_DEC_CONFIG_DRC_LOUD_NORM, &i_loud_norm); return IA_NO_ERROR; } extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { int status; int num_proc_iterations = 0; if (size < 1) return 0; Codec* codec = new Codec(); bool isADTS = false; if (size >= 2) { if ((data[0] == 0xFF) && ((data[1] & 0xF0) == 0xF0)) { isADTS = true; } } status = codec->initDecoder(data, size, isADTS); if (0 == status) { int32_t bytesConsumed = 0; status = codec->configXAACDecoder((uint8_t*)data, size, &bytesConsumed); while ((int32_t)size > bytesConsumed) { int32_t numOutBytes; size -= bytesConsumed; data += bytesConsumed; status = codec->decodeXAACStream((uint8_t*)data, size, &bytesConsumed, &numOutBytes); num_proc_iterations++; /* Stop processing after 500 frames */ if (num_proc_iterations > 500) break; /* If decoder doesn't consume any bytes, advance by 4 bytes */ if (0 == bytesConsumed) bytesConsumed = 4; } } status = codec->deInitXAACDecoder(); status = codec->deInitMPEGDDDrc(); delete codec; return 0; }