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