• 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 #include <malloc.h>
21 #include <string.h>
22 #include <algorithm>
23 #include "pvamrwbdecoder.h"
24 #include "pvamrwbdecoder_api.h"
25 
26 // Constants for AMR-WB.
27 constexpr int32_t kSamplesPerFrame = 320;
28 constexpr int32_t kBitsPerSample = 16;
29 constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
30 constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
31 constexpr int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58,
32                                      60, 17, 23, 32, 36, 40, 46, 50};
33 
34 class Codec {
35  public:
36   Codec() = default;
~Codec()37   ~Codec() { deInitDecoder(); }
38   bool initDecoder();
39   void decodeFrames(const uint8_t *data, size_t size);
40   void deInitDecoder();
41 
42  private:
43   void *mAmrHandle = nullptr;
44   int16_t *mDecoderCookie = nullptr;
45   void *mDecoderBuffer = nullptr;
46 };
47 
initDecoder()48 bool Codec::initDecoder() {
49   mDecoderBuffer = malloc(pvDecoder_AmrWbMemRequirements());
50   if (mDecoderBuffer) {
51     pvDecoder_AmrWb_Init(&mAmrHandle, mDecoderBuffer, &mDecoderCookie);
52     return true;
53   } else {
54     return false;
55   }
56 }
57 
deInitDecoder()58 void Codec::deInitDecoder() {
59   if (mDecoderBuffer) {
60     free(mDecoderBuffer);
61     mDecoderBuffer = nullptr;
62   }
63   mAmrHandle = nullptr;
64   mDecoderCookie = nullptr;
65 }
66 
decodeFrames(const uint8_t * data,size_t size)67 void Codec::decodeFrames(const uint8_t *data, size_t size) {
68   RX_State_wb rx_state{};
69   while (size > 0) {
70     uint8_t modeByte = *data;
71     bool quality = modeByte & 0x01;
72     int16 mode = ((modeByte >> 3) & 0x0f);
73     ++data;
74     --size;
75     int32_t frameSize = kFrameSizes[mode];
76     int16_t inputSampleBuf[kMaxSourceDataUnitSize];
77     uint8_t *inputBuf = new uint8_t[frameSize];
78     if (!inputBuf) {
79       return;
80     }
81     int32_t minSize = std::min((int32_t)size, frameSize);
82     memcpy(inputBuf, data, minSize);
83     int16 frameMode = mode;
84     int16 frameType;
85     mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, quality, &rx_state);
86 
87     int16_t numSamplesOutput;
88     int16_t outputBuf[kOutputBufferSize];
89     pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, mDecoderBuffer,
90                     frameType, mDecoderCookie);
91     data += minSize;
92     size -= minSize;
93     delete[] inputBuf;
94   }
95 }
96 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)97 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
98   if (size < 2) {
99     return 0;
100   }
101   Codec *codec = new Codec();
102   if (!codec) {
103     return 0;
104   }
105   if (codec->initDecoder()) {
106     codec->decodeFrames(data, size);
107   }
108   delete codec;
109   return 0;
110 }
111