• 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 <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