1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "AmrwbDecoderTest"
19 #define OUTPUT_FILE "/data/local/tmp/amrwbDecode.out"
20 
21 #include <utils/Log.h>
22 
23 #include <audio_utils/sndfile.h>
24 #include <stdio.h>
25 
26 #include "pvamrwbdecoder.h"
27 #include "pvamrwbdecoder_api.h"
28 
29 #include "AmrwbDecTestEnvironment.h"
30 
31 // Constants for AMR-WB.
32 constexpr int32_t kInputBufferSize = 64;
33 constexpr int32_t kSamplesPerFrame = 320;
34 constexpr int32_t kBitsPerSample = 16;
35 constexpr int32_t kSampleRate = 16000;
36 constexpr int32_t kChannels = 1;
37 constexpr int32_t kMaxSourceDataUnitSize = KAMRWB_NB_BITS_MAX * sizeof(int16_t);
38 constexpr int32_t kOutputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
39 const int32_t kFrameSizes[16] = {17, 23, 32, 36, 40, 46, 50, 58, 60, -1, -1, -1, -1, -1, -1, -1};
40 constexpr int32_t kNumFrameReset = 150;
41 
42 constexpr int32_t kMaxCount = 10;
43 
44 static AmrwbDecTestEnvironment *gEnv = nullptr;
45 
46 class AmrwbDecoderTest : public ::testing::TestWithParam<string> {
47   public:
AmrwbDecoderTest()48     AmrwbDecoderTest() : mFpInput(nullptr) {}
49 
~AmrwbDecoderTest()50     ~AmrwbDecoderTest() {
51         if (mFpInput) {
52             fclose(mFpInput);
53             mFpInput = nullptr;
54         }
55     }
56 
57     FILE *mFpInput;
58     int32_t DecodeFrames(int16_t *decoderCookie, void *decoderBuf, SNDFILE *outFileHandle,
59                          int32_t frameCount = INT32_MAX);
60     SNDFILE *openOutputFile(SF_INFO *sfInfo);
61 };
62 
openOutputFile(SF_INFO * sfInfo)63 SNDFILE *AmrwbDecoderTest::openOutputFile(SF_INFO *sfInfo) {
64     memset(sfInfo, 0, sizeof(SF_INFO));
65     sfInfo->channels = kChannels;
66     sfInfo->format = SF_FORMAT_WAV | SF_FORMAT_PCM_16;
67     sfInfo->samplerate = kSampleRate;
68     SNDFILE *outFileHandle = sf_open(OUTPUT_FILE, SFM_WRITE, sfInfo);
69     return outFileHandle;
70 }
71 
DecodeFrames(int16_t * decoderCookie,void * decoderBuf,SNDFILE * outFileHandle,int32_t frameCount)72 int32_t AmrwbDecoderTest::DecodeFrames(int16_t *decoderCookie, void *decoderBuf,
73                                        SNDFILE *outFileHandle, int32_t frameCount) {
74     uint8_t inputBuf[kInputBufferSize];
75     int16_t inputSampleBuf[kMaxSourceDataUnitSize];
76     int16_t outputBuf[kOutputBufferSize];
77     RX_State_wb rx_state{};
78 
79     while (frameCount > 0) {
80         uint8_t modeByte;
81         int32_t bytesRead = fread(&modeByte, 1, 1, mFpInput);
82         if (bytesRead != 1) break;
83 
84         int16 mode = ((modeByte >> 3) & 0x0f);
85         if (mode >= 9) {
86             // Produce silence for comfort noise, speech lost and no data.
87             int32_t outputBufferSize = kSamplesPerFrame * kBitsPerSample / 8;
88             memset(outputBuf, 0, outputBufferSize);
89         } else {
90             // Read rest of the frame.
91             int32_t frameSize = kFrameSizes[mode];
92             // AMR-WB file format cannot have mode 10, 11, 12 and 13.
93             if (frameSize < 0) {
94                 ALOGE("Illegal frame mode");
95                 return -1;
96             }
97             bytesRead = fread(inputBuf, 1, frameSize, mFpInput);
98             if (bytesRead != frameSize) break;
99 
100             int16 frameMode = mode;
101             int16 frameType;
102             mime_unsorting(inputBuf, inputSampleBuf, &frameType, &frameMode, 1, &rx_state);
103 
104             int16_t numSamplesOutput;
105             pvDecoder_AmrWb(frameMode, inputSampleBuf, outputBuf, &numSamplesOutput, decoderBuf,
106                             frameType, decoderCookie);
107             if (numSamplesOutput != kSamplesPerFrame) {
108                 ALOGE("Failed to decode the input file");
109                 return -1;
110             }
111             for (int count = 0; count < kSamplesPerFrame; ++count) {
112                 /* Delete the 2 LSBs (14-bit output) */
113                 outputBuf[count] &= 0xfffc;
114             }
115         }
116         sf_writef_short(outFileHandle, outputBuf, kSamplesPerFrame / kChannels);
117         frameCount--;
118     }
119     return 0;
120 }
121 
TEST_F(AmrwbDecoderTest,MultiCreateAmrwbDecoderTest)122 TEST_F(AmrwbDecoderTest, MultiCreateAmrwbDecoderTest) {
123     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
124     void *decoderBuf = malloc(memRequirements);
125     ASSERT_NE(decoderBuf, nullptr)
126             << "Failed to allocate decoder memory of size " << memRequirements;
127 
128     // Create AMR-WB decoder instance.
129     void *amrHandle = nullptr;
130     int16_t *decoderCookie;
131     for (int count = 0; count < kMaxCount; count++) {
132         pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
133         ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
134         ALOGV("Decoder created successfully");
135     }
136     if (decoderBuf) {
137         free(decoderBuf);
138         decoderBuf = nullptr;
139     }
140 }
141 
TEST_P(AmrwbDecoderTest,DecodeTest)142 TEST_P(AmrwbDecoderTest, DecodeTest) {
143     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
144     void *decoderBuf = malloc(memRequirements);
145     ASSERT_NE(decoderBuf, nullptr)
146             << "Failed to allocate decoder memory of size " << memRequirements;
147 
148     void *amrHandle = nullptr;
149     int16_t *decoderCookie;
150     pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
151     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
152 
153     string inputFile = gEnv->getRes() + GetParam();
154     mFpInput = fopen(inputFile.c_str(), "rb");
155     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
156 
157     // Open the output file.
158     SF_INFO sfInfo;
159     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
160     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
161 
162     int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
163     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
164 
165     sf_close(outFileHandle);
166     if (decoderBuf) {
167         free(decoderBuf);
168         decoderBuf = nullptr;
169     }
170 }
171 
TEST_P(AmrwbDecoderTest,ResetDecoderTest)172 TEST_P(AmrwbDecoderTest, ResetDecoderTest) {
173     uint32_t memRequirements = pvDecoder_AmrWbMemRequirements();
174     void *decoderBuf = malloc(memRequirements);
175     ASSERT_NE(decoderBuf, nullptr)
176             << "Failed to allocate decoder memory of size " << memRequirements;
177 
178     void *amrHandle = nullptr;
179     int16_t *decoderCookie;
180     pvDecoder_AmrWb_Init(&amrHandle, decoderBuf, &decoderCookie);
181     ASSERT_NE(amrHandle, nullptr) << "Failed to initialize decoder";
182 
183     string inputFile = gEnv->getRes() + GetParam();
184     mFpInput = fopen(inputFile.c_str(), "rb");
185     ASSERT_NE(mFpInput, nullptr) << "Error opening input file " << inputFile;
186 
187     // Open the output file.
188     SF_INFO sfInfo;
189     SNDFILE *outFileHandle = openOutputFile(&sfInfo);
190     ASSERT_NE(outFileHandle, nullptr) << "Error opening output file for writing decoded output";
191 
192     // Decode 150 frames first
193     int32_t decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle, kNumFrameReset);
194     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
195 
196     // Reset Decoder
197     pvDecoder_AmrWb_Reset(decoderBuf, 1);
198 
199     // Start decoding again
200     decoderErr = DecodeFrames(decoderCookie, decoderBuf, outFileHandle);
201     ASSERT_EQ(decoderErr, 0) << "DecodeFrames returned error";
202 
203     sf_close(outFileHandle);
204     if (decoderBuf) {
205         free(decoderBuf);
206     }
207 }
208 
209 INSTANTIATE_TEST_SUITE_P(AmrwbDecoderTestAll, AmrwbDecoderTest,
210                          ::testing::Values(("bbb_amrwb_1ch_14kbps_16000hz.amrwb"),
211                                            ("bbb_16000hz_1ch_9kbps_amrwb_30sec.amrwb")));
212 
main(int argc,char ** argv)213 int main(int argc, char **argv) {
214     gEnv = new AmrwbDecTestEnvironment();
215     ::testing::AddGlobalTestEnvironment(gEnv);
216     ::testing::InitGoogleTest(&argc, argv);
217     int status = gEnv->initFromOptions(argc, argv);
218     if (status == 0) {
219         status = RUN_ALL_TESTS();
220         ALOGV("Test result = %d\n", status);
221     }
222     return status;
223 }
224