diff options
-rw-r--r-- | Android.bp | 52 | ||||
-rw-r--r-- | METADATA | 3 | ||||
-rw-r--r-- | fuzzer/Android.bp | 82 | ||||
-rw-r--r-- | fuzzer/README.md | 150 | ||||
-rw-r--r-- | fuzzer/aac_dec_fuzzer.cpp | 141 | ||||
-rw-r--r-- | fuzzer/aac_enc_fuzzer.cpp | 479 | ||||
-rw-r--r-- | libAACdec/src/aacdecoder_lib.cpp | 19 | ||||
-rw-r--r-- | libAACdec/src/channel.cpp | 6 | ||||
-rw-r--r-- | libAACenc/src/aacenc_lib.cpp | 17 | ||||
-rw-r--r-- | libDRCdec/src/FDK_drcDecLib.cpp | 2 | ||||
-rw-r--r-- | libDRCdec/src/drcDec_reader.cpp | 13 | ||||
-rw-r--r-- | libFDK/src/FDK_core.cpp | 2 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_asc.cpp | 45 | ||||
-rw-r--r-- | libMpegTPDec/src/tpdec_lib.cpp | 2 | ||||
-rw-r--r-- | libMpegTPEnc/src/tpenc_lib.cpp | 2 | ||||
-rw-r--r-- | libPCMutils/src/version.h | 2 | ||||
-rw-r--r-- | libSACdec/src/sac_dec_lib.cpp | 2 | ||||
-rw-r--r-- | libSACenc/src/sacenc_lib.cpp | 2 | ||||
-rw-r--r-- | libSBRdec/src/sbrdecoder.cpp | 2 | ||||
-rw-r--r-- | libSBRenc/src/env_est.cpp | 22 | ||||
-rw-r--r-- | libSBRenc/src/sbr_encoder.cpp | 7 |
21 files changed, 1007 insertions, 45 deletions
@@ -1,6 +1,40 @@ +// *** THIS PACKAGE HAS SPECIAL LICENSING CONDITIONS. PLEASE +// CONSULT THE OWNERS AND opensource-licensing@google.com BEFORE +// DEPENDING ON IT IN YOUR PROJECT. *** +package { + default_applicable_licenses: ["external_aac_license"], +} + +// Added automatically by a large-scale-change that took the approach of +// 'apply every license found to every target'. While this makes sure we respect +// every license restriction, it may not be entirely correct. +// +// e.g. GPL in an MIT project might only apply to the contrib/ directory. +// +// Please consider splitting the single license below into multiple licenses, +// taking care not to lose any license_kind information, and overriding the +// default license using the 'licenses: [...]' property on targets as needed. +// +// For unused files, consider creating a 'fileGroup' with "//visibility:private" +// to attach the license to, and including a comment whether the files may be +// used in the current project. +// See: http://go/android-license-faq +license { + name: "external_aac_license", + visibility: [":__subpackages__"], + license_kinds: [ + "SPDX-license-identifier-Apache-2.0", + "legacy_by_exception_only", // by exception only + ], + license_text: [ + "NOTICE", + ], +} + cc_library_static { name: "libFraunhoferAAC", vendor_available: true, + host_supported: true, srcs: [ "libAACdec/src/*.cpp", "libAACenc/src/*.cpp", @@ -23,15 +57,15 @@ cc_library_static { "-Wuninitialized", "-Wno-self-assign", "-Wno-implicit-fallthrough", + "-DSUPPRESS_BUILD_DATE_INFO", ], sanitize: { - misc_undefined:[ - "unsigned-integer-overflow", - "signed-integer-overflow", - "bounds", + misc_undefined: [ + "unsigned-integer-overflow", + "signed-integer-overflow", + "bounds", ], - // Enable CFI if this becomes a shared library. - // cfi: true, + cfi: true, }, shared_libs: [ "liblog", @@ -52,6 +86,12 @@ cc_library_static { "libSACenc/include", ], + target: { + darwin: { + enabled: false, + }, + }, + apex_available: [ "//apex_available:platform", "com.android.bluetooth.updatable", diff --git a/METADATA b/METADATA new file mode 100644 index 0000000..5c12860 --- /dev/null +++ b/METADATA @@ -0,0 +1,3 @@ +third_party { + license_type: BY_EXCEPTION_ONLY +} diff --git a/fuzzer/Android.bp b/fuzzer/Android.bp new file mode 100644 index 0000000..6739798 --- /dev/null +++ b/fuzzer/Android.bp @@ -0,0 +1,82 @@ +/****************************************************************************** + * + * 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 + */ + +package { + // See: http://go/android-license-faq + // A large-scale-change added 'default_applicable_licenses' to import + // all of the 'license_kinds' from "external_aac_license" + // to get the below license kinds: + // SPDX-license-identifier-Apache-2.0 + default_applicable_licenses: ["external_aac_license"], +} + +cc_defaults { + name: "aac_fuzz_defaults", + host_supported: true, + + static_libs: [ + "libFraunhoferAAC", + ], + + target: { + darwin: { + enabled: false, + }, + }, + + fuzz_config: { + cc: [ + "android-media-fuzzing-reports@google.com", + ], + 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" + ], + + include_dirs: [ + "external/aac/libAACenc/" + ], +} diff --git a/fuzzer/README.md b/fuzzer/README.md new file mode 100644 index 0000000..b8cc260 --- /dev/null +++ b/fuzzer/README.md @@ -0,0 +1,150 @@ +# Fuzzer for libFraunhoferAAC decoder + +## Plugin Design Considerations +The fuzzer plugin for aac decoder is designed based on the understanding of the +codec and tries to achieve the following: + +##### Maximize code coverage + +This fuzzer makes use of the following config parameters: +1. Transport type (parameter name: `TRANSPORT_TYPE`) + +| Parameter| Valid Values| Configured Value| +|------------- |-------------| ----- | +| `TRANSPORT_TYPE` | 0.`TT_UNKNOWN ` 1.`TT_MP4_RAW ` 2.`TT_MP4_ADIF ` 3.`TT_MP4_ADTS ` 4.`TT_MP4_LATM_MCP1 ` 5.`TT_MP4_LATM_MCP0 ` 6.`TT_MP4_LOAS ` 7.`TT_DRM ` | `TT_MP4_ADIF ` | + +Note: Value of `TRANSPORT_TYPE` could be set to any of these values. +It is set to `TT_MP4_ADIF` in the fuzzer plugin. + +##### Maximize utilization of input data +The plugin feeds the entire input data to the codec using a loop. + * If the decode operation was successful, the input is advanced by an + offset calculated using valid bytes. + * If the decode operation was un-successful, the input is advanced by 1 byte + till it reaches a valid frame or end of stream. + +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_dec_fuzzer binary. + +## Android + +### Steps to build +Build the fuzzer +``` + $ mm -j$(nproc) aac_dec_fuzzer +``` + +### Steps to run +Create a directory CORPUS_DIR and copy some aac files to that folder. +Push this directory to device. + +To run on device +``` + $ adb sync data + $ adb shell /data/fuzz/arm64/aac_dec_fuzzer/aac_dec_fuzzer CORPUS_DIR +``` +To run on host +``` + $ $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: + +| AACENC_PARAM param| Valid Values| Configured Value| +|-------------| ----- |----- | +|`AACENC_SBR_MODE` | `-1 ` `0 ` `1 ` `2 ` | Calculated using first byte of data | +|`AACENC_AOT` |`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 ` | Calculated using second byte of data | +|`AACENC_SAMPLERATE` | `8000 ` `11025 ` `12000 ` `16000 ` `22050 ` `24000 ` `32000 ` `44100 ` `48000 ` `64000 ` `88200 ` `96000 `| Calculated using third byte of data | +|`AACENC_BITRATE` | In range `8000 ` to `960000 ` | Calculated using fourth, fifth and sixth byte of data | +|`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_6_1 ` `MODE_7_1_BACK ` `MODE_7_1_TOP_FRONT ` `MODE_7_1_REAR_SURROUND ` `MODE_7_1_FRONT_CENTER ` `MODE_212 ` | Calculated using seventh byte of data | +|`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 |`AACENC_SBR_RATIO` |`-1 ` `0 ` `1 ` `2 ` | Calculated using ninth byte of data | +|`AACENC_BITRATEMODE` |`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 ` | Calculated using thirty-fourth byte of data | +|`AACENC_GRANULE_LENGTH` |`120 ` `128 ` `240 ` `256 ` `480 ` `512 ` `1024 ` | Calculated using thirty-fifth byte of data | +|`AACENC_CHANNELORDER` |`CH_ORDER_MPEG ` `CH_ORDER_WAV ` | Calculated using thirty-sixth byte of data | +|`AACENC_AFTERBURNER` |`0 ` `1 ` | Calculated using thirty-seventh byte of data | +|`AACENC_BANDWIDTH` |`0 ` `1` | Calculated using thirty-eigth byte of data | +|` AACENC_IDX_PEAK_BITRATE` | In range `8000 ` to `960000 ` | Calculated using thirty-ninth byte of data | +|` AACENC_HEADER_PERIOD` |In range `0 ` to `255 ` | Calculated using fortieth byte of data | +|` AACENC_SIGNALING_MODE` |`-1 ` `0 ` `1 ` `2 ` `3 ` | Calculated using forty-first byte of data | +|` AACENC_TPSUBFRAMES` |In range `0 ` to `255 ` | Calculated using forty-second byte of data | +|` AACENC_AUDIOMUXVER` |`-1 ` `0 ` `1 ` `2 ` | Calculated using forty-third byte of data | +|` AACENC_PROTECTION` |`0 ` `1 ` | Calculated using forty-fourth of data | +|`AACENC_ANCILLARY_BITRATE` |In range `0 ` to `960000 `| Calculated using forty-fifth byte of data | +|`AACENC_METADATA_MODE ` |`0 ` `1 ` `2 ` `3 ` | Calculated using forty-sixth 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: + * http://llvm.org/docs/LibFuzzer.html + * https://github.com/google/oss-fuzz diff --git a/fuzzer/aac_dec_fuzzer.cpp b/fuzzer/aac_dec_fuzzer.cpp new file mode 100644 index 0000000..c970197 --- /dev/null +++ b/fuzzer/aac_dec_fuzzer.cpp @@ -0,0 +1,141 @@ +/****************************************************************************** + * + * 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 <stdint.h> +#include <string.h> +#include <algorithm> +#include "aacdecoder_lib.h" + +constexpr uint8_t kNumberOfLayers = 1; +constexpr uint8_t kMaxChannelCount = 8; +constexpr uint32_t kMaxConfigurationSize = 1024; +constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount; + +// Value indicating the start of AAC Header Segment +constexpr const char *kAacSegStartSeq = "AAC_STRT"; +constexpr uint8_t kAacSegStartSeqLen = sizeof(kAacSegStartSeq); +// Value indicating the end of AAC Header Segment +constexpr const char *kAacSegEndSeq = "AAC_ENDS"; +constexpr uint8_t kAacSegEndSeqLen = sizeof(kAacSegEndSeq); + +// Number of bytes used to signal the length of the header +constexpr uint8_t kHeaderLengthBytes = 2; +// Minimum size of an AAC header is 2 +// Minimum data required is +// strlen(AAC_STRT) + strlen(AAC_ENDS) + kHeaderLengthBytes + 2; +constexpr UINT kMinDataSize = kAacSegStartSeqLen + kAacSegEndSeqLen + kHeaderLengthBytes + 2; + +UINT getHeaderSize(UCHAR *data, UINT size) { + if (size < kMinDataSize) { + return 0; + } + + int32_t result = memcmp(data, kAacSegStartSeq, kAacSegStartSeqLen); + if (result) { + return 0; + } + data += kAacSegStartSeqLen; + size -= kAacSegStartSeqLen; + + uint32_t headerLengthInBytes = (data[0] << 8 | data[1]) & 0xFFFF; + data += kHeaderLengthBytes; + size -= kHeaderLengthBytes; + + if (headerLengthInBytes + kAacSegEndSeqLen > size) { + return 0; + } + + data += headerLengthInBytes; + size -= headerLengthInBytes; + result = memcmp(data, kAacSegEndSeq, kAacSegEndSeqLen); + if (result) { + return 0; + } + + return std::min(headerLengthInBytes, kMaxConfigurationSize); +} + +class Codec { + public: + Codec() = default; + ~Codec() { deInitDecoder(); } + bool initDecoder(); + void decodeFrames(UCHAR *data, UINT size); + void deInitDecoder(); + + private: + HANDLE_AACDECODER mAacDecoderHandle = nullptr; + AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK; +}; + +bool Codec::initDecoder() { + mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers); + if (!mAacDecoderHandle) { + return false; + } + return true; +} + +void Codec::deInitDecoder() { + aacDecoder_Close(mAacDecoderHandle); + mAacDecoderHandle = nullptr; +} + +void Codec::decodeFrames(UCHAR *data, UINT size) { + UINT headerSize = getHeaderSize(data, size); + if (headerSize != 0) { + data += kAacSegStartSeqLen + kHeaderLengthBytes; + size -= kAacSegStartSeqLen + kHeaderLengthBytes; + aacDecoder_ConfigRaw(mAacDecoderHandle, &data, &headerSize); + data += headerSize + kAacSegEndSeqLen; + size -= headerSize + kAacSegEndSeqLen; + } + while (size > 0) { + UINT inputSize = size; + UINT valid = size; + mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid); + if (mErrorCode != AAC_DEC_OK) { + ++data; + --size; + } else { + INT_PCM outputBuf[kMaxOutBufferSize]; + do { + mErrorCode = + aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf, + kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0); + } while (mErrorCode == AAC_DEC_OK); + UINT offset = inputSize - valid; + data += offset; + size = valid; + } + } +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + Codec *codec = new Codec(); + if (!codec) { + return 0; + } + if (codec->initDecoder()) { + codec->decodeFrames((UCHAR *)(data), static_cast<UINT>(size)); + } + delete codec; + return 0; +} diff --git a/fuzzer/aac_enc_fuzzer.cpp b/fuzzer/aac_enc_fuzzer.cpp new file mode 100644 index 0000000..5a35d70 --- /dev/null +++ b/fuzzer/aac_enc_fuzzer.cpp @@ -0,0 +1,479 @@ +/****************************************************************************** + * + * 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; +} diff --git a/libAACdec/src/aacdecoder_lib.cpp b/libAACdec/src/aacdecoder_lib.cpp index 90563ea..9d36d10 100644 --- a/libAACdec/src/aacdecoder_lib.cpp +++ b/libAACdec/src/aacdecoder_lib.cpp @@ -122,7 +122,7 @@ amm-info@iis.fraunhofer.de #define AACDECODER_LIB_VL1 2 #define AACDECODER_LIB_VL2 0 #define AACDECODER_LIB_TITLE "AAC Decoder Lib" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define AACDECODER_LIB_BUILD_DATE "" #define AACDECODER_LIB_BUILD_TIME "" #else @@ -441,12 +441,23 @@ static INT aacDecoder_UniDrcCallback(void *handle, HANDLE_FDK_BITSTREAM hBs, TRANSPORTDEC_ERROR errTp; HANDLE_AACDECODER hAacDecoder = (HANDLE_AACDECODER)handle; DRC_DEC_CODEC_MODE drcDecCodecMode = DRC_DEC_CODEC_MODE_UNDEFINED; + UCHAR dummyBuffer[4] = {0}; + FDK_BITSTREAM dummyBs; + HANDLE_FDK_BITSTREAM hReadBs; if (subStreamIndex != 0) { return TRANSPORTDEC_OK; } - else if (aot == AOT_USAC) { + if (hBs == NULL) { + /* use dummy zero payload to clear memory */ + hReadBs = &dummyBs; + FDKinitBitStream(hReadBs, dummyBuffer, 4, 24); + } else { + hReadBs = hBs; + } + + if (aot == AOT_USAC) { drcDecCodecMode = DRC_DEC_MPEG_D_USAC; } @@ -455,10 +466,10 @@ static INT aacDecoder_UniDrcCallback(void *handle, HANDLE_FDK_BITSTREAM hBs, if (payloadType == 0) /* uniDrcConfig */ { - err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hBs); + err = FDK_drcDec_ReadUniDrcConfig(hAacDecoder->hUniDrcDecoder, hReadBs); } else /* loudnessInfoSet */ { - err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hBs); + err = FDK_drcDec_ReadLoudnessInfoSet(hAacDecoder->hUniDrcDecoder, hReadBs); hAacDecoder->loudnessInfoSetPosition[1] = payloadStart; hAacDecoder->loudnessInfoSetPosition[2] = fullPayloadLength; } diff --git a/libAACdec/src/channel.cpp b/libAACdec/src/channel.cpp index a020034..7e62bfb 100644 --- a/libAACdec/src/channel.cpp +++ b/libAACdec/src/channel.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- 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. 1. INTRODUCTION @@ -265,7 +265,9 @@ void CChannelElement_Decode( stereo prediction since scaling has already been carried out. */ int max_sfb_ste = (INT)(pAacDecoderChannelInfo[L]->icsInfo.max_sfb_ste); - if ((!CP_active) || (CP_active && (max_sfb_ste < noSfbs)) || + if (!(CP_active && (max_sfb_ste == noSfbs)) || + !(CP_active && + !(pAacDecoderChannelInfo[ch]->pDynData->TnsData.Active)) || ((flags & (AC_USAC | AC_RSVD50 | AC_RSV603DA)) && (pAacDecoderChannelInfo[L]->pDynData->specificTo.usac.tns_on_lr == 0))) { diff --git a/libAACenc/src/aacenc_lib.cpp b/libAACenc/src/aacenc_lib.cpp index b0d0454..caa62c5 100644 --- a/libAACenc/src/aacenc_lib.cpp +++ b/libAACenc/src/aacenc_lib.cpp @@ -112,7 +112,7 @@ amm-info@iis.fraunhofer.de #define AACENCODER_LIB_VL1 0 #define AACENCODER_LIB_VL2 1 #define AACENCODER_LIB_TITLE "AAC Encoder" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define AACENCODER_LIB_BUILD_DATE "" #define AACENCODER_LIB_BUILD_TIME "" #else @@ -1784,8 +1784,8 @@ AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder, hAacEncoder->nSamplesRead)); INT_PCM *pIn = hAacEncoder->inputBuffer + - (hAacEncoder->inputBufferOffset + hAacEncoder->nSamplesRead) / - hAacEncoder->aacConfig.nChannels; + hAacEncoder->inputBufferOffset / hAacEncoder->aacConfig.nChannels + + hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels; newSamples -= (newSamples % hAacEncoder->extParam @@ -1827,12 +1827,13 @@ AACENC_ERROR aacEncEncode(const HANDLE_AACENCODER hAacEncoder, /* clear out until end-of-buffer */ if (nZeros) { + INT_PCM *pIn = + hAacEncoder->inputBuffer + + hAacEncoder->inputBufferOffset / + hAacEncoder->aacConfig.nChannels + + hAacEncoder->nSamplesRead / hAacEncoder->extParam.nChannels; for (i = 0; i < (int)hAacEncoder->extParam.nChannels; i++) { - FDKmemclear(hAacEncoder->inputBuffer + - i * hAacEncoder->inputBufferSizePerChannel + - (hAacEncoder->inputBufferOffset + - hAacEncoder->nSamplesRead) / - hAacEncoder->extParam.nChannels, + FDKmemclear(pIn + i * hAacEncoder->inputBufferSizePerChannel, sizeof(INT_PCM) * nZeros); } hAacEncoder->nZerosAppended += nZeros; diff --git a/libDRCdec/src/FDK_drcDecLib.cpp b/libDRCdec/src/FDK_drcDecLib.cpp index 83b5773..26e5b78 100644 --- a/libDRCdec/src/FDK_drcDecLib.cpp +++ b/libDRCdec/src/FDK_drcDecLib.cpp @@ -112,7 +112,7 @@ amm-info@iis.fraunhofer.de #define DRCDEC_LIB_VL1 1 #define DRCDEC_LIB_VL2 0 #define DRCDEC_LIB_TITLE "MPEG-D DRC Decoder Lib" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define DRCDEC_LIB_BUILD_DATE "" #define DRCDEC_LIB_BUILD_TIME "" #else diff --git a/libDRCdec/src/drcDec_reader.cpp b/libDRCdec/src/drcDec_reader.cpp index 367a352..b3ec187 100644 --- a/libDRCdec/src/drcDec_reader.cpp +++ b/libDRCdec/src/drcDec_reader.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- 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. 1. INTRODUCTION @@ -512,10 +512,13 @@ drcDec_readUniDrcGain(HANDLE_FDK_BITSTREAM hBs, fMin(tmpNNodes, (UCHAR)16) * sizeof(GAIN_NODE)); } - hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1); - if (hUniDrcGain->uniDrcGainExtPresent == 1) { - err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension)); - if (err) return err; + if (pCoef && (gainSequenceCount == + pCoef->gainSequenceCount)) { /* all sequences have been read */ + hUniDrcGain->uniDrcGainExtPresent = FDKreadBits(hBs, 1); + if (hUniDrcGain->uniDrcGainExtPresent == 1) { + err = _readUniDrcGainExtension(hBs, &(hUniDrcGain->uniDrcGainExtension)); + if (err) return err; + } } if (err == DE_OK && gainSequenceCount > 0) { diff --git a/libFDK/src/FDK_core.cpp b/libFDK/src/FDK_core.cpp index 2f77179..48db17e 100644 --- a/libFDK/src/FDK_core.cpp +++ b/libFDK/src/FDK_core.cpp @@ -107,7 +107,7 @@ amm-info@iis.fraunhofer.de #define FDK_TOOLS_LIB_VL1 1 #define FDK_TOOLS_LIB_VL2 0 #define FDK_TOOLS_LIB_TITLE "FDK Tools" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define FDK_TOOLS_LIB_BUILD_DATE "" #define FDK_TOOLS_LIB_BUILD_TIME "" #else diff --git a/libMpegTPDec/src/tpdec_asc.cpp b/libMpegTPDec/src/tpdec_asc.cpp index a2baaaf..e46cb32 100644 --- a/libMpegTPDec/src/tpdec_asc.cpp +++ b/libMpegTPDec/src/tpdec_asc.cpp @@ -1778,6 +1778,10 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc, int numConfigExtensions; CONFIG_EXT_ID usacConfigExtType; int usacConfigExtLength; + int loudnessInfoSetIndex = + -1; /* index of loudnessInfoSet config extension. -1 if not contained. */ + int tmp_subStreamIndex = 0; + AUDIO_OBJECT_TYPE tmp_aot = AOT_USAC; numConfigExtensions = (int)escapedValue(hBs, 2, 4, 8) + 1; for (int confExtIdx = 0; confExtIdx < numConfigExtensions; confExtIdx++) { @@ -1807,10 +1811,12 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc, ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( cb->cbUniDrcData, hBs, usacConfigExtLength, 1, /* loudnessInfoSet */ - 0, loudnessInfoSetConfigExtensionPosition, AOT_USAC); + tmp_subStreamIndex, loudnessInfoSetConfigExtensionPosition, + tmp_aot); if (ErrorStatus != TRANSPORTDEC_OK) { return ErrorStatus; } + loudnessInfoSetIndex = confExtIdx; } } break; default: @@ -1826,6 +1832,17 @@ static TRANSPORTDEC_ERROR configExtension(CSUsacConfig *usc, FDKpushFor(hBs, usacConfigExtLength); } + if (loudnessInfoSetIndex == -1 && cb->cbUniDrc != NULL) { + /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding + * an empty config extension */ + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, tmp_subStreamIndex, + 0, tmp_aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + return ErrorStatus; } @@ -1842,6 +1859,8 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse( int channelElementIdx = 0; /* index for elements which contain audio channels (sce, cpe, lfe) */ SC_CHANNEL_CONFIG sc_chan_config = {0, 0, 0, 0}; + int uniDrcElement = + -1; /* index of uniDrc extension element. -1 if not contained. */ numberOfElements = (int)escapedValue(hBs, 4, 8, 16) + 1; usc->m_usacNumElements = numberOfElements; @@ -2017,6 +2036,10 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse( case ID_USAC_EXT: ErrorStatus = extElementConfig(&usc->element[i].extElement, hBs, cb, 0, asc->m_samplesPerFrame, 0, asc->m_aot); + if (usc->element[i].extElement.usacExtElementType == + ID_EXT_ELE_UNI_DRC) { + uniDrcElement = i; + } if (ErrorStatus) { return ErrorStatus; @@ -2045,6 +2068,18 @@ static TRANSPORTDEC_ERROR UsacRsv60DecoderConfig_Parse( } } + if (uniDrcElement == -1 && cb->cbUniDrc != NULL) { + /* no uniDrcConfig contained. Clear the uniDrcConfig struct by feeding an + * empty extension element */ + int subStreamIndex = 0; + ErrorStatus = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, NULL, 0, 0 /* uniDrcConfig */, subStreamIndex, 0, + asc->m_aot); + if (ErrorStatus != TRANSPORTDEC_OK) { + return ErrorStatus; + } + } + return ErrorStatus; } @@ -2131,6 +2166,14 @@ static TRANSPORTDEC_ERROR UsacConfig_Parse(CSAudioSpecificConfig *asc, if (err != TRANSPORTDEC_OK) { return err; } + } else if (cb->cbUniDrc != NULL) { + /* no loudnessInfoSet contained. Clear the loudnessInfoSet struct by feeding + * an empty config extension */ + err = (TRANSPORTDEC_ERROR)cb->cbUniDrc( + cb->cbUniDrcData, NULL, 0, 1 /* loudnessInfoSet */, 0, 0, asc->m_aot); + if (err != TRANSPORTDEC_OK) { + return err; + } } /* sanity check whether number of channels signaled in UsacDecoderConfig() diff --git a/libMpegTPDec/src/tpdec_lib.cpp b/libMpegTPDec/src/tpdec_lib.cpp index ca35184..091d011 100644 --- a/libMpegTPDec/src/tpdec_lib.cpp +++ b/libMpegTPDec/src/tpdec_lib.cpp @@ -1769,7 +1769,7 @@ TRANSPORTDEC_ERROR transportDec_GetLibInfo(LIB_INFO *info) { info += i; info->module_id = FDK_TPDEC; -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO info->build_date = ""; info->build_time = ""; #else diff --git a/libMpegTPEnc/src/tpenc_lib.cpp b/libMpegTPEnc/src/tpenc_lib.cpp index 14ea5fe..77c19b5 100644 --- a/libMpegTPEnc/src/tpenc_lib.cpp +++ b/libMpegTPEnc/src/tpenc_lib.cpp @@ -647,7 +647,7 @@ TRANSPORTENC_ERROR transportEnc_GetLibInfo(LIB_INFO *info) { info->module_id = FDK_TPENC; info->version = LIB_VERSION(TP_LIB_VL0, TP_LIB_VL1, TP_LIB_VL2); LIB_VERSION_STRING(info); -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO info->build_date = ""; info->build_time = ""; #else diff --git a/libPCMutils/src/version.h b/libPCMutils/src/version.h index 05371f8..871aa90 100644 --- a/libPCMutils/src/version.h +++ b/libPCMutils/src/version.h @@ -108,7 +108,7 @@ amm-info@iis.fraunhofer.de #define PCMUTIL_LIB_VL1 1 #define PCMUTIL_LIB_VL2 0 #define PCMUTIL_LIB_TITLE "PCM Utility Lib" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define PCMUTIL_LIB_BUILD_DATE "" #define PCMUTIL_LIB_BUILD_TIME "" #else diff --git a/libSACdec/src/sac_dec_lib.cpp b/libSACdec/src/sac_dec_lib.cpp index da19bb8..d30131f 100644 --- a/libSACdec/src/sac_dec_lib.cpp +++ b/libSACdec/src/sac_dec_lib.cpp @@ -1819,7 +1819,7 @@ int mpegSurroundDecoder_GetLibInfo(LIB_INFO *info) { info += i; info->module_id = FDK_MPSDEC; -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO info->build_date = ""; info->build_time = ""; #else diff --git a/libSACenc/src/sacenc_lib.cpp b/libSACenc/src/sacenc_lib.cpp index d6a1658..fcfe39b 100644 --- a/libSACenc/src/sacenc_lib.cpp +++ b/libSACenc/src/sacenc_lib.cpp @@ -130,7 +130,7 @@ Description of file contents #define SACENC_LIB_VL1 0 #define SACENC_LIB_VL2 0 #define SACENC_LIB_TITLE "MPEG Surround Encoder" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define SACENC_LIB_BUILD_DATE "" #define SACENC_LIB_BUILD_TIME "" #else diff --git a/libSBRdec/src/sbrdecoder.cpp b/libSBRdec/src/sbrdecoder.cpp index 55f929f..b101a4a 100644 --- a/libSBRdec/src/sbrdecoder.cpp +++ b/libSBRdec/src/sbrdecoder.cpp @@ -158,7 +158,7 @@ amm-info@iis.fraunhofer.de #define SBRDECODER_LIB_VL1 1 #define SBRDECODER_LIB_VL2 0 #define SBRDECODER_LIB_TITLE "SBR Decoder" -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO #define SBRDECODER_LIB_BUILD_DATE "" #define SBRDECODER_LIB_BUILD_TIME "" #else diff --git a/libSBRenc/src/env_est.cpp b/libSBRenc/src/env_est.cpp index 0eb8425..cc8780a 100644 --- a/libSBRenc/src/env_est.cpp +++ b/libSBRenc/src/env_est.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- 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. 1. INTRODUCTION @@ -1267,6 +1267,7 @@ void FDKsbrEnc_extractSbrEnvelope2( sbrExtrEnv->pre_transient_info[1] = ed->transient_info[1]; /* tran_flag */ hEnvChan->encEnvData.noOfEnvelopes = ed->nEnvelopes = ed->frame_info->nEnvelopes; /* number of envelopes of current frame */ + hEnvChan->encEnvData.currentAmpResFF = (AMP_RES)h_con->initAmpResFF; /* Check if the current frame is divided into one envelope only. If so, set @@ -1274,8 +1275,9 @@ void FDKsbrEnc_extractSbrEnvelope2( */ if ((hEnvChan->encEnvData.hSbrBSGrid->frameClass == FIXFIX) && (ed->nEnvelopes == 1)) { + AMP_RES currentAmpResFF = SBR_AMP_RES_1_5; if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY) { - /* Note: global_tonaliy_float_value == + /* Note: global_tonality_float_value == ((float)hEnvChan->encEnvData.global_tonality/((INT64)(1)<<(31-(19+2)))/0.524288*(2.0/3.0))); threshold_float_value == ((float)h_con->thresholdAmpResFF_m/((INT64)(1)<<(31-(h_con->thresholdAmpResFF_e)))/0.524288*(2.0/3.0))); @@ -1289,14 +1291,13 @@ void FDKsbrEnc_extractSbrEnvelope2( } else { hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_3_0; } - } else - hEnvChan->encEnvData.currentAmpResFF = SBR_AMP_RES_1_5; + currentAmpResFF = hEnvChan->encEnvData.currentAmpResFF; + } - if (hEnvChan->encEnvData.currentAmpResFF != - hEnvChan->encEnvData.init_sbr_amp_res) { + if (currentAmpResFF != hEnvChan->encEnvData.init_sbr_amp_res) { FDKsbrEnc_InitSbrHuffmanTables( &hEnvChan->encEnvData, &hEnvChan->sbrCodeEnvelope, - &hEnvChan->sbrCodeNoiseFloor, hEnvChan->encEnvData.currentAmpResFF); + &hEnvChan->sbrCodeNoiseFloor, currentAmpResFF); } } else { if (sbrHeaderData->sbr_amp_res != hEnvChan->encEnvData.init_sbr_amp_res) { @@ -1355,6 +1356,13 @@ void FDKsbrEnc_extractSbrEnvelope2( } } + if (h_con->sbrSyntaxFlags & SBR_SYNTAX_LOW_DELAY && + stereoMode == SBR_SWITCH_LRC && + h_envChan[0]->encEnvData.currentAmpResFF != + h_envChan[1]->encEnvData.currentAmpResFF) { + stereoMode = SBR_LEFT_RIGHT; + } + /* Extract envelope of current frame. */ diff --git a/libSBRenc/src/sbr_encoder.cpp b/libSBRenc/src/sbr_encoder.cpp index df9e996..c3da072 100644 --- a/libSBRenc/src/sbr_encoder.cpp +++ b/libSBRenc/src/sbr_encoder.cpp @@ -1,7 +1,7 @@ /* ----------------------------------------------------------------------------- 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. 1. INTRODUCTION @@ -1450,8 +1450,6 @@ static INT initEnvChannel(HANDLE_SBR_CONFIG_DATA sbrConfigData, params->deltaTAcrossFrames, 0, 0)) return (1); - sbrConfigData->initAmpResFF = params->init_amp_res_FF; - if (FDKsbrEnc_InitSbrHuffmanTables(&hEnv->encEnvData, &hEnv->sbrCodeEnvelope, &hEnv->sbrCodeNoiseFloor, sbrHeaderData->sbr_amp_res)) @@ -1749,6 +1747,7 @@ static INT FDKsbrEnc_EnvInit(HANDLE_SBR_ELEMENT hSbrElement, hSbrElement->sbrHeaderData.sbr_data_extra = 1; hSbrElement->sbrHeaderData.sbr_amp_res = (AMP_RES)params->amp_res; + hSbrElement->sbrConfigData.initAmpResFF = params->init_amp_res_FF; /* header_extra_1 */ hSbrElement->sbrHeaderData.freqScale = params->freqScale; @@ -2560,7 +2559,7 @@ INT sbrEncoder_GetLibInfo(LIB_INFO *info) { info->version = LIB_VERSION(SBRENCODER_LIB_VL0, SBRENCODER_LIB_VL1, SBRENCODER_LIB_VL2); LIB_VERSION_STRING(info); -#ifdef __ANDROID__ +#ifdef SUPPRESS_BUILD_DATE_INFO info->build_date = ""; info->build_time = ""; #else |