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 <stdint.h>
22 #include <stdlib.h>
23 #include <string.h>
24
25 #include <opus.h>
26
27 /* 4 bytes: packet length, 4 bytes: encoder final range */
28 constexpr int kSetupByteOffset = 8;
29 constexpr int kMaxFrameSample = 5760;
30 const int kSamplingRates[] = {8000, 12000, 16000, 24000, 48000};
31 constexpr int kNumberSamplingRates = sizeof(kSamplingRates) / sizeof(kSamplingRates[0]);
32
33 #ifdef MULTISTREAM
34 #include "opus_multistream.h"
35 #define OPUS_DEC_DATA_TYPE OpusMSDecoder
36 #define OPUS_DEC_DECODE_API opus_multistream_decode
37 #define OPUS_DEC_CREATE_API ms_opus_decoder_create
38 #define OPUS_DEC_DESTROY_API opus_multistream_decoder_destroy
ms_opus_decoder_create(opus_int32 Fs,int channels,int * error)39 static OpusMSDecoder *ms_opus_decoder_create(opus_int32 Fs, int channels, int *error) {
40 int streams = 1;
41 int coupledStreams = channels == 2;
42 unsigned char mapping[256] = {0, 1};
43 return opus_multistream_decoder_create(Fs, channels, streams, coupledStreams, mapping, error);
44 }
45 #else
46 #define OPUS_DEC_DATA_TYPE OpusDecoder
47 #define OPUS_DEC_DECODE_API opus_decode
48 #define OPUS_DEC_CREATE_API opus_decoder_create
49 #define OPUS_DEC_DESTROY_API opus_decoder_destroy
50 #endif
51
52 class Codec {
53 public:
54 Codec() = default;
~Codec()55 ~Codec() { deInitDecoder(); }
56 bool initDecoder(const uint8_t *data);
57 void decodeFrames(const uint8_t *data, size_t size);
58 void deInitDecoder();
59
60 private:
61 int mSamplingRate;
62 int mNoOfChannels;
63 OPUS_DEC_DATA_TYPE *mDec = nullptr;
64 opus_int16 *mPcm = nullptr;
65 };
66
initDecoder(const uint8_t * data)67 bool Codec::initDecoder(const uint8_t *data) {
68 const uint8_t *tocPtr = &data[kSetupByteOffset];
69 const int bandwidth = opus_packet_get_bandwidth(tocPtr);
70 int samplingRateIndex = bandwidth - OPUS_BANDWIDTH_NARROWBAND;
71
72 /*bounds check on samplingRateIndex*/
73 if ((samplingRateIndex >= 0) && (samplingRateIndex < kNumberSamplingRates)) {
74 mSamplingRate = kSamplingRates[samplingRateIndex];
75 } else {
76 mSamplingRate = 8000; // set to a default value
77 }
78
79 mNoOfChannels = opus_packet_get_nb_channels(tocPtr);
80 if ((mNoOfChannels != 1) && (mNoOfChannels != 2)) {
81 mNoOfChannels = 1;
82 }
83
84 int err;
85 mDec = OPUS_DEC_CREATE_API(mSamplingRate, mNoOfChannels, &err);
86 if (!mDec || err != OPUS_OK) {
87 return false;
88 }
89 size_t sizePcm = sizeof(*mPcm) * kMaxFrameSample * mNoOfChannels;
90 mPcm = static_cast<opus_int16 *>(malloc(sizePcm));
91 if (!mPcm) {
92 return false;
93 }
94 memset(mPcm, 0x0, sizePcm);
95 return true;
96 }
97
deInitDecoder()98 void Codec::deInitDecoder() {
99 OPUS_DEC_DESTROY_API(mDec);
100 mDec = nullptr;
101 if (mPcm) {
102 free(mPcm);
103 }
104 mPcm = nullptr;
105 }
106
decodeFrames(const uint8_t * data,size_t size)107 void Codec::decodeFrames(const uint8_t *data, size_t size) {
108 (void)OPUS_DEC_DECODE_API(mDec, data, size, mPcm, kMaxFrameSample, 0 /*fec*/);
109 }
110
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)111 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
112 if (size < kSetupByteOffset + 1) {
113 return 0;
114 }
115 Codec *codec = new Codec();
116 if (!codec) {
117 return 0;
118 }
119 if (codec->initDecoder(data)) {
120 codec->decodeFrames(data, size);
121 }
122 delete codec;
123 return 0;
124 }
125