1 /******************************************************************************
2 *
3 * Copyright (C) 2020 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include <malloc.h>
21 #include <string.h>
22 #include <algorithm>
23 #include "pvamrwbdecoder.h"
24 #include "pvamrwbdecoder_api.h"
25
26 // Constants for AMR-WB.
27 constexpr int32_t kSamplesPerFrame = 320;
28 constexpr int32_t kBitsPerSample = 16;
29 constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
30 constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
31 constexpr int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58,
32 60, 17, 23, 32, 36, 40, 46, 50};
33
34 class Codec {
35 public:
36 Codec() = default;
~Codec()37 ~Codec() { deInitDecoder(); }
38 bool initDecoder();
39 void decodeFrames(const uint8_t *data, size_t size);
40 void deInitDecoder();
41
42 private:
43 void *mAmrHandle = nullptr;
44 int16_t *mDecoderCookie = nullptr;
45 void *mDecoderBuffer = nullptr;
46 };
47
initDecoder()48 bool Codec::initDecoder() {
49 mDecoderBuffer = malloc(pvDecoder_AmrWbMemRequirements());
50 if (mDecoderBuffer) {
51 pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuffer, &mDecoderCookie);
52 return true;
53 } else {
54 return false;
55 }
56 }
57
deInitDecoder()58 void Codec::deInitDecoder() {
59 if (mDecoderBuffer) {
60 free(mDecoderBuffer);
61 mDecoderBuffer = nullptr;
62 }
63 mAmrHandle = nullptr;
64 mDecoderCookie = nullptr;
65 }
66
decodeFrames(const uint8_t * data,size_t size)67 void Codec::decodeFrames(const uint8_t *data, size_t size) {
68 RX_State_wb rx_state{};
69 while (size > 0) {
70 uint8_t modeByte = *data;
71 bool quality = modeByte & 0x01;
72 int16 mode = ((modeByte >> 3) & 0x0f);
73 ++data;
74 --size;
75 int32_t frameSize = kFrameSizes[mode];
76 int16_t inputSampleBuf[kMaxSourceDataUnitSize];
77 uint8_t *inputBuf = new uint8_t[frameSize];
78 if (!inputBuf) {
79 return;
80 }
81 int32_t minSize = std::min((int32_t)size, frameSize);
82 memcpy(inputBuf, data, minSize);
83 int16 frameMode = mode;
84 int16 frameType;
85 mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, quality, &rx_state);
86
87 int16_t numSamplesOutput;
88 int16_t outputBuf[kOutputBufferSize];
89 pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, mDecoderBuffer,
90 frameType, mDecoderCookie);
91 data += minSize;
92 size -= minSize;
93 delete[] inputBuf;
94 }
95 }
96
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)97 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
98 if (size < 2) {
99 return 0;
100 }
101 Codec *codec = new Codec();
102 if (!codec) {
103 return 0;
104 }
105 if (codec->initDecoder()) {
106 codec->decodeFrames(data, size);
107 }
108 delete codec;
109 return 0;
110 }
111