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 "AmrwbEncoderTest"
19
20 #include <utils/Log.h>
21
22 #include <stdio.h>
23 #include <fstream>
24
25 #include "cmnMemory.h"
26 #include "voAMRWB.h"
27
28 #include "AmrwbEncTestEnvironment.h"
29
30 #define OUTPUT_FILE "/data/local/tmp/amrwbEncode.out"
31 #define VOAMRWB_RFC3267_HEADER_INFO "#!AMR-WB\n"
32
33 constexpr int32_t kInputBufferSize = 640;
34 constexpr int32_t kOutputBufferSize = 1024;
35
36 static AmrwbEncTestEnvironment *gEnv = nullptr;
37
38 class AmrwbEncoderTest : public ::testing::TestWithParam<tuple<string, int32_t,
39 VOAMRWBFRAMETYPE, string>> {
40 public:
AmrwbEncoderTest()41 AmrwbEncoderTest() : mEncoderHandle(nullptr) {
42 tuple<string, int32_t, VOAMRWBFRAMETYPE, string> params = GetParam();
43 mInputFile = gEnv->getRes() + get<0>(params);
44 mMode = get<1>(params);
45 mFrameType = get<2>(params);
46 refFilePath = gEnv->getRes() + get<3>(params);
47 mMemOperator.Alloc = cmnMemAlloc;
48 mMemOperator.Copy = cmnMemCopy;
49 mMemOperator.Free = cmnMemFree;
50 mMemOperator.Set = cmnMemSet;
51 mMemOperator.Check = cmnMemCheck;
52
53 mUserData.memflag = VO_IMF_USERMEMOPERATOR;
54 mUserData.memData = (VO_PTR)(&mMemOperator);
55 }
56
~AmrwbEncoderTest()57 ~AmrwbEncoderTest() {
58 if (mEncoderHandle) {
59 mEncoderHandle = nullptr;
60 }
61 }
62
63 string mInputFile;
64 unsigned char mOutputBuf[kOutputBufferSize];
65 unsigned char mInputBuf[kInputBufferSize];
66 VOAMRWBFRAMETYPE mFrameType;
67 VO_AUDIO_CODECAPI mApiHandle;
68 VO_MEM_OPERATOR mMemOperator;
69 VO_CODEC_INIT_USERDATA mUserData;
70 VO_HANDLE mEncoderHandle;
71 int32_t mMode;
72 string refFilePath;
73
74 bool compareBinaryFiles(const string& refFilePath, const string& outFilePath);
75 };
76
compareBinaryFiles(const std::string & refFilePath,const std::string & outFilePath)77 bool AmrwbEncoderTest::compareBinaryFiles(const std::string &refFilePath,
78 const std::string &outFilePath) {
79 std::ifstream refFile(refFilePath, std::ios::binary | std::ios::ate);
80 std::ifstream outFile(outFilePath, std::ios::binary | std::ios::ate);
81 assert(refFile.is_open() && "Error opening reference file " + refFilePath);
82 assert(outFile.is_open() && "Error opening output file " + outFilePath);
83
84 std::streamsize refFileSize = refFile.tellg();
85 std::streamsize outFileSize = outFile.tellg();
86 if (refFileSize != outFileSize) {
87 ALOGE("Error, File size mismatch: Reference file size = %td bytes,"
88 "but output file size = %td bytes", refFileSize, outFileSize);
89 return false;
90 }
91
92 refFile.seekg(0, std::ios::beg);
93 outFile.seekg(0, std::ios::beg);
94 constexpr std::streamsize kBufferSize = 16 * 1024;
95 char refBuffer[kBufferSize];
96 char outBuffer[kBufferSize];
97
98 while (refFile && outFile) {
99 refFile.read(refBuffer, kBufferSize);
100 outFile.read(outBuffer, kBufferSize);
101
102 std::streamsize refBytesRead = refFile.gcount();
103 std::streamsize outBytesRead = outFile.gcount();
104
105 if (refBytesRead != outBytesRead || memcmp(refBuffer, outBuffer, refBytesRead) != 0) {
106 ALOGE("Error, File content mismatch.");
107 return false;
108 }
109 }
110 return true;
111 }
112
TEST_P(AmrwbEncoderTest,CreateAmrwbEncoderTest)113 TEST_P(AmrwbEncoderTest, CreateAmrwbEncoderTest) {
114 int32_t status = voGetAMRWBEncAPI(&mApiHandle);
115 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to get api handle";
116
117 status = mApiHandle.Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &mUserData);
118 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to init AMRWB encoder";
119
120 status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &mFrameType);
121 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder frame type to " << mFrameType;
122
123 status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mMode);
124 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder mode to %d" << mMode;
125 ALOGV("AMR-WB encoder created successfully");
126
127 status = mApiHandle.Uninit(mEncoderHandle);
128 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to delete AMRWB encoder";
129 ALOGV("AMR-WB encoder deleted successfully");
130 }
131
TEST_P(AmrwbEncoderTest,AmrwbEncodeTest)132 TEST_P(AmrwbEncoderTest, AmrwbEncodeTest) {
133 VO_CODECBUFFER inData;
134 VO_CODECBUFFER outData;
135 VO_AUDIO_OUTPUTINFO outFormat;
136
137 FILE *fpInput = fopen(mInputFile.c_str(), "rb");
138 ASSERT_NE(fpInput, nullptr) << "Error opening input file " << mInputFile;
139
140 FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
141 ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
142
143 uint32_t status = voGetAMRWBEncAPI(&mApiHandle);
144 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to get api handle";
145
146 status = mApiHandle.Init(&mEncoderHandle, VO_AUDIO_CodingAMRWB, &mUserData);
147 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to init AMRWB encoder";
148
149 status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_FRAMETYPE, &mFrameType);
150 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder frame type to " << mFrameType;
151
152 status = mApiHandle.SetParam(mEncoderHandle, VO_PID_AMRWB_MODE, &mMode);
153 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to set AMRWB encoder mode to " << mMode;
154
155 if (mFrameType == VOAMRWB_RFC3267) {
156 /* write RFC3267 Header info to indicate single channel AMR file storage format */
157 int32_t size = strlen(VOAMRWB_RFC3267_HEADER_INFO);
158 memcpy(mOutputBuf, VOAMRWB_RFC3267_HEADER_INFO, size);
159 fwrite(mOutputBuf, 1, size, fpOutput);
160 }
161
162 int32_t frameNum = 0;
163 while (1) {
164 int32_t buffLength =
165 (int32_t)fread(mInputBuf, sizeof(signed char), kInputBufferSize, fpInput);
166
167 if (buffLength == 0 || feof(fpInput)) break;
168 ASSERT_EQ(buffLength, kInputBufferSize) << "Error in reading input file";
169
170 inData.Buffer = (unsigned char *)mInputBuf;
171 inData.Length = buffLength;
172 outData.Buffer = mOutputBuf;
173 status = mApiHandle.SetInputData(mEncoderHandle, &inData);
174 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to setup Input data";
175
176 do {
177 status = mApiHandle.GetOutputData(mEncoderHandle, &outData, &outFormat);
178 ASSERT_NE(status, VO_ERR_LICENSE_ERROR) << "Failed to encode the file";
179 if (status == 0) {
180 frameNum++;
181 fwrite(outData.Buffer, 1, outData.Length, fpOutput);
182 fflush(fpOutput);
183 }
184 } while (status != VO_ERR_INPUT_BUFFER_SMALL);
185 }
186
187 ALOGV("Number of frames processed: %d", frameNum);
188 status = mApiHandle.Uninit(mEncoderHandle);
189 ASSERT_EQ(status, VO_ERR_NONE) << "Failed to delete AMRWB encoder";
190
191 if (fpInput) {
192 fclose(fpInput);
193 }
194 if (fpOutput) {
195 fclose(fpOutput);
196 }
197
198 ASSERT_TRUE(compareBinaryFiles(refFilePath, OUTPUT_FILE))
199 << "Error, Binary file comparison failed: Output file "
200 << OUTPUT_FILE << " does not match the reference file " << refFilePath << ".";
201 }
202
203 INSTANTIATE_TEST_SUITE_P(
204 AmrwbEncoderTestAll, AmrwbEncoderTest,
205 ::testing::Values(
206 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_DEFAULT,
207 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD66_VOAMRWB_DEFAULT_ref.amrwb"),
208 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_DEFAULT,
209 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD885_VOAMRWB_DEFAULT_ref.amrwb"),
210 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_DEFAULT,
211 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1265_VOAMRWB_DEFAULT_ref.amrwb"),
212 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_DEFAULT,
213 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1425_VOAMRWB_DEFAULT_ref.amrwb"),
214 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_DEFAULT,
215 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1585_VOAMRWB_DEFAULT_ref.amrwb"),
216 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_DEFAULT,
217 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1825_VOAMRWB_DEFAULT_ref.amrwb"),
218 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_DEFAULT,
219 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1985_VOAMRWB_DEFAULT_ref.amrwb"),
220 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_DEFAULT,
221 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2305_VOAMRWB_DEFAULT_ref.amrwb"),
222 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_DEFAULT,
223 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2385_VOAMRWB_DEFAULT_ref.amrwb"),
224 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_ITU,
225 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD66_VOAMRWB_ITU_ref.amrwb"),
226 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_ITU,
227 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD885_VOAMRWB_ITU_ref.amrwb"),
228 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_ITU,
229 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1265_VOAMRWB_ITU_ref.amrwb"),
230 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_ITU,
231 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1425_VOAMRWB_ITU_ref.amrwb"),
232 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_ITU,
233 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1585_VOAMRWB_ITU_ref.amrwb"),
234 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_ITU,
235 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1825_VOAMRWB_ITU_ref.amrwb"),
236 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_ITU,
237 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1985_VOAMRWB_ITU_ref.amrwb"),
238 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_ITU,
239 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2305_VOAMRWB_ITU_ref.amrwb"),
240 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_ITU,
241 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2385_VOAMRWB_ITU_ref.amrwb"),
242 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD66, VOAMRWB_RFC3267,
243 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD66_VOAMRWB_RFC3267_ref.amrwb"),
244 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD885, VOAMRWB_RFC3267,
245 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD885_VOAMRWB_RFC3267_ref.amrwb"),
246 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1265, VOAMRWB_RFC3267,
247 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1265_VOAMRWB_RFC3267_ref.amrwb"),
248 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1425, VOAMRWB_RFC3267,
249 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1425_VOAMRWB_RFC3267_ref.amrwb"),
250 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1585, VOAMRWB_RFC3267,
251 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1585_VOAMRWB_RFC3267_ref.amrwb"),
252 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1825, VOAMRWB_RFC3267,
253 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1825_VOAMRWB_RFC3267_ref.amrwb"),
254 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD1985, VOAMRWB_RFC3267,
255 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD1985_VOAMRWB_RFC3267_ref.amrwb"),
256 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2305, VOAMRWB_RFC3267,
257 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2305_VOAMRWB_RFC3267_ref.amrwb"),
258 make_tuple("bbb_raw_1ch_16khz_s16le.raw", VOAMRWB_MD2385, VOAMRWB_RFC3267,
259 "bbb_raw_1ch_16khz_s16le_VOAMRWB_MD2385_VOAMRWB_RFC3267_ref.amrwb")));
260
main(int argc,char ** argv)261 int main(int argc, char **argv) {
262 gEnv = new AmrwbEncTestEnvironment();
263 ::testing::AddGlobalTestEnvironment(gEnv);
264 ::testing::InitGoogleTest(&argc, argv);
265 int status = gEnv->initFromOptions(argc, argv);
266 if (status == 0) {
267 status = RUN_ALL_TESTS();
268 ALOGV("Test result = %d\n", status);
269 }
270 return status;
271 }
272