• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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