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
21 #include <algorithm>
22
23 #include "opus.h"
24
25 using namespace std;
26
27 constexpr int kFrameDuration = 50;
28 constexpr int kMaxPacket = 1500;
29 constexpr int kMinBitRate = 500;
30 constexpr int kMaxBitRate = 512000;
31
32 constexpr opus_int32 kSampleRates[] = {8000, 12000, 16000, 24000, 48000};
33 constexpr size_t kSampleRatesSize = size(kSampleRates);
34
35 #ifndef MULTISTREAM
36 constexpr int kChannels[] = {1, 2};
37 constexpr size_t kChannelsSize = size(kChannels);
38 #endif
39
40 constexpr int kApplications[] = {OPUS_APPLICATION_VOIP, OPUS_APPLICATION_AUDIO,
41 OPUS_APPLICATION_RESTRICTED_LOWDELAY};
42 constexpr size_t kApplicationsSize = size(kApplications);
43
44 constexpr int kSignals[] = {OPUS_AUTO, OPUS_SIGNAL_VOICE, OPUS_SIGNAL_MUSIC};
45 constexpr size_t kSignalsSize = size(kSignals);
46
47 constexpr int kSetDTX[] = {0, 1};
48 constexpr size_t kSetDTXSize = size(kSetDTX);
49
50 constexpr int kSetVBR[] = {0, 1};
51 constexpr size_t kSetVBRSize = size(kSetVBR);
52
53 constexpr int kSetInbandFec[] = {0, 1};
54 constexpr size_t kSetInbandFecSize = size(kSetInbandFec);
55
56 constexpr int kSetVBRConstraint[] = {0, 1};
57 constexpr size_t kSetVBRConstraintSize = size(kSetVBRConstraint);
58
59 constexpr int kSetPredDisable[] = {0, 1};
60 constexpr size_t kSetPredDisableSize = size(kSetPredDisable);
61
62 constexpr int kComplexities[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
63 constexpr size_t kComplexitiesSize = size(kComplexities);
64
65 constexpr int kForceChannels[] = {OPUS_AUTO, 1, 2};
66 constexpr size_t kForceChannelsSize = size(kForceChannels);
67
68 constexpr int kMaxBandwidths[] = {OPUS_BANDWIDTH_NARROWBAND, OPUS_BANDWIDTH_MEDIUMBAND,
69 OPUS_BANDWIDTH_WIDEBAND, OPUS_BANDWIDTH_SUPERWIDEBAND,
70 OPUS_BANDWIDTH_FULLBAND};
71 constexpr size_t kMaxBandwidthsSize = size(kMaxBandwidths);
72
73 constexpr int kPacketLossPerc[] = {0, 1, 2, 5};
74 constexpr size_t kPacketLossPercSize = size(kPacketLossPerc);
75
76 constexpr int kLsbDepths[] = {8, 24};
77 constexpr size_t kLsbDepthsSize = size(kLsbDepths);
78
79 constexpr int kFrameDurations[] = {
80 OPUS_FRAMESIZE_2_5_MS, OPUS_FRAMESIZE_5_MS, OPUS_FRAMESIZE_10_MS,
81 OPUS_FRAMESIZE_20_MS, OPUS_FRAMESIZE_40_MS, OPUS_FRAMESIZE_60_MS,
82 OPUS_FRAMESIZE_80_MS, OPUS_FRAMESIZE_100_MS, OPUS_FRAMESIZE_120_MS};
83 constexpr size_t kFrameDurationsSize = size(kFrameDurations);
84
85 #ifdef MULTISTREAM
86 #include "opus_multistream.h"
87 #define OPUS_ENC_DATA_TYPE OpusMSEncoder
88 #define OPUS_ENC_ENCODE_API opus_multistream_encode
89 #define OPUS_ENC_CTL_API opus_multistream_encoder_ctl
90 #define OPUS_ENC_CREATE_API ms_opus_encoder_create
91 #define OPUS_ENC_DESTROY_API opus_multistream_encoder_destroy
ms_opus_encoder_create(opus_int32 sampleRate,int channels,int application,int * error)92 static OpusMSEncoder* ms_opus_encoder_create(opus_int32 sampleRate, int channels, int application,
93 int* error) {
94 unsigned char* mapping = (unsigned char*)malloc(sizeof(unsigned char) * channels);
95 if (!mapping) {
96 *error = 1;
97 return nullptr;
98 }
99 for (unsigned char x = 0; x < channels; ++x) {
100 mapping[x] = x;
101 }
102 OpusMSEncoder* enc = opus_multistream_encoder_create(sampleRate, channels, 1, channels - 1,
103 mapping, application, error);
104 free(mapping);
105 return enc;
106 }
107 #else
108 #define OPUS_ENC_DATA_TYPE OpusEncoder
109 #define OPUS_ENC_ENCODE_API opus_encode
110 #define OPUS_ENC_CTL_API opus_encoder_ctl
111 #define OPUS_ENC_CREATE_API opus_encoder_create
112 #define OPUS_ENC_DESTROY_API opus_encoder_destroy
113 #endif
114
115 enum {
116 IDX_SAMPLE_RATE_INDEX = 0,
117 IDX_CHANNEL,
118 IDX_BIT_RATE_1,
119 IDX_BIT_RATE_2,
120 IDX_BIT_RATE_3,
121 IDX_COMPLEXITY,
122 IDX_APPLICATION,
123 IDX_SET_DTX,
124 IDX_SET_SIGNAL,
125 IDX_SET_VBR,
126 IDX_SET_VBR_CONSTRAINT,
127 IDX_FORCE_CHANNEL_INDEX,
128 IDX_SET_MAX_BANDWIDTH,
129 IDX_SET_INBAND_FEC,
130 IDX_SET_PACKET_LOSS_PERC,
131 IDX_SET_LSB_DEPTH,
132 IDX_SET_PREDICTION_DISABLED,
133 IDX_FRAME_ENUM,
134 IDX_LAST
135 };
136
137 template <typename type1, typename type2, typename type3>
generateNumberInRangeFromData(type1 data,type2 min,type3 max)138 auto generateNumberInRangeFromData(type1 data, type2 min, type3 max) -> decltype(max) {
139 return (data % (1 + max - min)) + min;
140 }
141
142 class Codec {
143 public:
~Codec()144 ~Codec() { deInitEncoder(); }
145 bool initEncoder(uint8_t** dataPtr, size_t* sizePtr);
146 void encodeFrames(const uint8_t* data, size_t size);
147 void deInitEncoder();
148
149 private:
150 OPUS_ENC_DATA_TYPE* mEncoder = nullptr;
151 int mChannels = 0;
152 int mNumSamplesPerFrame = 0;
153 size_t mFrameSize = 0;
154 size_t mNumPcmBytesPerInputFrame = 0;
155 };
156
get_frame_size(int frameSizeEnum,int samplingRate)157 int get_frame_size(int frameSizeEnum, int samplingRate) {
158 int frameSize = 0;
159 switch (frameSizeEnum) {
160 case OPUS_FRAMESIZE_2_5_MS:
161 frameSize = samplingRate / 400;
162 break;
163 case OPUS_FRAMESIZE_5_MS:
164 frameSize = samplingRate / 200;
165 break;
166 case OPUS_FRAMESIZE_10_MS:
167 frameSize = samplingRate / 100;
168 break;
169 case OPUS_FRAMESIZE_20_MS:
170 frameSize = samplingRate / 50;
171 break;
172 case OPUS_FRAMESIZE_40_MS:
173 frameSize = samplingRate / 25;
174 break;
175 case OPUS_FRAMESIZE_60_MS:
176 frameSize = 3 * samplingRate / 50;
177 break;
178 case OPUS_FRAMESIZE_80_MS:
179 frameSize = 4 * samplingRate / 50;
180 break;
181 case OPUS_FRAMESIZE_100_MS:
182 frameSize = 5 * samplingRate / 50;
183 break;
184 case OPUS_FRAMESIZE_120_MS:
185 frameSize = 6 * samplingRate / 50;
186 break;
187 default:
188 break;
189 }
190 return frameSize;
191 }
192
initEncoder(uint8_t ** dataPtr,size_t * sizePtr)193 bool Codec::initEncoder(uint8_t** dataPtr, size_t* sizePtr) {
194 uint8_t* data = *dataPtr;
195
196 int sampleRateIndex = data[IDX_SAMPLE_RATE_INDEX] % kSampleRatesSize;
197 opus_int32 sampleRate = kSampleRates[sampleRateIndex];
198
199 #ifdef MULTISTREAM
200 mChannels = generateNumberInRangeFromData(data[IDX_CHANNEL], 1, 255);
201 #else
202 int channelIndex = data[IDX_CHANNEL] % kChannelsSize;
203 mChannels = kChannels[channelIndex];
204 #endif
205
206 mNumSamplesPerFrame = sampleRate / kFrameDuration;
207 mNumPcmBytesPerInputFrame = mChannels * mNumSamplesPerFrame * sizeof(int16_t);
208
209 int application = kApplications[data[IDX_APPLICATION] % kApplicationsSize];
210 int err = 0;
211 mEncoder = OPUS_ENC_CREATE_API(sampleRate, mChannels, application, &err);
212 if (err) {
213 return false;
214 }
215 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_APPLICATION(application));
216
217 int complexityIndex = data[IDX_COMPLEXITY] % kComplexitiesSize;
218 int complexity = kComplexities[complexityIndex];
219 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_COMPLEXITY(complexity));
220
221 int setDTXIndex = data[IDX_SET_DTX] % kSetDTXSize;
222 int setDTX = kSetDTX[setDTXIndex];
223 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_DTX(setDTX));
224
225 int signalIndex = data[IDX_SET_SIGNAL] % kSignalsSize;
226 int signal = kSignals[signalIndex];
227 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_SIGNAL(signal));
228
229 int setVBRIndex = data[IDX_SET_VBR] % kSetVBRSize;
230 int setVBR = kSetVBR[setVBRIndex];
231 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_VBR(setVBR));
232
233 int setVBRConstraintIndex = data[IDX_SET_VBR_CONSTRAINT] % kSetVBRConstraintSize;
234 int setVBRConstraint = kSetVBRConstraint[setVBRConstraintIndex];
235 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_VBR_CONSTRAINT(setVBRConstraint));
236
237 // Clubbing 3 bytes of data to ensure bit rate in the range [kMinBitRate, kMaxBitRate]
238 uint32_t tempValue =
239 (data[IDX_BIT_RATE_1] << 16) | (data[IDX_BIT_RATE_2] << 8) | data[IDX_BIT_RATE_3];
240 uint32_t bitRate = generateNumberInRangeFromData(tempValue, kMinBitRate, kMaxBitRate);
241 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_BITRATE(bitRate));
242
243 int forceChanneIndex = data[IDX_FORCE_CHANNEL_INDEX] % kForceChannelsSize;
244 int forceChannel = kForceChannels[forceChanneIndex];
245 forceChannel = min(forceChannel, mChannels);
246 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_FORCE_CHANNELS(forceChannel));
247
248 int maxBandwidthIndex = data[IDX_SET_MAX_BANDWIDTH] % kMaxBandwidthsSize;
249 opus_int32 maxBandwidth = kMaxBandwidths[maxBandwidthIndex];
250 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_MAX_BANDWIDTH(maxBandwidth));
251
252 int setInbandFecIndex = data[IDX_SET_INBAND_FEC] % kSetInbandFecSize;
253 int setInbandFec = kSetInbandFec[setInbandFecIndex];
254 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_INBAND_FEC(setInbandFec));
255
256 int pktLossIndex = data[IDX_SET_PACKET_LOSS_PERC] % kPacketLossPercSize;
257 int pktLoss = kPacketLossPerc[pktLossIndex];
258 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_PACKET_LOSS_PERC(pktLoss));
259
260 int lsbDepthIndex = data[IDX_SET_LSB_DEPTH] % kLsbDepthsSize;
261 int lsbDepth = kLsbDepths[lsbDepthIndex];
262 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_LSB_DEPTH(lsbDepth));
263
264 int setPredDisableIndex = data[IDX_SET_PREDICTION_DISABLED] % kSetPredDisableSize;
265 int setPredDisable = kSetPredDisable[setPredDisableIndex];
266 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_PREDICTION_DISABLED(setPredDisable));
267
268 int frameSizesEnumIndex = data[IDX_FRAME_ENUM] % kFrameDurationsSize;
269 int frameSizeEnum = kFrameDurations[frameSizesEnumIndex];
270 OPUS_ENC_CTL_API(mEncoder, OPUS_SET_EXPERT_FRAME_DURATION(frameSizeEnum));
271
272 mFrameSize = get_frame_size(frameSizeEnum, sampleRate);
273 if (mFrameSize == 0) {
274 return false;
275 }
276
277 // Not re-using the data which was used for configuration for encoding
278 *dataPtr += IDX_LAST;
279 *sizePtr -= IDX_LAST;
280 return true;
281 }
282
encodeFrames(const uint8_t * data,size_t size)283 void Codec::encodeFrames(const uint8_t* data, size_t size) {
284 opus_int16* inputBuffer = (opus_int16*)data;
285 size = size / sizeof(opus_int16);
286 size_t offset = 0;
287 do {
288 size_t frameSize = mFrameSize / mChannels;
289 if (frameSize > (size - offset)) {
290 frameSize = size - offset;
291 }
292 unsigned char packet[kMaxPacket];
293 (void)OPUS_ENC_ENCODE_API(mEncoder, &inputBuffer[offset], frameSize, packet, kMaxPacket);
294 offset += mFrameSize * mChannels;
295 } while (offset < size);
296 }
297
deInitEncoder()298 void Codec::deInitEncoder() {
299 if (mEncoder) {
300 OPUS_ENC_DESTROY_API(mEncoder);
301 mEncoder = nullptr;
302 }
303 }
304
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)305 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
306 if (size < IDX_LAST) {
307 return 0;
308 }
309 Codec encoder;
310 if (encoder.initEncoder(const_cast<uint8_t**>(&data), &size)) {
311 encoder.encodeFrames(data, size);
312 }
313 return 0;
314 }
315