• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "AmrnbEncoderTest"
19 
20 #include <utils/Log.h>
21 
22 #include <audio_utils/sndfile.h>
23 #include <stdio.h>
24 
25 #include "gsmamr_enc.h"
26 
27 #include "AmrnbEncTestEnvironment.h"
28 
29 #define OUTPUT_FILE "/data/local/tmp/amrnbEncode.out"
30 
31 constexpr int32_t kInputBufferSize = L_FRAME * 2;  // 160 samples * 16-bit per sample.
32 constexpr int32_t kOutputBufferSize = 1024;
33 constexpr int32_t kNumFrameReset = 200;
34 constexpr int32_t kMaxCount = 10;
35 struct AmrNbEncState {
36     void *encCtx;
37     void *pidSyncCtx;
38 };
39 
40 static AmrnbEncTestEnvironment *gEnv = nullptr;
41 
42 class AmrnbEncoderTest : public ::testing::TestWithParam<pair<string, int32_t>> {
43   public:
AmrnbEncoderTest()44     AmrnbEncoderTest() : mAmrEncHandle(nullptr) {}
45 
~AmrnbEncoderTest()46     ~AmrnbEncoderTest() {
47         if (mAmrEncHandle) {
48             free(mAmrEncHandle);
49             mAmrEncHandle = nullptr;
50         }
51     }
52 
53     AmrNbEncState *mAmrEncHandle;
54     int32_t EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
55                          int32_t frameCount = INT32_MAX);
56 };
57 
EncodeFrames(int32_t mode,FILE * fpInput,FILE * mFpOutput,int32_t frameCount)58 int32_t AmrnbEncoderTest::EncodeFrames(int32_t mode, FILE *fpInput, FILE *mFpOutput,
59                                        int32_t frameCount) {
60     int32_t frameNum = 0;
61     uint16_t inputBuf[kInputBufferSize];
62     uint8_t outputBuf[kOutputBufferSize];
63     while (frameNum < frameCount) {
64         int32_t bytesRead = fread(inputBuf, 1, kInputBufferSize, fpInput);
65         if (bytesRead != kInputBufferSize && !feof(fpInput)) {
66             ALOGE("Unable to read data from input file");
67             return -1;
68         } else if (feof(fpInput) && bytesRead == 0) {
69             break;
70         }
71         Frame_Type_3GPP frame_type = (Frame_Type_3GPP)mode;
72         int32_t bytesGenerated =
73                 AMREncode(mAmrEncHandle->encCtx, mAmrEncHandle->pidSyncCtx, (Mode)mode,
74                           (Word16 *)inputBuf, outputBuf, &frame_type, AMR_TX_WMF);
75         frameNum++;
76         if (bytesGenerated < 0) {
77             ALOGE("Error in encoging the file: Invalid output format");
78             return -1;
79         }
80 
81         // Convert from WMF to RFC 3267 format.
82         if (bytesGenerated > 0) {
83             outputBuf[0] = ((outputBuf[0] << 3) | 4) & 0x7c;
84         }
85         fwrite(outputBuf, 1, bytesGenerated, mFpOutput);
86     }
87     return 0;
88 }
89 
TEST_F(AmrnbEncoderTest,CreateAmrnbEncoderTest)90 TEST_F(AmrnbEncoderTest, CreateAmrnbEncoderTest) {
91     mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
92     ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
93     for (int count = 0; count < kMaxCount; count++) {
94         int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
95         ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
96         ALOGV("Successfully created encoder");
97     }
98     if (mAmrEncHandle) {
99         AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
100         ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
101         ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
102         free(mAmrEncHandle);
103         mAmrEncHandle = nullptr;
104         ALOGV("Successfully deleted encoder");
105     }
106 }
107 
TEST_P(AmrnbEncoderTest,EncodeTest)108 TEST_P(AmrnbEncoderTest, EncodeTest) {
109     mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
110     ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
111     int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
112     ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
113 
114     string inputFile = gEnv->getRes() + GetParam().first;
115     FILE *fpInput = fopen(inputFile.c_str(), "rb");
116     ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
117 
118     FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
119     ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
120 
121     // Write file header.
122     fwrite("#!AMR\n", 1, 6, fpOutput);
123 
124     int32_t mode = GetParam().second;
125     int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput);
126     ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
127 
128     fclose(fpOutput);
129     fclose(fpInput);
130 
131     AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
132     ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
133     ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
134     free(mAmrEncHandle);
135     mAmrEncHandle = nullptr;
136     ALOGV("Successfully deleted encoder");
137 }
138 
TEST_P(AmrnbEncoderTest,ResetEncoderTest)139 TEST_P(AmrnbEncoderTest, ResetEncoderTest) {
140     mAmrEncHandle = (AmrNbEncState *)malloc(sizeof(AmrNbEncState));
141     ASSERT_NE(mAmrEncHandle, nullptr) << "Error in allocating memory to Codec handle";
142     int32_t status = AMREncodeInit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx, 0);
143     ASSERT_EQ(status, 0) << "Error creating AMR-NB encoder";
144 
145     string inputFile = gEnv->getRes() + GetParam().first;
146     FILE *fpInput = fopen(inputFile.c_str(), "rb");
147     ASSERT_NE(fpInput, nullptr) << "Error opening input file " << inputFile;
148 
149     FILE *fpOutput = fopen(OUTPUT_FILE, "wb");
150     ASSERT_NE(fpOutput, nullptr) << "Error opening output file " << OUTPUT_FILE;
151 
152     // Write file header.
153     fwrite("#!AMR\n", 1, 6, fpOutput);
154 
155     int32_t mode = GetParam().second;
156     // Encode kNumFrameReset first
157     int32_t encodeErr = EncodeFrames(mode, fpInput, fpOutput, kNumFrameReset);
158     ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
159 
160     status = AMREncodeReset(mAmrEncHandle->encCtx, mAmrEncHandle->pidSyncCtx);
161     ASSERT_EQ(status, 0) << "Error resting AMR-NB encoder";
162 
163     // Start encoding again
164     encodeErr = EncodeFrames(mode, fpInput, fpOutput);
165     ASSERT_EQ(encodeErr, 0) << "EncodeFrames returned error for Codec mode: " << mode;
166 
167     fclose(fpOutput);
168     fclose(fpInput);
169 
170     AMREncodeExit(&mAmrEncHandle->encCtx, &mAmrEncHandle->pidSyncCtx);
171     ASSERT_EQ(mAmrEncHandle->encCtx, nullptr) << "Error deleting AMR-NB encoder";
172     ASSERT_EQ(mAmrEncHandle->pidSyncCtx, nullptr) << "Error deleting AMR-NB encoder";
173     free(mAmrEncHandle);
174     mAmrEncHandle = nullptr;
175     ALOGV("Successfully deleted encoder");
176 }
177 
178 // TODO: Add more test vectors
179 INSTANTIATE_TEST_SUITE_P(AmrnbEncoderTestAll, AmrnbEncoderTest,
180                          ::testing::Values(make_pair("bbb_raw_1ch_8khz_s16le.raw", MR475),
181                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR515),
182                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR59),
183                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR67),
184                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR74),
185                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR795),
186                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR102),
187                                            make_pair("bbb_raw_1ch_8khz_s16le.raw", MR122),
188                                            make_pair("sinesweepraw.raw", MR475),
189                                            make_pair("sinesweepraw.raw", MR515),
190                                            make_pair("sinesweepraw.raw", MR59),
191                                            make_pair("sinesweepraw.raw", MR67),
192                                            make_pair("sinesweepraw.raw", MR74),
193                                            make_pair("sinesweepraw.raw", MR795),
194                                            make_pair("sinesweepraw.raw", MR102),
195                                            make_pair("sinesweepraw.raw", MR122)));
196 
main(int argc,char ** argv)197 int main(int argc, char **argv) {
198     gEnv = new AmrnbEncTestEnvironment();
199     ::testing::AddGlobalTestEnvironment(gEnv);
200     ::testing::InitGoogleTest(&argc, argv);
201     int status = gEnv->initFromOptions(argc, argv);
202     if (status == 0) {
203         status = RUN_ALL_TESTS();
204         ALOGV("Test result = %d\n", status);
205     }
206     return status;
207 }
208