| /****************************************************************************** |
| * |
| * Copyright (C) 2020 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 <string> |
| #include "aacenc_lib.h" |
| #include "src/aacenc.h" |
| |
| using namespace std; |
| |
| // IN_AUDIO_DATA, IN_ANCILLRY_DATA and IN_METADATA_SETUP |
| constexpr size_t kMaxBuffers = 3; |
| |
| constexpr size_t kMaxOutputBufferSize = 8192; |
| |
| constexpr uint32_t kMinBitRate = 8000; |
| constexpr uint32_t kMaxBitRate = 960000; |
| |
| constexpr int32_t kSampleRates[] = {8000, 11025, 12000, 16000, 22050, 24000, |
| 32000, 44100, 48000, 64000, 88200, 96000}; |
| constexpr size_t kSampleRatesSize = size(kSampleRates); |
| |
| constexpr CHANNEL_MODE kChannelModes[] = {MODE_1, |
| MODE_2, |
| MODE_1_2, |
| MODE_1_2_1, |
| MODE_1_2_2, |
| MODE_1_2_2_1, |
| MODE_1_2_2_2_1, |
| MODE_6_1, |
| MODE_7_1_BACK, |
| MODE_7_1_TOP_FRONT, |
| MODE_7_1_REAR_SURROUND, |
| MODE_7_1_FRONT_CENTER, |
| MODE_212}; |
| constexpr size_t kChannelModesSize = size(kChannelModes); |
| |
| constexpr TRANSPORT_TYPE kIdentifiers[] = { |
| TT_MP4_RAW, TT_MP4_ADIF, TT_MP4_ADTS, TT_MP4_LATM_MCP1, TT_MP4_LATM_MCP0, TT_MP4_LOAS, TT_DRM}; |
| constexpr size_t kIdentifiersSize = size(kIdentifiers); |
| |
| constexpr AUDIO_OBJECT_TYPE kAudioObjectTypes[] = {AOT_NONE, AOT_NULL_OBJECT, |
| AOT_AAC_MAIN, AOT_AAC_LC, |
| AOT_AAC_SSR, AOT_AAC_LTP, |
| AOT_SBR, AOT_AAC_SCAL, |
| AOT_TWIN_VQ, AOT_CELP, |
| AOT_HVXC, AOT_RSVD_10, |
| AOT_RSVD_11, AOT_TTSI, |
| AOT_MAIN_SYNTH, AOT_WAV_TAB_SYNTH, |
| AOT_GEN_MIDI, AOT_ALG_SYNTH_AUD_FX, |
| AOT_ER_AAC_LC, AOT_RSVD_18, |
| AOT_ER_AAC_LTP, AOT_ER_AAC_SCAL, |
| AOT_ER_TWIN_VQ, AOT_ER_BSAC, |
| AOT_ER_AAC_LD, AOT_ER_CELP, |
| AOT_ER_HVXC, AOT_ER_HILN, |
| AOT_ER_PARA, AOT_RSVD_28, |
| AOT_PS, AOT_MPEGS, |
| AOT_ESCAPE, AOT_MP3ONMP4_L1, |
| AOT_MP3ONMP4_L2, AOT_MP3ONMP4_L3, |
| AOT_RSVD_35, AOT_RSVD_36, |
| AOT_AAC_SLS, AOT_SLS, |
| AOT_ER_AAC_ELD, AOT_USAC, |
| AOT_SAOC, AOT_LD_MPEGS, |
| AOT_MP2_AAC_LC, AOT_MP2_SBR, |
| AOT_DRM_AAC, AOT_DRM_SBR, |
| AOT_DRM_MPEG_PS, AOT_DRM_SURROUND, |
| AOT_DRM_USAC}; |
| |
| constexpr size_t kAudioObjectTypesSize = size(kAudioObjectTypes); |
| |
| constexpr int32_t kSbrRatios[] = {-1, 0, 1, 2}; |
| constexpr size_t kSbrRatiosSize = size(kSbrRatios); |
| |
| constexpr int32_t kBitRateModes[] = { |
| AACENC_BR_MODE_INVALID, AACENC_BR_MODE_CBR, AACENC_BR_MODE_VBR_1, |
| AACENC_BR_MODE_VBR_2, AACENC_BR_MODE_VBR_3, AACENC_BR_MODE_VBR_4, |
| AACENC_BR_MODE_VBR_5, AACENC_BR_MODE_FF, AACENC_BR_MODE_SFR}; |
| constexpr size_t kBitRateModesSize = size(kBitRateModes); |
| |
| constexpr int32_t kGranuleLengths[] = {120, 128, 240, 256, 480, 512, 1024}; |
| constexpr size_t kGranuleLengthsSize = size(kGranuleLengths); |
| |
| constexpr int32_t kChannelOrder[] = {CH_ORDER_MPEG, CH_ORDER_WAV}; |
| constexpr size_t kChannelOrderSize = size(kChannelOrder); |
| |
| constexpr int32_t kSignalingModes[] = {-1, 0, 1, 2, 3}; |
| constexpr size_t kSignalingModesSize = size(kSignalingModes); |
| |
| constexpr int32_t kAudioMuxVer[] = {-1, 0, 1, 2}; |
| constexpr size_t kAudioMuxVerSize = size(kAudioMuxVer); |
| |
| constexpr int32_t kSbrModes[] = {-1, 0, 1, 2}; |
| constexpr size_t kSbrModesSize = size(kSbrModes); |
| |
| constexpr AACENC_METADATA_DRC_PROFILE kMetaDataDrcProfiles[] = { |
| AACENC_METADATA_DRC_NONE, AACENC_METADATA_DRC_FILMSTANDARD, |
| AACENC_METADATA_DRC_FILMLIGHT, AACENC_METADATA_DRC_MUSICSTANDARD, |
| AACENC_METADATA_DRC_MUSICLIGHT, AACENC_METADATA_DRC_SPEECH, |
| AACENC_METADATA_DRC_NOT_PRESENT}; |
| constexpr size_t kMetaDataDrcProfilesSize = size(kMetaDataDrcProfiles); |
| |
| enum { |
| IDX_SBR_MODE = 0, |
| IDX_AAC_AOT, |
| IDX_SAMPLE_RATE, |
| IDX_BIT_RATE_1, |
| IDX_BIT_RATE_2, |
| IDX_BIT_RATE_3, |
| IDX_CHANNEL, |
| IDX_IDENTIFIER, |
| IDX_SBR_RATIO, |
| IDX_METADATA_DRC_PROFILE, |
| IDX_METADATA_COMP_PROFILE, |
| IDX_METADATA_DRC_TARGET_REF_LEVEL, |
| IDX_METADATA_COMP_TARGET_REF_LEVEL, |
| IDX_METADATA_PROG_LEVEL_PRESENT, |
| IDX_METADATA_PROG_LEVEL, |
| IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT, |
| IDX_METADATA_ETSI_DMXLVL_PRESENT, |
| IDX_METADATA_CENTER_MIX_LEVEL, |
| IDX_METADATA_SURROUND_MIX_LEVEL, |
| IDX_METADATA_DOLBY_SURROUND_MODE, |
| IDX_METADATA_DRC_PRESENTATION_MODE, |
| IDX_METADATA_EXT_ANC_DATA_ENABLE, |
| IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE, |
| IDX_METADATA_EXT_DOWNMIX_LEVEL_A, |
| IDX_METADATA_EXT_DOWNMIX_LEVEL_B, |
| IDX_METADATA_DMX_GAIN_ENABLE, |
| IDX_METADATA_DMX_GAIN_5, |
| IDX_METADATA_DMX_GAIN_2, |
| IDX_METADATA_LFE_DMX_ENABLE, |
| IDX_METADATA_LFE_DMX_LEVEL, |
| IDX_IN_BUFFER_INDEX_1, |
| IDX_IN_BUFFER_INDEX_2, |
| IDX_IN_BUFFER_INDEX_3, |
| IDX_BIT_RATE_MODE, |
| IDX_GRANULE_LENGTH, |
| IDX_CHANNELORDER, |
| IDX_AFTERBURNER, |
| IDX_BANDWIDTH, |
| IDX_PEAK_BITRATE, |
| IDX_HEADER_PERIOD, |
| IDX_SIGNALING_MODE, |
| IDX_TPSUBFRAMES, |
| IDX_AUDIOMUXVER, |
| IDX_PROTECTION, |
| IDX_ANCILLARY_BITRATE, |
| IDX_METADATA_MODE, |
| IDX_LAST |
| }; |
| |
| template <typename type1, typename type2, typename type3> |
| auto generateNumberInRangeFromData(type1 data, type2 min, type3 max) -> decltype(max) { |
| return (data % (1 + max - min)) + min; |
| } |
| |
| class Codec { |
| public: |
| ~Codec() { deInitEncoder(); } |
| bool initEncoder(uint8_t **dataPtr, size_t *sizePtr); |
| void encodeFrames(const uint8_t *data, size_t size); |
| void deInitEncoder(); |
| |
| private: |
| template <typename type1, typename type2, typename type3> |
| void setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max, |
| const type3 *array = nullptr); |
| void setupMetaData(uint8_t *data); |
| |
| HANDLE_AACENCODER mEncoder = nullptr; |
| AACENC_MetaData mMetaData = {}; |
| uint32_t mInBufferIdx_1 = 0; |
| uint32_t mInBufferIdx_2 = 0; |
| uint32_t mInBufferIdx_3 = 0; |
| }; |
| |
| void Codec::setupMetaData(uint8_t *data) { |
| uint32_t drcProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_DRC_PROFILE], 0, |
| kMetaDataDrcProfilesSize - 1); |
| AACENC_METADATA_DRC_PROFILE drcProfile = kMetaDataDrcProfiles[drcProfileIndex]; |
| mMetaData.drc_profile = drcProfile; |
| |
| uint32_t compProfileIndex = generateNumberInRangeFromData(data[IDX_METADATA_COMP_PROFILE], 0, |
| kMetaDataDrcProfilesSize - 1); |
| AACENC_METADATA_DRC_PROFILE compProfile = kMetaDataDrcProfiles[compProfileIndex]; |
| mMetaData.comp_profile = compProfile; |
| |
| INT drcTargetRefLevel = |
| generateNumberInRangeFromData(data[IDX_METADATA_DRC_TARGET_REF_LEVEL], 0, UINT8_MAX); |
| mMetaData.drc_TargetRefLevel = drcTargetRefLevel; |
| |
| INT compTargetRefLevel = |
| generateNumberInRangeFromData(data[IDX_METADATA_COMP_TARGET_REF_LEVEL], 0, UINT8_MAX); |
| mMetaData.comp_TargetRefLevel = compTargetRefLevel; |
| |
| INT isProgRefLevelPresent = |
| generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL_PRESENT], 0, 1); |
| mMetaData.prog_ref_level_present = isProgRefLevelPresent; |
| |
| INT progRefLevel = generateNumberInRangeFromData(data[IDX_METADATA_PROG_LEVEL], 0, UINT8_MAX); |
| mMetaData.prog_ref_level = progRefLevel; |
| |
| UCHAR isPCEMixdownIdxPresent = |
| generateNumberInRangeFromData(data[IDX_METADATA_PCE_MIXDOWN_IDX_PRESENT], 0, 1); |
| mMetaData.PCE_mixdown_idx_present = isPCEMixdownIdxPresent; |
| |
| UCHAR isETSIDmxLvlPresent = |
| generateNumberInRangeFromData(data[IDX_METADATA_ETSI_DMXLVL_PRESENT], 0, 1); |
| mMetaData.ETSI_DmxLvl_present = isETSIDmxLvlPresent; |
| |
| SCHAR centerMixLevel = generateNumberInRangeFromData(data[IDX_METADATA_CENTER_MIX_LEVEL], 0, 7); |
| mMetaData.centerMixLevel = centerMixLevel; |
| |
| SCHAR surroundMixLevel = |
| generateNumberInRangeFromData(data[IDX_METADATA_SURROUND_MIX_LEVEL], 0, 7); |
| mMetaData.surroundMixLevel = surroundMixLevel; |
| |
| UCHAR dolbySurroundMode = |
| generateNumberInRangeFromData(data[IDX_METADATA_DOLBY_SURROUND_MODE], 0, 2); |
| mMetaData.dolbySurroundMode = dolbySurroundMode; |
| |
| UCHAR drcPresentationMode = |
| generateNumberInRangeFromData(data[IDX_METADATA_DRC_PRESENTATION_MODE], 0, 2); |
| mMetaData.drcPresentationMode = drcPresentationMode; |
| |
| UCHAR extAncDataEnable = |
| generateNumberInRangeFromData(data[IDX_METADATA_EXT_ANC_DATA_ENABLE], 0, 1); |
| mMetaData.ExtMetaData.extAncDataEnable = extAncDataEnable; |
| |
| UCHAR extDownmixLevelEnable = |
| generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_ENABLE], 0, 1); |
| mMetaData.ExtMetaData.extDownmixLevelEnable = extDownmixLevelEnable; |
| |
| UCHAR extDownmixLevel_A = |
| generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_A], 0, 7); |
| mMetaData.ExtMetaData.extDownmixLevel_A = extDownmixLevel_A; |
| |
| UCHAR extDownmixLevel_B = |
| generateNumberInRangeFromData(data[IDX_METADATA_EXT_DOWNMIX_LEVEL_B], 0, 7); |
| mMetaData.ExtMetaData.extDownmixLevel_B = extDownmixLevel_B; |
| |
| UCHAR dmxGainEnable = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_ENABLE], 0, 1); |
| mMetaData.ExtMetaData.dmxGainEnable = dmxGainEnable; |
| |
| INT dmxGain5 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_5], 0, UINT8_MAX); |
| mMetaData.ExtMetaData.dmxGain5 = dmxGain5; |
| |
| INT dmxGain2 = generateNumberInRangeFromData(data[IDX_METADATA_DMX_GAIN_2], 0, UINT8_MAX); |
| mMetaData.ExtMetaData.dmxGain2 = dmxGain2; |
| |
| UCHAR lfeDmxEnable = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_ENABLE], 0, 1); |
| mMetaData.ExtMetaData.lfeDmxEnable = lfeDmxEnable; |
| |
| UCHAR lfeDmxLevel = generateNumberInRangeFromData(data[IDX_METADATA_LFE_DMX_LEVEL], 0, 15); |
| mMetaData.ExtMetaData.lfeDmxLevel = lfeDmxLevel; |
| } |
| |
| template <typename type1, typename type2, typename type3> |
| void Codec::setAACParam(type1 data, const AACENC_PARAM aacParam, type2 min, type2 max, |
| const type3 *array) { |
| auto value = 0; |
| if (array) { |
| uint32_t index = generateNumberInRangeFromData(data, min, max); |
| value = array[index]; |
| } else { |
| value = generateNumberInRangeFromData(data, min, max); |
| } |
| aacEncoder_SetParam(mEncoder, aacParam, value); |
| (void)aacEncoder_GetParam(mEncoder, aacParam); |
| } |
| |
| bool Codec::initEncoder(uint8_t **dataPtr, size_t *sizePtr) { |
| uint8_t *data = *dataPtr; |
| |
| if (AACENC_OK != aacEncOpen(&mEncoder, 0, 0)) { |
| return false; |
| } |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_SBR_MODE], AACENC_SBR_MODE, 0, kSbrModesSize - 1, |
| kSbrModes); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_SBR_RATIO], AACENC_SBR_RATIO, 0, |
| kSbrRatiosSize - 1, kSbrRatios); |
| |
| setAACParam<uint8_t, size_t, AUDIO_OBJECT_TYPE>(data[IDX_AAC_AOT], AACENC_AOT, 0, |
| kAudioObjectTypesSize - 1, kAudioObjectTypes); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_SAMPLE_RATE], AACENC_SAMPLERATE, 0, |
| kSampleRatesSize - 1, kSampleRates); |
| |
| uint32_t tempValue = |
| (data[IDX_BIT_RATE_1] << 16) | (data[IDX_BIT_RATE_2] << 8) | data[IDX_BIT_RATE_3]; |
| setAACParam<uint8_t, uint32_t, uint32_t>(tempValue, AACENC_BITRATE, kMinBitRate, kMaxBitRate); |
| |
| setAACParam<uint8_t, size_t, CHANNEL_MODE>(data[IDX_CHANNEL], AACENC_CHANNELMODE, 0, |
| kChannelModesSize - 1, kChannelModes); |
| |
| setAACParam<uint8_t, size_t, TRANSPORT_TYPE>(data[IDX_IDENTIFIER], AACENC_TRANSMUX, 0, |
| kIdentifiersSize - 1, kIdentifiers); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_BIT_RATE_MODE], AACENC_BITRATEMODE, 0, |
| kBitRateModesSize - 1, kBitRateModes); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_GRANULE_LENGTH], AACENC_GRANULE_LENGTH, 0, |
| kGranuleLengthsSize - 1, kGranuleLengths); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_CHANNELORDER], AACENC_CHANNELORDER, 0, |
| kChannelOrderSize - 1, kChannelOrder); |
| |
| setAACParam<uint8_t, int32_t, int32_t>(data[IDX_AFTERBURNER], AACENC_AFTERBURNER, 0, 1); |
| |
| setAACParam<uint8_t, int32_t, int32_t>(data[IDX_BANDWIDTH], AACENC_BANDWIDTH, 0, 1); |
| |
| setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_PEAK_BITRATE], AACENC_PEAK_BITRATE, |
| kMinBitRate, kMinBitRate); |
| |
| setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_HEADER_PERIOD], AACENC_HEADER_PERIOD, 0, |
| UINT8_MAX); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_SIGNALING_MODE], AACENC_SIGNALING_MODE, 0, |
| kSignalingModesSize - 1, kSignalingModes); |
| |
| setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_TPSUBFRAMES], AACENC_TPSUBFRAMES, 0, |
| UINT8_MAX); |
| |
| setAACParam<uint8_t, size_t, int32_t>(data[IDX_AUDIOMUXVER], AACENC_AUDIOMUXVER, 0, |
| kAudioMuxVerSize - 1, kAudioMuxVer); |
| |
| setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_PROTECTION], AACENC_PROTECTION, 0, 1); |
| |
| setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_ANCILLARY_BITRATE], AACENC_ANCILLARY_BITRATE, |
| 0, kMaxBitRate); |
| |
| setAACParam<uint8_t, uint32_t, uint32_t>(data[IDX_METADATA_MODE], AACENC_METADATA_MODE, 0, 3); |
| |
| AACENC_InfoStruct encInfo; |
| aacEncInfo(mEncoder, &encInfo); |
| |
| mInBufferIdx_1 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_1], 0, kMaxBuffers - 1); |
| mInBufferIdx_2 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_2], 0, kMaxBuffers - 1); |
| mInBufferIdx_3 = generateNumberInRangeFromData(data[IDX_IN_BUFFER_INDEX_3], 0, kMaxBuffers - 1); |
| |
| setupMetaData(data); |
| |
| // Not re-using the data which was used for configuration for encoding |
| *dataPtr += IDX_LAST; |
| *sizePtr -= IDX_LAST; |
| |
| return true; |
| } |
| |
| static void deleteBuffers(uint8_t **buffers, size_t size) { |
| for (size_t n = 0; n < size; ++n) { |
| delete[] buffers[n]; |
| } |
| delete[] buffers; |
| } |
| |
| void Codec::encodeFrames(const uint8_t *data, size_t size) { |
| uint8_t *audioData = (uint8_t *)data; |
| uint8_t *ancData = (uint8_t *)data; |
| size_t audioSize = size; |
| size_t ancSize = size; |
| |
| while ((audioSize > 0) && (ancSize > 0)) { |
| AACENC_InArgs inargs; |
| memset(&inargs, 0, sizeof(inargs)); |
| inargs.numInSamples = audioSize / sizeof(int16_t); |
| inargs.numAncBytes = ancSize; |
| |
| void *buffers[] = {(void *)audioData, (void *)ancData, &mMetaData}; |
| INT bufferIds[] = {IN_AUDIO_DATA, IN_ANCILLRY_DATA, IN_METADATA_SETUP}; |
| INT bufferSizes[] = {static_cast<INT>(audioSize), static_cast<INT>(ancSize), |
| static_cast<INT>(sizeof(mMetaData))}; |
| INT bufferElSizes[] = {sizeof(int16_t), sizeof(UCHAR), sizeof(AACENC_MetaData)}; |
| |
| void *inBuffer[kMaxBuffers] = {}; |
| INT inBufferIds[kMaxBuffers] = {}; |
| INT inBufferSize[kMaxBuffers] = {}; |
| INT inBufferElSize[kMaxBuffers] = {}; |
| for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { |
| uint32_t Idxs[] = {mInBufferIdx_1, mInBufferIdx_2, mInBufferIdx_3}; |
| inBuffer[buffer] = buffers[Idxs[buffer]]; |
| inBufferIds[buffer] = bufferIds[Idxs[buffer]]; |
| inBufferSize[buffer] = bufferSizes[Idxs[buffer]]; |
| inBufferElSize[buffer] = bufferElSizes[Idxs[buffer]]; |
| } |
| |
| AACENC_BufDesc inBufDesc; |
| inBufDesc.numBufs = kMaxBuffers; |
| inBufDesc.bufs = (void **)&inBuffer; |
| inBufDesc.bufferIdentifiers = inBufferIds; |
| inBufDesc.bufSizes = inBufferSize; |
| inBufDesc.bufElSizes = inBufferElSize; |
| |
| uint8_t **outPtrRef = new uint8_t *[kMaxBuffers]; |
| for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { |
| outPtrRef[buffer] = new uint8_t[kMaxOutputBufferSize]; |
| } |
| |
| void *outBuffer[kMaxBuffers]; |
| INT outBufferIds[kMaxBuffers]; |
| INT outBufferSize[kMaxBuffers]; |
| INT outBufferElSize[kMaxBuffers]; |
| |
| for (int32_t buffer = 0; buffer < kMaxBuffers; ++buffer) { |
| outBuffer[buffer] = outPtrRef[buffer]; |
| outBufferIds[buffer] = OUT_BITSTREAM_DATA; |
| outBufferSize[buffer] = (INT)kMaxOutputBufferSize; |
| outBufferElSize[buffer] = sizeof(UCHAR); |
| } |
| |
| AACENC_BufDesc outBufDesc; |
| outBufDesc.numBufs = kMaxBuffers; |
| outBufDesc.bufs = (void **)&outBuffer; |
| outBufDesc.bufferIdentifiers = outBufferIds; |
| outBufDesc.bufSizes = outBufferSize; |
| outBufDesc.bufElSizes = outBufferElSize; |
| |
| AACENC_OutArgs outargs = {}; |
| aacEncEncode(mEncoder, &inBufDesc, &outBufDesc, &inargs, &outargs); |
| |
| if (outargs.numOutBytes == 0) { |
| if (audioSize > 0) { |
| ++audioData; |
| --audioSize; |
| } |
| if (ancSize > 0) { |
| ++ancData; |
| --ancSize; |
| } |
| } else { |
| size_t audioConsumed = outargs.numInSamples * sizeof(int16_t); |
| audioData += audioConsumed; |
| audioSize -= audioConsumed; |
| |
| size_t ancConsumed = outargs.numAncBytes; |
| ancData += ancConsumed; |
| ancSize -= ancConsumed; |
| } |
| deleteBuffers(outPtrRef, kMaxBuffers); |
| |
| // break out of loop if only metadata was sent in all the input buffers |
| // as sending it multiple times in a loop is redundant. |
| if ((mInBufferIdx_1 == kMaxBuffers - 1) && (mInBufferIdx_2 == kMaxBuffers - 1) && |
| (mInBufferIdx_3 == kMaxBuffers - 1)) { |
| break; |
| } |
| } |
| } |
| |
| void Codec::deInitEncoder() { aacEncClose(&mEncoder); } |
| |
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { |
| if (size < IDX_LAST) { |
| return 0; |
| } |
| Codec encoder; |
| if (encoder.initEncoder(const_cast<uint8_t **>(&data), &size)) { |
| encoder.encodeFrames(data, size); |
| } |
| return 0; |
| } |