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 "cmnMemory.h"
24 #include "voAMRWB.h"
25 #include "cnst.h"
26 
27 typedef int(VO_API *VOGETAUDIOENCAPI)(VO_AUDIO_CODECAPI *pEncHandle);
28 const int32_t kInputBufferSize = L_FRAME16k * sizeof(int16_t) * 2;
29 const int32_t kOutputBufferSize = 2 * kInputBufferSize;
30 const int32_t kModes[] = {VOAMRWB_MD66 /* 6.60kbps */,    VOAMRWB_MD885 /* 8.85kbps */,
31                           VOAMRWB_MD1265 /* 12.65kbps */, VOAMRWB_MD1425 /* 14.25kbps */,
32                           VOAMRWB_MD1585 /* 15.85kbps */, VOAMRWB_MD1825 /* 18.25kbps */,
33                           VOAMRWB_MD1985 /* 19.85kbps */, VOAMRWB_MD2305 /* 23.05kbps */,
34                           VOAMRWB_MD2385 /* 23.85kbps */, VOAMRWB_N_MODES /* Invalid Mode */};
35 const VOAMRWBFRAMETYPE kFrameTypes[] = {VOAMRWB_DEFAULT, VOAMRWB_ITU, VOAMRWB_RFC3267};
36 
37 class Codec {
38    public:
39     Codec() = default;
~Codec()40     ~Codec() { deInitEncoder(); }
41     bool initEncoder(const uint8_t *data);
42     void deInitEncoder();
43     void encodeFrames(const uint8_t *data, size_t size);
44 
45    private:
46     VO_AUDIO_CODECAPI *mApiHandle = nullptr;
47     VO_MEM_OPERATOR *mMemOperator = nullptr;
48     VO_HANDLE mEncoderHandle = nullptr;
49 };
50 
initEncoder(const uint8_t * data)51 bool Codec::initEncoder(const uint8_t *data) {
52     uint8_t startByte = *data;
53     int32_t mode = kModes[(startByte >> 4) % 10];
54     VOAMRWBFRAMETYPE frameType = kFrameTypes[startByte % 3];
55     mMemOperator = new VO_MEM_OPERATOR;
56     if (!mMemOperator) {
57         return false;
58     }
59 
60     mMemOperator->Alloc = cmnMemAlloc;
61     mMemOperator->Copy = cmnMemCopy;
62     mMemOperator->Free = cmnMemFree;
63     mMemOperator->Set = cmnMemSet;
64     mMemOperator->Check = cmnMemCheck;
65 
66     VO_CODEC_INIT_USERDATA userData;
67     memset(&userData, 0, sizeof(userData));
68     userData.memflag = VO_IMF_USERMEMOPERATOR;
69     userData.memData = (VO_PTR)mMemOperator;
70 
71     mApiHandle = new VO_AUDIO_CODECAPI;
72     if (!mApiHandle) {
73         return false;
74     }
75     if (VO_ERR_NONE != voGetAMRWBEncAPI(mApiHandle)) {
76         // Failed to get api handle
77         return false;
78     }
79     if (VO_ERR_NONE != mApiHandle->Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &userData)) {
80         // Failed to init AMRWB encoder
81         return false;
82     }
83     if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &frameType)) {
84         // Failed to set AMRWB encoder frame type
85         return false;
86     }
87     if (VO_ERR_NONE != mApiHandle->SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mode)) {
88         // Failed to set AMRWB encoder mode
89         return false;
90     }
91     return true;
92 }
93 
deInitEncoder()94 void Codec::deInitEncoder() {
95     if (mEncoderHandle) {
96         mApiHandle->Uninit(mEncoderHandle);
97         mEncoderHandle = nullptr;
98     }
99     if (mApiHandle) {
100         delete mApiHandle;
101         mApiHandle = nullptr;
102     }
103     if (mMemOperator) {
104         delete mMemOperator;
105         mMemOperator = nullptr;
106     }
107 }
108 
encodeFrames(const uint8_t * data,size_t size)109 void Codec::encodeFrames(const uint8_t *data, size_t size) {
110     do {
111         int32_t minSize = std::min((int32_t)size, kInputBufferSize);
112         uint8_t outputBuf[kOutputBufferSize] = {};
113         VO_CODECBUFFER inData;
114         VO_CODECBUFFER outData;
115         VO_AUDIO_OUTPUTINFO outFormat;
116         inData.Buffer = (unsigned char *)data;
117         inData.Length = minSize;
118         outData.Buffer = outputBuf;
119         mApiHandle->SetInputData(mEncoderHandle, &inData);
120         mApiHandle->GetOutputData(mEncoderHandle, &outData, &outFormat);
121         data += minSize;
122         size -= minSize;
123     } while (size > 0);
124 }
125 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)126 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
127     if (size < 1) {
128         return 0;
129     }
130     Codec *codec = new Codec();
131     if (!codec) {
132         return 0;
133     }
134     if (codec->initEncoder(data)) {
135         // Consume first byte
136         ++data;
137         --size;
138         codec->encodeFrames(data, size);
139     }
140     delete codec;
141     return 0;
142 }
143