1*e5436536SAndroid Build Coastguard Worker /******************************************************************************
2*e5436536SAndroid Build Coastguard Worker *
3*e5436536SAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
4*e5436536SAndroid Build Coastguard Worker *
5*e5436536SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
6*e5436536SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
7*e5436536SAndroid Build Coastguard Worker * You may obtain a copy of the License at:
8*e5436536SAndroid Build Coastguard Worker *
9*e5436536SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
10*e5436536SAndroid Build Coastguard Worker *
11*e5436536SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
12*e5436536SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
13*e5436536SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*e5436536SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
15*e5436536SAndroid Build Coastguard Worker * limitations under the License.
16*e5436536SAndroid Build Coastguard Worker *
17*e5436536SAndroid Build Coastguard Worker *****************************************************************************
18*e5436536SAndroid Build Coastguard Worker * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*e5436536SAndroid Build Coastguard Worker */
20*e5436536SAndroid Build Coastguard Worker
21*e5436536SAndroid Build Coastguard Worker #include <stdint.h>
22*e5436536SAndroid Build Coastguard Worker #include <string.h>
23*e5436536SAndroid Build Coastguard Worker #include <algorithm>
24*e5436536SAndroid Build Coastguard Worker #include "aacdecoder_lib.h"
25*e5436536SAndroid Build Coastguard Worker
26*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kNumberOfLayers = 1;
27*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kMaxChannelCount = 8;
28*e5436536SAndroid Build Coastguard Worker constexpr uint32_t kMaxConfigurationSize = 1024;
29*e5436536SAndroid Build Coastguard Worker constexpr uint32_t kMaxOutBufferSize = 2048 * kMaxChannelCount;
30*e5436536SAndroid Build Coastguard Worker
31*e5436536SAndroid Build Coastguard Worker // Value indicating the start of AAC Header Segment
32*e5436536SAndroid Build Coastguard Worker constexpr const char *kAacSegStartSeq = "AAC_STRT";
33*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kAacSegStartSeqLen = sizeof(kAacSegStartSeq);
34*e5436536SAndroid Build Coastguard Worker // Value indicating the end of AAC Header Segment
35*e5436536SAndroid Build Coastguard Worker constexpr const char *kAacSegEndSeq = "AAC_ENDS";
36*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kAacSegEndSeqLen = sizeof(kAacSegEndSeq);
37*e5436536SAndroid Build Coastguard Worker
38*e5436536SAndroid Build Coastguard Worker // Number of bytes used to signal the length of the header
39*e5436536SAndroid Build Coastguard Worker constexpr uint8_t kHeaderLengthBytes = 2;
40*e5436536SAndroid Build Coastguard Worker // Minimum size of an AAC header is 2
41*e5436536SAndroid Build Coastguard Worker // Minimum data required is
42*e5436536SAndroid Build Coastguard Worker // strlen(AAC_STRT) + strlen(AAC_ENDS) + kHeaderLengthBytes + 2;
43*e5436536SAndroid Build Coastguard Worker constexpr UINT kMinDataSize = kAacSegStartSeqLen + kAacSegEndSeqLen + kHeaderLengthBytes + 2;
44*e5436536SAndroid Build Coastguard Worker
getHeaderSize(UCHAR * data,UINT size)45*e5436536SAndroid Build Coastguard Worker UINT getHeaderSize(UCHAR *data, UINT size) {
46*e5436536SAndroid Build Coastguard Worker if (size < kMinDataSize) {
47*e5436536SAndroid Build Coastguard Worker return 0;
48*e5436536SAndroid Build Coastguard Worker }
49*e5436536SAndroid Build Coastguard Worker
50*e5436536SAndroid Build Coastguard Worker int32_t result = memcmp(data, kAacSegStartSeq, kAacSegStartSeqLen);
51*e5436536SAndroid Build Coastguard Worker if (result) {
52*e5436536SAndroid Build Coastguard Worker return 0;
53*e5436536SAndroid Build Coastguard Worker }
54*e5436536SAndroid Build Coastguard Worker data += kAacSegStartSeqLen;
55*e5436536SAndroid Build Coastguard Worker size -= kAacSegStartSeqLen;
56*e5436536SAndroid Build Coastguard Worker
57*e5436536SAndroid Build Coastguard Worker uint32_t headerLengthInBytes = (data[0] << 8 | data[1]) & 0xFFFF;
58*e5436536SAndroid Build Coastguard Worker data += kHeaderLengthBytes;
59*e5436536SAndroid Build Coastguard Worker size -= kHeaderLengthBytes;
60*e5436536SAndroid Build Coastguard Worker
61*e5436536SAndroid Build Coastguard Worker if (headerLengthInBytes + kAacSegEndSeqLen > size) {
62*e5436536SAndroid Build Coastguard Worker return 0;
63*e5436536SAndroid Build Coastguard Worker }
64*e5436536SAndroid Build Coastguard Worker
65*e5436536SAndroid Build Coastguard Worker data += headerLengthInBytes;
66*e5436536SAndroid Build Coastguard Worker size -= headerLengthInBytes;
67*e5436536SAndroid Build Coastguard Worker result = memcmp(data, kAacSegEndSeq, kAacSegEndSeqLen);
68*e5436536SAndroid Build Coastguard Worker if (result) {
69*e5436536SAndroid Build Coastguard Worker return 0;
70*e5436536SAndroid Build Coastguard Worker }
71*e5436536SAndroid Build Coastguard Worker
72*e5436536SAndroid Build Coastguard Worker return std::min(headerLengthInBytes, kMaxConfigurationSize);
73*e5436536SAndroid Build Coastguard Worker }
74*e5436536SAndroid Build Coastguard Worker
75*e5436536SAndroid Build Coastguard Worker class Codec {
76*e5436536SAndroid Build Coastguard Worker public:
77*e5436536SAndroid Build Coastguard Worker Codec() = default;
~Codec()78*e5436536SAndroid Build Coastguard Worker ~Codec() { deInitDecoder(); }
79*e5436536SAndroid Build Coastguard Worker bool initDecoder();
80*e5436536SAndroid Build Coastguard Worker void decodeFrames(UCHAR *data, UINT size);
81*e5436536SAndroid Build Coastguard Worker void deInitDecoder();
82*e5436536SAndroid Build Coastguard Worker
83*e5436536SAndroid Build Coastguard Worker private:
84*e5436536SAndroid Build Coastguard Worker HANDLE_AACDECODER mAacDecoderHandle = nullptr;
85*e5436536SAndroid Build Coastguard Worker AAC_DECODER_ERROR mErrorCode = AAC_DEC_OK;
86*e5436536SAndroid Build Coastguard Worker };
87*e5436536SAndroid Build Coastguard Worker
initDecoder()88*e5436536SAndroid Build Coastguard Worker bool Codec::initDecoder() {
89*e5436536SAndroid Build Coastguard Worker mAacDecoderHandle = aacDecoder_Open(TT_MP4_ADIF, kNumberOfLayers);
90*e5436536SAndroid Build Coastguard Worker if (!mAacDecoderHandle) {
91*e5436536SAndroid Build Coastguard Worker return false;
92*e5436536SAndroid Build Coastguard Worker }
93*e5436536SAndroid Build Coastguard Worker return true;
94*e5436536SAndroid Build Coastguard Worker }
95*e5436536SAndroid Build Coastguard Worker
deInitDecoder()96*e5436536SAndroid Build Coastguard Worker void Codec::deInitDecoder() {
97*e5436536SAndroid Build Coastguard Worker aacDecoder_Close(mAacDecoderHandle);
98*e5436536SAndroid Build Coastguard Worker mAacDecoderHandle = nullptr;
99*e5436536SAndroid Build Coastguard Worker }
100*e5436536SAndroid Build Coastguard Worker
decodeFrames(UCHAR * data,UINT size)101*e5436536SAndroid Build Coastguard Worker void Codec::decodeFrames(UCHAR *data, UINT size) {
102*e5436536SAndroid Build Coastguard Worker UINT headerSize = getHeaderSize(data, size);
103*e5436536SAndroid Build Coastguard Worker if (headerSize != 0) {
104*e5436536SAndroid Build Coastguard Worker data += kAacSegStartSeqLen + kHeaderLengthBytes;
105*e5436536SAndroid Build Coastguard Worker size -= kAacSegStartSeqLen + kHeaderLengthBytes;
106*e5436536SAndroid Build Coastguard Worker aacDecoder_ConfigRaw(mAacDecoderHandle, &data, &headerSize);
107*e5436536SAndroid Build Coastguard Worker data += headerSize + kAacSegEndSeqLen;
108*e5436536SAndroid Build Coastguard Worker size -= headerSize + kAacSegEndSeqLen;
109*e5436536SAndroid Build Coastguard Worker }
110*e5436536SAndroid Build Coastguard Worker while (size > 0) {
111*e5436536SAndroid Build Coastguard Worker UINT inputSize = size;
112*e5436536SAndroid Build Coastguard Worker UINT valid = size;
113*e5436536SAndroid Build Coastguard Worker mErrorCode = aacDecoder_Fill(mAacDecoderHandle, &data, &inputSize, &valid);
114*e5436536SAndroid Build Coastguard Worker if (mErrorCode != AAC_DEC_OK) {
115*e5436536SAndroid Build Coastguard Worker ++data;
116*e5436536SAndroid Build Coastguard Worker --size;
117*e5436536SAndroid Build Coastguard Worker } else {
118*e5436536SAndroid Build Coastguard Worker INT_PCM outputBuf[kMaxOutBufferSize];
119*e5436536SAndroid Build Coastguard Worker do {
120*e5436536SAndroid Build Coastguard Worker mErrorCode =
121*e5436536SAndroid Build Coastguard Worker aacDecoder_DecodeFrame(mAacDecoderHandle, outputBuf,
122*e5436536SAndroid Build Coastguard Worker kMaxOutBufferSize /*size in number of INT_PCM, not bytes*/, 0);
123*e5436536SAndroid Build Coastguard Worker } while (mErrorCode == AAC_DEC_OK);
124*e5436536SAndroid Build Coastguard Worker UINT offset = inputSize - valid;
125*e5436536SAndroid Build Coastguard Worker data += offset;
126*e5436536SAndroid Build Coastguard Worker size = valid;
127*e5436536SAndroid Build Coastguard Worker }
128*e5436536SAndroid Build Coastguard Worker }
129*e5436536SAndroid Build Coastguard Worker }
130*e5436536SAndroid Build Coastguard Worker
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)131*e5436536SAndroid Build Coastguard Worker extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
132*e5436536SAndroid Build Coastguard Worker Codec *codec = new Codec();
133*e5436536SAndroid Build Coastguard Worker if (!codec) {
134*e5436536SAndroid Build Coastguard Worker return 0;
135*e5436536SAndroid Build Coastguard Worker }
136*e5436536SAndroid Build Coastguard Worker if (codec->initDecoder()) {
137*e5436536SAndroid Build Coastguard Worker codec->decodeFrames((UCHAR *)(data), static_cast<UINT>(size));
138*e5436536SAndroid Build Coastguard Worker }
139*e5436536SAndroid Build Coastguard Worker delete codec;
140*e5436536SAndroid Build Coastguard Worker return 0;
141*e5436536SAndroid Build Coastguard Worker }
142