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