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 <string.h>
21 #include <utils/Log.h>
22 #include <algorithm>
23 #include "gsmamr_enc.h"
24
25 // Constants for AMR-NB
26 const int32_t kNumInputSamples = L_FRAME; // 160 samples
27 const int32_t kOutputBufferSize = 2 * kNumInputSamples * sizeof(Word16);
28 const Mode kModes[9] = {MR475, /* 4.75 kbps */
29 MR515, /* 5.15 kbps */
30 MR59, /* 5.90 kbps */
31 MR67, /* 6.70 kbps */
32 MR74, /* 7.40 kbps */
33 MR795, /* 7.95 kbps */
34 MR102, /* 10.2 kbps */
35 MR122, /* 12.2 kbps */
36 MRDTX, /* DTX */};
37 const Word16 kOutputFormat[3] = {AMR_TX_WMF, AMR_TX_IF2, AMR_TX_ETS};
38
39 class Codec {
40 public:
41 Codec() = default;
~Codec()42 ~Codec() { deInitEncoder(); }
43 Word16 initEncoder(const uint8_t *data);
44 void deInitEncoder();
45 void encodeFrames(const uint8_t *data, size_t size);
46
47 private:
48 void *mEncState = nullptr;
49 void *mSidState = nullptr;
50 };
51
initEncoder(const uint8_t * data)52 Word16 Codec::initEncoder(const uint8_t *data) {
53 return AMREncodeInit(&mEncState, &mSidState, (*data >> 1) & 0x01 /* dtx_enable flag */);
54 }
55
deInitEncoder()56 void Codec::deInitEncoder() {
57 if (mEncState) {
58 AMREncodeExit(&mEncState, &mSidState);
59 mEncState = nullptr;
60 mSidState = nullptr;
61 }
62 }
63
encodeFrames(const uint8_t * data,size_t size)64 void Codec::encodeFrames(const uint8_t *data, size_t size) {
65 AMREncodeReset(mEncState, mSidState);
66 uint8_t startByte = *data;
67 int modeIndex = ((startByte >> 3) % 9);
68 int outputFormatIndex = (startByte % 3);
69 Mode mode = kModes[modeIndex];
70 Word16 outputFormat = kOutputFormat[outputFormatIndex];
71
72 // Consume startByte
73 data++;
74 size--;
75
76 while (size > 0) {
77 Frame_Type_3GPP frameType = (Frame_Type_3GPP)mode;
78
79 Word16 inputBuf[kNumInputSamples] = {};
80 int32_t minSize = std::min(size, sizeof(inputBuf));
81
82 uint8_t outputBuf[kOutputBufferSize] = {};
83 memcpy(inputBuf, data, minSize);
84
85 AMREncode(mEncState, mSidState, mode, inputBuf, outputBuf, &frameType, outputFormat);
86
87 data += minSize;
88 size -= minSize;
89 }
90 }
91
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)92 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
93 if (size < 1) {
94 return 0;
95 }
96 Codec *codec = new Codec();
97 if (!codec) {
98 return 0;
99 }
100 if (codec->initEncoder(data) == 0) {
101 codec->encodeFrames(data, size);
102 }
103 delete codec;
104 return 0;
105 }
106