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