1*a58d3d2aSXin Li /******************************************************************************
2*a58d3d2aSXin Li *
3*a58d3d2aSXin Li * Copyright (C) 2020 The Android Open Source Project
4*a58d3d2aSXin Li *
5*a58d3d2aSXin Li * Licensed under the Apache License, Version 2.0 (the "License");
6*a58d3d2aSXin Li * you may not use this file except in compliance with the License.
7*a58d3d2aSXin Li * You may obtain a copy of the License at:
8*a58d3d2aSXin Li *
9*a58d3d2aSXin Li * http://www.apache.org/licenses/LICENSE-2.0
10*a58d3d2aSXin Li *
11*a58d3d2aSXin Li * Unless required by applicable law or agreed to in writing, software
12*a58d3d2aSXin Li * distributed under the License is distributed on an "AS IS" BASIS,
13*a58d3d2aSXin Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*a58d3d2aSXin Li * See the License for the specific language governing permissions and
15*a58d3d2aSXin Li * limitations under the License.
16*a58d3d2aSXin Li *
17*a58d3d2aSXin Li *****************************************************************************
18*a58d3d2aSXin Li * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*a58d3d2aSXin Li */
20*a58d3d2aSXin Li
21*a58d3d2aSXin Li #include <stdint.h>
22*a58d3d2aSXin Li #include <stdlib.h>
23*a58d3d2aSXin Li #include <string.h>
24*a58d3d2aSXin Li
25*a58d3d2aSXin Li #include <opus.h>
26*a58d3d2aSXin Li
27*a58d3d2aSXin Li /* 4 bytes: packet length, 4 bytes: encoder final range */
28*a58d3d2aSXin Li constexpr int kSetupByteOffset = 8;
29*a58d3d2aSXin Li constexpr int kMaxFrameSample = 5760;
30*a58d3d2aSXin Li const int kSamplingRates[] = {8000, 12000, 16000, 24000, 48000};
31*a58d3d2aSXin Li constexpr int kNumberSamplingRates = sizeof(kSamplingRates) / sizeof(kSamplingRates[0]);
32*a58d3d2aSXin Li
33*a58d3d2aSXin Li #ifdef MULTISTREAM
34*a58d3d2aSXin Li #include "opus_multistream.h"
35*a58d3d2aSXin Li #define OPUS_DEC_DATA_TYPE OpusMSDecoder
36*a58d3d2aSXin Li #define OPUS_DEC_DECODE_API opus_multistream_decode
37*a58d3d2aSXin Li #define OPUS_DEC_CREATE_API ms_opus_decoder_create
38*a58d3d2aSXin Li #define OPUS_DEC_DESTROY_API opus_multistream_decoder_destroy
ms_opus_decoder_create(opus_int32 Fs,int channels,int * error)39*a58d3d2aSXin Li static OpusMSDecoder *ms_opus_decoder_create(opus_int32 Fs, int channels, int *error) {
40*a58d3d2aSXin Li int streams = 1;
41*a58d3d2aSXin Li int coupledStreams = channels == 2;
42*a58d3d2aSXin Li unsigned char mapping[256] = {0, 1};
43*a58d3d2aSXin Li return opus_multistream_decoder_create(Fs, channels, streams, coupledStreams, mapping, error);
44*a58d3d2aSXin Li }
45*a58d3d2aSXin Li #else
46*a58d3d2aSXin Li #define OPUS_DEC_DATA_TYPE OpusDecoder
47*a58d3d2aSXin Li #define OPUS_DEC_DECODE_API opus_decode
48*a58d3d2aSXin Li #define OPUS_DEC_CREATE_API opus_decoder_create
49*a58d3d2aSXin Li #define OPUS_DEC_DESTROY_API opus_decoder_destroy
50*a58d3d2aSXin Li #endif
51*a58d3d2aSXin Li
52*a58d3d2aSXin Li class Codec {
53*a58d3d2aSXin Li public:
54*a58d3d2aSXin Li Codec() = default;
~Codec()55*a58d3d2aSXin Li ~Codec() { deInitDecoder(); }
56*a58d3d2aSXin Li bool initDecoder(const uint8_t *data);
57*a58d3d2aSXin Li void decodeFrames(const uint8_t *data, size_t size);
58*a58d3d2aSXin Li void deInitDecoder();
59*a58d3d2aSXin Li
60*a58d3d2aSXin Li private:
61*a58d3d2aSXin Li int mSamplingRate;
62*a58d3d2aSXin Li int mNoOfChannels;
63*a58d3d2aSXin Li OPUS_DEC_DATA_TYPE *mDec = nullptr;
64*a58d3d2aSXin Li opus_int16 *mPcm = nullptr;
65*a58d3d2aSXin Li };
66*a58d3d2aSXin Li
initDecoder(const uint8_t * data)67*a58d3d2aSXin Li bool Codec::initDecoder(const uint8_t *data) {
68*a58d3d2aSXin Li const uint8_t *tocPtr = &data[kSetupByteOffset];
69*a58d3d2aSXin Li const int bandwidth = opus_packet_get_bandwidth(tocPtr);
70*a58d3d2aSXin Li int samplingRateIndex = bandwidth - OPUS_BANDWIDTH_NARROWBAND;
71*a58d3d2aSXin Li
72*a58d3d2aSXin Li /*bounds check on samplingRateIndex*/
73*a58d3d2aSXin Li if ((samplingRateIndex >= 0) && (samplingRateIndex < kNumberSamplingRates)) {
74*a58d3d2aSXin Li mSamplingRate = kSamplingRates[samplingRateIndex];
75*a58d3d2aSXin Li } else {
76*a58d3d2aSXin Li mSamplingRate = 8000; // set to a default value
77*a58d3d2aSXin Li }
78*a58d3d2aSXin Li
79*a58d3d2aSXin Li mNoOfChannels = opus_packet_get_nb_channels(tocPtr);
80*a58d3d2aSXin Li if ((mNoOfChannels != 1) && (mNoOfChannels != 2)) {
81*a58d3d2aSXin Li mNoOfChannels = 1;
82*a58d3d2aSXin Li }
83*a58d3d2aSXin Li
84*a58d3d2aSXin Li int err;
85*a58d3d2aSXin Li mDec = OPUS_DEC_CREATE_API(mSamplingRate, mNoOfChannels, &err);
86*a58d3d2aSXin Li if (!mDec || err != OPUS_OK) {
87*a58d3d2aSXin Li return false;
88*a58d3d2aSXin Li }
89*a58d3d2aSXin Li size_t sizePcm = sizeof(*mPcm) * kMaxFrameSample * mNoOfChannels;
90*a58d3d2aSXin Li mPcm = static_cast<opus_int16 *>(malloc(sizePcm));
91*a58d3d2aSXin Li if (!mPcm) {
92*a58d3d2aSXin Li return false;
93*a58d3d2aSXin Li }
94*a58d3d2aSXin Li memset(mPcm, 0x0, sizePcm);
95*a58d3d2aSXin Li return true;
96*a58d3d2aSXin Li }
97*a58d3d2aSXin Li
deInitDecoder()98*a58d3d2aSXin Li void Codec::deInitDecoder() {
99*a58d3d2aSXin Li OPUS_DEC_DESTROY_API(mDec);
100*a58d3d2aSXin Li mDec = nullptr;
101*a58d3d2aSXin Li if (mPcm) {
102*a58d3d2aSXin Li free(mPcm);
103*a58d3d2aSXin Li }
104*a58d3d2aSXin Li mPcm = nullptr;
105*a58d3d2aSXin Li }
106*a58d3d2aSXin Li
decodeFrames(const uint8_t * data,size_t size)107*a58d3d2aSXin Li void Codec::decodeFrames(const uint8_t *data, size_t size) {
108*a58d3d2aSXin Li (void)OPUS_DEC_DECODE_API(mDec, data, size, mPcm, kMaxFrameSample, 0 /*fec*/);
109*a58d3d2aSXin Li }
110*a58d3d2aSXin Li
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)111*a58d3d2aSXin Li extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
112*a58d3d2aSXin Li if (size < kSetupByteOffset + 1) {
113*a58d3d2aSXin Li return 0;
114*a58d3d2aSXin Li }
115*a58d3d2aSXin Li Codec *codec = new Codec();
116*a58d3d2aSXin Li if (!codec) {
117*a58d3d2aSXin Li return 0;
118*a58d3d2aSXin Li }
119*a58d3d2aSXin Li if (codec->initDecoder(data)) {
120*a58d3d2aSXin Li codec->decodeFrames(data, size);
121*a58d3d2aSXin Li }
122*a58d3d2aSXin Li delete codec;
123*a58d3d2aSXin Li return 0;
124*a58d3d2aSXin Li }
125