diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp new file mode 100644 index 0000000..d2c08fe --- /dev/null +++ b/fuzzer/Android.bp @@ -0,0 +1,11 @@ +cc_fuzz { + name: "xaac_dec_fuzzer", + host_supported: true, + srcs: [ + "xaac_dec_fuzzer.cpp", + ], + static_libs: [ + "libxaacdec", + "liblog", + ], +} diff --git a/fuzzer/README.md b/fuzzer/README.md new file mode 100644 index 0000000..efa9907 --- /dev/null +++ b/fuzzer/README.md @@ -0,0 +1,70 @@ +# Fuzzer for libxaac decoder + +This describes steps to build xaac_dec_fuzzer binary. + +## Linux x86/x64 + +### Requirements +- cmake (3.5 or above) +- make +- clang (6.0 or above) + needs to support -fsanitize=fuzzer, -fsanitize=fuzzer-no-link + +### Steps to build +Clone libxaac repository +``` +$ git clone https://android.googlesource.com/platform/external/libxaac +``` +Create a directory inside libxaac and change directory +``` + $ cd libxaac + $ mkdir build + $ cd build +``` +Build libxaac using cmake +``` + $ CC=clang CXX=clang++ cmake ../ \ + -DSANITIZE=fuzzer-no-link,address,signed-integer-overflow + $ make + ``` +Build the fuzzer +``` + $ clang++ -std=c++11 -fsanitize=fuzzer,address -I. -I../ -I../common \ + -I../decoder -I../decoder/drc_src -Wl,--start-group \ + ../fuzzer/xaac_dec_fuzzer.cpp -o ./xaac_dec_fuzzer ./libxaacdec.a \ + -Wl,--end-group +``` + +### Steps to run +Create a directory CORPUS_DIR and copy some elementary aac files to that folder +To run the fuzzer +``` +$ ./xaac_dec_fuzzer CORPUS_DIR +``` + +## Android + +### Steps to build +Build the fuzzer +``` + $ SANITIZE_TARGET=address SANITIZE_HOST=address mmma -j$(nproc) \ + external/libxaac/fuzzer +``` + +### Steps to run +Create a directory CORPUS_DIR and copy some elementary aac files to that folder +Push this directory to device. + +To run on device +``` + $ adb sync data + $ adb shell /data/fuzz/xaac_dec_fuzzer CORPUS_DIR +``` +To run on host +``` + $ $ANDROID_HOST_OUT/fuzz/xaac_dec_fuzzer CORPUS_DIR +``` + +## References: + * http://llvm.org/docs/LibFuzzer.html + * https://github.com/google/oss-fuzz diff --git a/fuzzer/ossfuzz.sh b/fuzzer/ossfuzz.sh new file mode 100755 index 0000000..aac1654 --- /dev/null +++ b/fuzzer/ossfuzz.sh @@ -0,0 +1,43 @@ +#!/bin/bash -eu +# +# 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. +# +################################################################################ +# Ensure SRC and WORK are set +test "${SRC}" != "" || exit 1 +test "${WORK}" != "" || exit 1 + +# Build libxaac +build_dir=$WORK/build +rm -rf ${build_dir} +mkdir -p ${build_dir} +pushd ${build_dir} + +cmake $SRC/libxaac +make -j$(nproc) +popd + +# build fuzzers +$CXX $CXXFLAGS -std=c++11 \ + -I$SRC/libxaac \ + -I$SRC/libxaac/common \ + -I$SRC/libxaac/decoder \ + -I$SRC/libxaac/decoder/drc_src \ + -I${build_dir} \ + -Wl,--start-group \ + $LIB_FUZZING_ENGINE \ + $SRC/libxaac/fuzzer/xaac_dec_fuzzer.cpp -o $OUT/xaac_dec_fuzzer \ + ${build_dir}/libxaacdec.a \ + -Wl,--end-group + +cp $SRC/libxaac/fuzzer/xaac_dec_fuzzer.dict $OUT/xaacdec_fuzzer.dict diff --git a/fuzzer/xaac_dec_fuzzer.cpp b/fuzzer/xaac_dec_fuzzer.cpp new file mode 100644 index 0000000..6ec2ab1 --- /dev/null +++ b/fuzzer/xaac_dec_fuzzer.cpp @@ -0,0 +1,874 @@ +/****************************************************************************** + * + * 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 "ixheaacd_type_def.h" +#include "ixheaacd_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; + 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); + /* 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; +} diff --git a/fuzzer/xaac_dec_fuzzer.dict b/fuzzer/xaac_dec_fuzzer.dict new file mode 100644 index 0000000..3b00312 --- /dev/null +++ b/fuzzer/xaac_dec_fuzzer.dict @@ -0,0 +1,2 @@ +# Start code (bytes 0-1) +kw1="\xFF\xF0"