Merge remote-tracking branch 'aosp/master'

This commit is contained in:
Martin Storsjo 2021-01-14 15:38:20 +02:00
commit a52114dd69
8 changed files with 574 additions and 46 deletions

View File

@ -32,8 +32,7 @@ cc_library_static {
"signed-integer-overflow", "signed-integer-overflow",
"bounds", "bounds",
], ],
// Enable CFI if this becomes a shared library. cfi: true,
// cfi: true,
}, },
shared_libs: [ shared_libs: [
"liblog", "liblog",
@ -58,6 +57,13 @@ cc_library_static {
darwin: { darwin: {
enabled: false, enabled: false,
}, },
android: {
sanitize: {
diag: {
cfi: true,
},
},
},
}, },
apex_available: [ apex_available: [

View File

@ -18,17 +18,12 @@
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/ */
cc_fuzz { cc_defaults {
name: "aac_dec_fuzzer", name: "aac_fuzz_defaults",
host_supported:true, host_supported: true,
static_libs: [ static_libs: [
"libFraunhoferAAC", "libFraunhoferAAC",
"liblog",
],
srcs: [
"aac_dec_fuzzer.cpp",
], ],
target: { target: {
@ -44,3 +39,31 @@ cc_fuzz {
componentid: 155276, componentid: 155276,
}, },
} }
cc_fuzz {
name: "aac_dec_fuzzer",
srcs: [
"aac_dec_fuzzer.cpp",
],
static_libs: [
"liblog",
],
defaults: [
"aac_fuzz_defaults"
],
}
cc_fuzz {
name: "aac_enc_fuzzer",
srcs: [
"aac_enc_fuzzer.cpp",
],
defaults: [
"aac_fuzz_defaults"
],
}

View File

@ -53,7 +53,85 @@ To run on host
$ $ANDROID_HOST_OUT/fuzz/x86_64/aac_dec_fuzzer/aac_dec_fuzzer CORPUS_DIR $ $ANDROID_HOST_OUT/fuzz/x86_64/aac_dec_fuzzer/aac_dec_fuzzer CORPUS_DIR
``` ```
# Fuzzer for libFraunhoferAAC encoder
## Plugin Design Considerations
The fuzzer plugin for aac encoder is designed based on the understanding of the
codec and tries to achieve the following:
##### Maximize code coverage
The configuration parameters are not hardcoded, but instead selected based on
incoming data. This ensures more code paths are reached by the fuzzer.
Following arguments are passed to aacEncoder_SetParam to set the respective AACENC_PARAM parameter:
| Variable name| AACENC_PARAM param| Valid Values| Configured Value|
|------------- |-------------| ----- |----- |
| `sbrMode` |`AACENC_SBR_MODE` | `AAC_SBR_OFF ` `AAC_SBR_SINGLE_RATE ` `AAC_SBR_DUAL_RATE ` `AAC_SBR_AUTO ` | Calculated using first byte of data |
| `aacAOT` | `AACENC_AOT` |`AOT_AAC_LC ` `AOT_ER_AAC_ELD ` `AOT_SBR ` `AOT_PS ` `AOT_ER_AAC_LD ` | Calculated using second byte of data |
| `sampleRate` |`AACENC_SAMPLERATE` | `8000 ` `11025 ` `12000 ` `16000 ` `22050 ` `24000 ` `32000 ` `44100 ` `48000 `| Calculated using third byte of data |
| `bitRate` |`AACENC_BITRATE` | In range `8000 ` to `960000 ` | Calculated using fourth, fifth and sixth byte of data |
| `channelMode` |`AACENC_CHANNELMODE` | `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_7_1_BACK ` | Calculated using seventh byte of data |
| `identifier` |`AACENC_TRANSMUX` | `TT_MP4_RAW ` `TT_MP4_ADIF ` `TT_MP4_ADTS ` `TT_MP4_LATM_MCP1 ` `TT_MP4_LATM_MCP0 ` `TT_MP4_LOAS ` `TT_DRM ` | Calculated using eight byte of data |
| `sbrRatio` | `AACENC_SBR_RATIO` |`0 ` `1 ` `2 ` | Calculated using ninth byte of data |
Following values are configured to set up the meta data represented by the class variable `mMetaData ` :
| Variable name| Possible Values| Configured Value|
|------------- | ----- |----- |
| `drc_profile` | `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 ` | Calculated using tenth byte of data |
| `comp_profile` | `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 ` | Calculated using eleventh byte of data |
| `drc_TargetRefLevel` | In range `0 ` to `255 ` | Calculated using twelfth byte of data |
| `comp_TargetRefLevel` | In range `0 ` to `255 ` | Calculated using thirteenth byte of data |
| `prog_ref_level_present` | `0 ` `1 ` | Calculated using fourteenth byte of data |
| `prog_ref_level` | In range `0 ` to `255 ` | Calculated using fifteenth byte of data |
| `PCE_mixdown_idx_present` | `0 ` `1 ` | Calculated using sixteenth byte of data |
| `ETSI_DmxLvl_present` | `0 ` `1 ` | Calculated using seventeenth byte of data |
| `centerMixLevel` | In range `0 ` to `7 ` | Calculated using eighteenth byte of data |
| `surroundMixLevel` | In range `0 ` to `7 ` | Calculated using nineteenth byte of data |
| `dolbySurroundMode` | In range `0 ` to `2 ` | Calculated using twentieth byte of data |
| `drcPresentationMode` | In range `0 ` to `2 ` | Calculated using twenty-first byte of data |
| `extAncDataEnable` | `0 ` `1 ` | Calculated using twenty-second byte of data |
| `extDownmixLevelEnable` | `0 ` `1 ` | Calculated using twenty-third byte of data |
| `extDownmixLevel_A` | In range `0 ` to `7 ` | Calculated using twenty-fourth byte of data |
| `extDownmixLevel_B` | In range `0 ` to `7 ` | Calculated using twenty-fifth byte of data |
| `dmxGainEnable` | `0 ` `1 ` | Calculated using twenty-sixth byte of data |
| `dmxGain5` | In range `0 ` to `255 ` | Calculated using twenty-seventh byte of data |
| `dmxGain2` | In range `0 ` to `255 ` | Calculated using twenty-eighth byte of data |
| `lfeDmxEnable` | `0 ` `1 ` | Calculated using twenty-ninth byte of data |
| `lfeDmxLevel` | In range `0 ` to `15 ` | Calculated using thirtieth byte of data |
Indexes `mInBufferIdx_1`, `mInBufferIdx_2` and `mInBufferIdx_3`(in range `0 ` to `2`) are calculated using the thirty-first, thirty-second and thirty-third byte respectively.
##### Maximize utilization of input data
The plugin feeds the entire input data to the codec and continues with the encoding even on a failure. This ensures that the plugin tolerates any kind of input (empty, huge, malformed, etc) and doesnt `exit()` on any input and thereby increasing the chance of identifying vulnerabilities.
## Build
This describes steps to build aac_enc_fuzzer binary.
## Android
### Steps to build
Build the fuzzer
```
$ mm -j$(nproc) aac_enc_fuzzer
```
### Steps to run
Create a directory CORPUS_DIR and copy some raw files to that folder.
Push this directory to device.
To run on device
```
$ adb sync data
$ adb shell /data/fuzz/arm64/aac_enc_fuzzer/aac_enc_fuzzer CORPUS_DIR
```
To run on host
```
$ $ANDROID_HOST_OUT/fuzz/x86_64/aac_enc_fuzzer/aac_enc_fuzzer CORPUS_DIR
```
## References: ## References:
* http://llvm.org/docs/LibFuzzer.html * http://llvm.org/docs/LibFuzzer.html
* https://github.com/google/oss-fuzz * https://github.com/google/oss-fuzz

374
fuzzer/aac_enc_fuzzer.cpp Normal file
View File

@ -0,0 +1,374 @@
/******************************************************************************
*
* 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"
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 uint32_t kSampleRates[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000};
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_7_1_BACK};
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_AAC_LC, AOT_ER_AAC_ELD, AOT_SBR, AOT_PS,
AOT_ER_AAC_LD};
constexpr size_t kAudioObjectTypesSize = size(kAudioObjectTypes);
constexpr int32_t kSbrRatios[] = {0, 1, 2};
constexpr size_t kSbrRatiosSize = size(kSbrRatios);
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_LAST
};
enum aac_sbr_mode_t : uint32_t {
AAC_SBR_OFF,
AAC_SBR_SINGLE_RATE,
AAC_SBR_DUAL_RATE,
AAC_SBR_AUTO
};
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:
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;
}
bool Codec::initEncoder(uint8_t **dataPtr, size_t *sizePtr) {
uint8_t *data = *dataPtr;
if (AACENC_OK != aacEncOpen(&mEncoder, 0, 0)) {
return false;
}
uint32_t sbrMode = generateNumberInRangeFromData(data[IDX_SBR_MODE], (uint32_t)AAC_SBR_OFF,
(uint32_t)AAC_SBR_AUTO);
aacEncoder_SetParam(mEncoder, AACENC_SBR_MODE, sbrMode);
uint32_t sbrRatioIndex =
generateNumberInRangeFromData(data[IDX_SBR_RATIO], 0, kSbrRatiosSize - 1);
int32_t sbrRatio = kSbrRatios[sbrRatioIndex];
aacEncoder_SetParam(mEncoder, AACENC_SBR_RATIO, sbrRatio);
uint32_t aacAOTIndex =
generateNumberInRangeFromData(data[IDX_AAC_AOT], 0, kAudioObjectTypesSize - 1);
uint32_t aacAOT = kAudioObjectTypes[aacAOTIndex];
aacEncoder_SetParam(mEncoder, AACENC_AOT, aacAOT);
uint32_t sampleRateIndex =
generateNumberInRangeFromData(data[IDX_SAMPLE_RATE], 0, kSampleRatesSize - 1);
uint32_t sampleRate = kSampleRates[sampleRateIndex];
aacEncoder_SetParam(mEncoder, AACENC_SAMPLERATE, sampleRate);
uint32_t tempValue =
(data[IDX_BIT_RATE_1] << 16) | (data[IDX_BIT_RATE_2] << 8) | data[IDX_BIT_RATE_3];
uint32_t bitRate = generateNumberInRangeFromData(tempValue, kMinBitRate, kMaxBitRate);
aacEncoder_SetParam(mEncoder, AACENC_BITRATE, bitRate);
uint32_t channelModeIndex =
generateNumberInRangeFromData(data[IDX_CHANNEL], 0, kChannelModesSize - 1);
CHANNEL_MODE channelMode = kChannelModes[channelModeIndex];
aacEncoder_SetParam(mEncoder, AACENC_CHANNELMODE, channelMode);
uint32_t identifierIndex =
generateNumberInRangeFromData(data[IDX_IDENTIFIER], 0, kIdentifiersSize - 1);
uint32_t identifier = kIdentifiers[identifierIndex];
aacEncoder_SetParam(mEncoder, AACENC_TRANSMUX, identifier);
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;
}

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten © Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -245,6 +245,46 @@ INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode,
return bitrate; return bitrate;
} }
/*-----------------------------------------------------------------------------
functionname: FDKaacEnc_AdjustVBRBitrateMode
description: Adjust bitrate mode to given bitrate parameter
input params: int vbrQuality (VBR0, VBR1, VBR2)
bitrate
channelMode
returns: vbr bitrate mode
------------------------------------------------------------------------------*/
AACENC_BITRATE_MODE FDKaacEnc_AdjustVBRBitrateMode(
AACENC_BITRATE_MODE bitrateMode, INT bitrate, CHANNEL_MODE channelMode) {
AACENC_BITRATE_MODE newBitrateMode = bitrateMode;
if (bitrate != -1) {
const INT monoStereoMode =
(FDKaacEnc_GetMonoStereoMode(channelMode) == EL_MODE_STEREO) ? 1 : 0;
const INT nChannelsEff =
FDKaacEnc_GetChannelModeConfiguration(channelMode)->nChannelsEff;
newBitrateMode = AACENC_BR_MODE_INVALID;
for (int idx = (int)(sizeof(configTabVBR) / sizeof(*configTabVBR)) - 1;
idx >= 0; idx--) {
if (bitrate >=
configTabVBR[idx].chanBitrate[monoStereoMode] * nChannelsEff) {
if (configTabVBR[idx].chanBitrate[monoStereoMode] * nChannelsEff <
FDKaacEnc_GetVBRBitrate(bitrateMode, channelMode)) {
newBitrateMode = configTabVBR[idx].bitrateMode;
} else {
newBitrateMode = bitrateMode;
}
break;
}
}
}
return AACENC_BR_MODE_IS_VBR(newBitrateMode) ? newBitrateMode
: AACENC_BR_MODE_INVALID;
}
/** /**
* \brief Convert encoder bitreservoir value for transport library. * \brief Convert encoder bitreservoir value for transport library.
* *
@ -397,7 +437,6 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(
FIXP_DBL mbfac, bw_ratio; FIXP_DBL mbfac, bw_ratio;
QC_INIT qcInit; QC_INIT qcInit;
INT averageBitsPerFrame = 0; INT averageBitsPerFrame = 0;
int bitresMin = 0; /* the bitreservoir is always big for AAC-LC */
const CHANNEL_MODE prevChannelMode = hAacEnc->encoderMode; const CHANNEL_MODE prevChannelMode = hAacEnc->encoderMode;
if (config == NULL) return AAC_ENC_INVALID_HANDLE; if (config == NULL) return AAC_ENC_INVALID_HANDLE;
@ -553,7 +592,6 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(
qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame & ~7); qcInit.minBits = fixMin(qcInit.minBits, averageBitsPerFrame & ~7);
} else { } else {
INT bitreservoir = -1; /* default bitreservoir size*/ INT bitreservoir = -1; /* default bitreservoir size*/
bitresMin = BITRES_MIN;
if (isLowDelay(config->audioObjectType)) { if (isLowDelay(config->audioObjectType)) {
INT brPerChannel = config->bitRate / config->nChannels; INT brPerChannel = config->bitRate / config->nChannels;
brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel)); brPerChannel = fMin(BITRATE_MAX_LD, fMax(BITRATE_MIN_LD, brPerChannel));
@ -567,7 +605,6 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(
bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD - BITRES_MIN_LD)) + bitreservoir = fMultI(slope, (INT)(BITRES_MAX_LD - BITRES_MIN_LD)) +
BITRES_MIN_LD; /* interpolate */ BITRES_MIN_LD; /* interpolate */
bitreservoir = bitreservoir & ~7; /* align to bytes */ bitreservoir = bitreservoir & ~7; /* align to bytes */
bitresMin = BITRES_MIN_LD;
} }
int maxBitres; int maxBitres;
@ -604,7 +641,8 @@ AAC_ENCODER_ERROR FDKaacEnc_Initialize(
qcInit.nSubFrames = config->nSubFrames; qcInit.nSubFrames = config->nSubFrames;
qcInit.padding.paddingRest = config->sampleRate; qcInit.padding.paddingRest = config->sampleRate;
if (qcInit.maxBits - qcInit.averageBits >= bitresMin * config->nChannels) { if (qcInit.maxBits - qcInit.averageBits >=
((qcInit.isLowDelay) ? BITRES_MIN_LD : BITRES_MIN) * config->nChannels) {
qcInit.bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */ qcInit.bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */
} else if (qcInit.maxBits > qcInit.averageBits) { } else if (qcInit.maxBits > qcInit.averageBits) {
qcInit.bitResMode = AACENC_BR_MODE_REDUCED; /* reduced bitreservoir */ qcInit.bitResMode = AACENC_BR_MODE_REDUCED; /* reduced bitreservoir */

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Förderung der angewandten © Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -334,6 +334,19 @@ INT FDKaacEnc_GetBitReservoirState(const HANDLE_AAC_ENC hAacEncoder);
INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode, INT FDKaacEnc_GetVBRBitrate(AACENC_BITRATE_MODE bitrateMode,
CHANNEL_MODE channelMode); CHANNEL_MODE channelMode);
/*-----------------------------------------------------------------------------
functionname: FDKaacEnc_AdjustVBRBitrateMode
description: Adjust bitrate mode to given bitrate parameter
input params: int vbrQuality (VBR0, VBR1, VBR2)
bitrate
channelMode
returns: vbr bitrate mode
------------------------------------------------------------------------------*/
AACENC_BITRATE_MODE FDKaacEnc_AdjustVBRBitrateMode(
AACENC_BITRATE_MODE bitrateMode, INT bitrate, CHANNEL_MODE channelMode);
/*----------------------------------------------------------------------------- /*-----------------------------------------------------------------------------
functionname: FDKaacEnc_AacInitDefaultConfig functionname: FDKaacEnc_AacInitDefaultConfig

View File

@ -1028,6 +1028,13 @@ static AACENC_ERROR FDKaacEnc_AdjustEncSettings(HANDLE_AACENCODER hAacEncoder,
case AACENC_BR_MODE_VBR_3: case AACENC_BR_MODE_VBR_3:
case AACENC_BR_MODE_VBR_4: case AACENC_BR_MODE_VBR_4:
case AACENC_BR_MODE_VBR_5: case AACENC_BR_MODE_VBR_5:
/* Adjust bitrate mode in case given peak bitrate is lower than expected
* VBR bitrate. */
if ((INT)config->userPeakBitrate != -1) {
hAacConfig->bitrateMode = FDKaacEnc_AdjustVBRBitrateMode(
hAacConfig->bitrateMode, config->userPeakBitrate,
hAacConfig->channelMode);
}
/* Get bitrate in VBR configuration */ /* Get bitrate in VBR configuration */
/* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode. /* In VBR mode; SBR-modul depends on bitrate, core encoder on bitrateMode.
*/ */

View File

@ -1,7 +1,7 @@
/* ----------------------------------------------------------------------------- /* -----------------------------------------------------------------------------
Software License for The Fraunhofer FDK AAC Codec Library for Android Software License for The Fraunhofer FDK AAC Codec Library for Android
© Copyright 1995 - 2019 Fraunhofer-Gesellschaft zur Förderung der angewandten © Copyright 1995 - 2020 Fraunhofer-Gesellschaft zur Förderung der angewandten
Forschung e.V. All rights reserved. Forschung e.V. All rights reserved.
1. INTRODUCTION 1. INTRODUCTION
@ -373,13 +373,8 @@ AAC_ENCODER_ERROR FDKaacEnc_QCInit(QC_STATE* hQC, struct QC_INIT* init,
hQC->invQuant = init->invQuant; hQC->invQuant = init->invQuant;
hQC->maxIterations = init->maxIterations; hQC->maxIterations = init->maxIterations;
if (isConstantBitrateMode(hQC->bitrateMode)) { /* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir */
/* 0: full bitreservoir, 1: reduced bitreservoir, 2: disabled bitreservoir
*/
hQC->bitResMode = init->bitResMode; hQC->bitResMode = init->bitResMode;
} else {
hQC->bitResMode = AACENC_BR_MODE_FULL; /* full bitreservoir */
}
hQC->padding.paddingRest = init->padding.paddingRest; hQC->padding.paddingRest = init->padding.paddingRest;
@ -800,10 +795,15 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, PSY_OUT** psyOut,
INT avgTotalDynBits = 0; /* maximal allowed dynamic bits for all frames */ INT avgTotalDynBits = 0; /* maximal allowed dynamic bits for all frames */
INT totalAvailableBits = 0; INT totalAvailableBits = 0;
INT nSubFrames = 1; INT nSubFrames = 1;
const INT isCBRAdjustment = (isConstantBitrateMode(hQC->bitrateMode) ||
(hQC->bitResMode != AACENC_BR_MODE_FULL))
? 1
: 0;
/*-------------------------------------------- */ /*-------------------------------------------- */
/* redistribute total bitreservoir to elements */ /* redistribute total bitreservoir to elements */
ErrorStatus = FDKaacEnc_BitResRedistribution(hQC, cm, avgTotalBits); ErrorStatus = FDKaacEnc_BitResRedistribution(
hQC, cm, (isCBRAdjustment == 0) ? hQC->maxBitsPerFrame : avgTotalBits);
if (ErrorStatus != AAC_ENC_OK) { if (ErrorStatus != AAC_ENC_OK) {
return ErrorStatus; return ErrorStatus;
} }
@ -831,33 +831,22 @@ AAC_ENCODER_ERROR FDKaacEnc_QCMain(QC_STATE* RESTRICT hQC, PSY_OUT** psyOut,
/*-------------------------------------------- */ /*-------------------------------------------- */
/*-------------------------------------------- */ /*-------------------------------------------- */
if (isConstantBitrateMode(hQC->bitrateMode)) {
/* calc granted dynamic bits for sub frame and /* calc granted dynamic bits for sub frame and
distribute it to each element */ distribute it to each element */
ErrorStatus = FDKaacEnc_prepareBitDistribution( ErrorStatus = FDKaacEnc_prepareBitDistribution(
hQC, psyOut, qcOut, cm, qcElement, avgTotalBits, &totalAvailableBits, hQC, psyOut, qcOut, cm, qcElement,
&avgTotalDynBits); (isCBRAdjustment == 0) ? hQC->maxBitsPerFrame : avgTotalBits,
&totalAvailableBits, &avgTotalDynBits);
if (ErrorStatus != AAC_ENC_OK) { if (ErrorStatus != AAC_ENC_OK) {
return ErrorStatus; return ErrorStatus;
} }
} else {
qcOut[0]->grantedDynBits =
((hQC->maxBitsPerFrame - (hQC->globHdrBits)) & ~7) -
(qcOut[0]->globalExtBits + qcOut[0]->staticBits +
qcOut[0]->elementExtBits);
qcOut[0]->maxDynBits = qcOut[0]->grantedDynBits;
totalAvailableBits = hQC->maxBitsPerFrame;
avgTotalDynBits = 0;
}
/* for ( all sub frames ) ... */ /* for ( all sub frames ) ... */
for (c = 0; c < nSubFrames; c++) { for (c = 0; c < nSubFrames; c++) {
/* for CBR and VBR mode */ /* for CBR and VBR mode */
FDKaacEnc_AdjustThresholds(hQC->hAdjThr, qcElement[c], qcOut[c], FDKaacEnc_AdjustThresholds(hQC->hAdjThr, qcElement[c], qcOut[c],
psyOut[c]->psyOutElement, psyOut[c]->psyOutElement, isCBRAdjustment, cm);
isConstantBitrateMode(hQC->bitrateMode), cm);
} /* -end- sub frame counter */ } /* -end- sub frame counter */