1 /*
2 * Copyright (C) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "gtest/gtest.h"
17 #include "audio_ffmpeg_aac_encoder_plugin.h"
18 #include "audio_ffmpeg_flac_encoder_plugin.h"
19 #include <set>
20 #include <fstream>
21 #include "media_description.h"
22 #include "avcodec_errors.h"
23 #include "avcodec_trace.h"
24 #include "avcodec_log.h"
25 #include "avcodec_mime_type.h"
26 #include "avcodec_audio_common.h"
27 #include "ffmpeg_converter.h"
28 #include "audio_codec_adapter.h"
29 #include "meta/format.h"
30 #include "avcodec_audio_decoder.h"
31 #include "avcodec_codec_name.h"
32
33 using namespace std;
34 using namespace OHOS::Media;
35 using namespace testing::ext;
36
37 namespace {
38 constexpr int32_t MIN_CHANNELS = 2;
39 constexpr int32_t MAX_CHANNELS = 8;
40 constexpr int32_t AAC_SAMPLE_RATE = 44100;
41 constexpr int32_t AAC_BITRATE = 128000;
42 constexpr int32_t DEFAULT_AAC_TYPE = 1;
43 constexpr int32_t BUFFER_SIZE = 6400;
44 constexpr std::string_view AAC_NAME = "aac_enc_buffer";
45 constexpr std::string_view FLAC_NAME = "flac_enc_buffer";
46 constexpr uint32_t META_SIZE = 6400;
47 constexpr int32_t FLAC_CHANNELS = 2;
48 constexpr int32_t FLAC_ENC_SAMPLE_RATE = 32000;
49 constexpr int32_t FLAC_BITRATE = 32000;
50 constexpr int32_t ONE_FRAME_SIZE = 64000;
51 constexpr int32_t COMPLIANCE_LEVEL = 2;
52 }
53
54 namespace OHOS {
55 namespace MediaAVCodec {
56 class AudioEncPluginUnitTest : public testing::Test {
57 public:
58 static void SetUpTestCase(void);
59 static void TearDownTestCase(void);
60 void SetUp();
61 void TearDown();
62 void PrepareFlacEncoder();
63 std::shared_ptr<AudioBufferInfo> CreateAudioBuffer(const std::vector<int16_t> &data, size_t offset,
64 size_t size, int64_t pts, bool isEos);
65 bool ProcessAudioData(const std::vector<int16_t> &pcmData, size_t offset, size_t size, int64_t pts);
66 bool FlushEncoder();
67
68 protected:
69 OHOS::MediaAVCodec::Format aacFormat_;
70 OHOS::MediaAVCodec::Format flacFormat_;
71 std::shared_ptr<AudioFFMpegAacEncoderPlugin> aacEncPlugin_ = {nullptr};
72 std::shared_ptr<AudioFFMpegFlacEncoderPlugin> flacEncPlugin_ = {nullptr};
73 };
74
SetUpTestCase(void)75 void AudioEncPluginUnitTest::SetUpTestCase(void)
76 {
77 cout << "[SetUpTestCase]: " << endl;
78 }
79
TearDownTestCase(void)80 void AudioEncPluginUnitTest::TearDownTestCase(void)
81 {
82 cout << "[TearDownTestCase]: " << endl;
83 }
84
SetUp(void)85 void AudioEncPluginUnitTest::SetUp(void)
86 {
87 aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, MAX_CHANNELS);
88 aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, AAC_SAMPLE_RATE);
89 aacFormat_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, AAC_BITRATE);
90 aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
91 aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_AAC_IS_ADTS, DEFAULT_AAC_TYPE);
92
93 flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, FLAC_CHANNELS);
94 flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
95 flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_SAMPLE_RATE, FLAC_ENC_SAMPLE_RATE);
96 flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_BITRATE, FLAC_BITRATE);
97 flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_BITS_PER_CODED_SAMPLE, SAMPLE_S16LE);
98 flacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_COMPLIANCE_LEVEL, COMPLIANCE_LEVEL);
99 flacFormat_.PutLongValue(MediaDescriptionKey::MD_KEY_CHANNEL_LAYOUT, AudioChannelLayout::STEREO);
100
101 aacEncPlugin_ = std::make_shared<AudioFFMpegAacEncoderPlugin>();
102 flacEncPlugin_ = std::make_shared<AudioFFMpegFlacEncoderPlugin>();
103 cout << "[SetUp]: SetUp!!!" << endl;
104 }
105
TearDown(void)106 void AudioEncPluginUnitTest::TearDown(void)
107 {
108 if (aacEncPlugin_) {
109 aacEncPlugin_->Release();
110 }
111 if (flacEncPlugin_) {
112 flacEncPlugin_->Release();
113 }
114 cout << "[TearDown]: over!!!" << endl;
115 }
116
PrepareFlacEncoder()117 void AudioEncPluginUnitTest::PrepareFlacEncoder()
118 {
119 int32_t ret = flacEncPlugin_->Init(flacFormat_);
120 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
121 cout << "Failed to initialize FLAC encoder" << endl;
122 }
123 }
124
CreateAudioBuffer(const std::vector<int16_t> & data,size_t offset,size_t size,int64_t pts,bool isEos)125 std::shared_ptr<AudioBufferInfo> AudioEncPluginUnitTest::CreateAudioBuffer(const std::vector<int16_t> &data,
126 size_t offset, size_t size, int64_t pts, bool isEos)
127 {
128 auto buffer = std::make_shared<AudioBufferInfo>(size, FLAC_NAME, ONE_FRAME_SIZE);
129 auto memory = buffer->GetBuffer();
130 if (!memory) {
131 cout << "Failed to allocate memory for audio buffer" << endl;
132 return nullptr;
133 }
134
135 if (size > 0) {
136 if (memcpy_s(memory->GetBase(), memory->GetSize(), data.data() + offset, size) != EOK) {
137 cout << "Fatal: memory copy failed (size=" << size
138 << ", dest_size=" << memory->GetSize() << ")" << endl;
139 }
140 }
141
142 AVCodecBufferInfo attr = {};
143 attr.size = size;
144 attr.presentationTimeUs = pts;
145 buffer->SetBufferAttr(attr);
146 buffer->SetEos(isEos);
147
148 return buffer;
149 }
150
ProcessAudioData(const std::vector<int16_t> & pcmData,size_t offset,size_t size,int64_t pts)151 bool AudioEncPluginUnitTest::ProcessAudioData(const std::vector<int16_t> &pcmData, size_t offset,
152 size_t size, int64_t pts)
153 {
154 auto inputBuffer = CreateAudioBuffer(pcmData, offset, size, pts, false);
155 if (!inputBuffer) {
156 return false;
157 }
158
159 int32_t ret = flacEncPlugin_->ProcessSendData(inputBuffer);
160 while (true) {
161 auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, FLAC_NAME, ONE_FRAME_SIZE);
162 ret = flacEncPlugin_->ProcessRecieveData(outputBuffer);
163 if (ret == AVCodecServiceErrCode::AVCS_ERR_NOT_ENOUGH_DATA) {
164 break;
165 }
166 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
167 cout <<"Failed to receive encoded data: " << ret << endl;
168 return false;
169 }
170 }
171 return true;
172 }
173
FlushEncoder()174 bool AudioEncPluginUnitTest::FlushEncoder()
175 {
176 auto eosBuffer = CreateAudioBuffer({}, 0, 0, 0, true);
177 if (!eosBuffer) {
178 return false;
179 }
180
181 int32_t ret = flacEncPlugin_->ProcessSendData(eosBuffer);
182 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
183 cout << "Failed to send EOS: " << ret << endl;
184 }
185
186 while (true) {
187 auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, FLAC_NAME, ONE_FRAME_SIZE);
188 ret = flacEncPlugin_->ProcessRecieveData(outputBuffer);
189 if (ret == AVCodecServiceErrCode::AVCS_ERR_END_OF_STREAM) {
190 break;
191 }
192 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
193 cout << "Error during flush: " << ret << endl;
194 return false;
195 }
196 }
197 return true;
198 }
199
200
201 HWTEST_F(AudioEncPluginUnitTest, CheckBitRate_Aac_001, TestSize.Level1)
202 {
203 aacFormat_.PutLongValue(MediaDescriptionKey::MD_KEY_BITRATE, -44100); // invalid
204 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
205 }
206
207 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_001, TestSize.Level1)
208 {
209 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
210 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Release());
211 auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
212 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
213 }
214
215 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_002, TestSize.Level1)
216 {
217 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
218 auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
219 inputBuffer->SetEos(false);
220 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
221 }
222
223 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_003, TestSize.Level1)
224 {
225 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
226 auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
227 inputBuffer->SetEos(false);
228
229 AVCodecBufferInfo attr;
230 attr.size = -6400; // invalid
231 inputBuffer->SetBufferAttr(attr);
232 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
233 }
234
235 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_004, TestSize.Level1)
236 {
237 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
238 auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
239 inputBuffer->SetEos(false);
240
241 AVCodecBufferInfo attr;
242 attr.size = 9600; // attr.size > 6400
243 inputBuffer->SetBufferAttr(attr);
244 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
245 }
246
247 HWTEST_F(AudioEncPluginUnitTest, SendBuffer_Aac_005, TestSize.Level1)
248 {
249 aacFormat_.PutIntValue(MediaDescriptionKey::MD_KEY_CHANNEL_COUNT, MIN_CHANNELS);
250 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
251 auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
252 inputBuffer->SetEos(false);
253
254 AVCodecBufferInfo attr;
255 attr.size = 6400; // valid size
256 inputBuffer->SetBufferAttr(attr);
257 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessSendData(inputBuffer));
258 }
259
260 HWTEST_F(AudioEncPluginUnitTest, ProcessRecieveData_Aac_001, TestSize.Level1)
261 {
262 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
263 auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
264 outputBuffer = nullptr;
265 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessRecieveData(outputBuffer));
266 }
267
268 HWTEST_F(AudioEncPluginUnitTest, ProcessRecieveData_Aac_002, TestSize.Level1)
269 {
270 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
271 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Release());
272 auto outputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, AAC_NAME, META_SIZE);
273 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->ProcessRecieveData(outputBuffer));
274 }
275
276 HWTEST_F(AudioEncPluginUnitTest, CheckResample_Aac_001, TestSize.Level1)
277 {
278 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
279 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Release());
280 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, aacEncPlugin_->Init(aacFormat_));
281 }
282
283 HWTEST_F(AudioEncPluginUnitTest, ProcessSendData_Flac_001, TestSize.Level1)
284 {
285 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, flacEncPlugin_->Init(flacFormat_));
286 EXPECT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, flacEncPlugin_->Release());
287 auto inputBuffer = std::make_shared<AudioBufferInfo>(BUFFER_SIZE, FLAC_NAME, ONE_FRAME_SIZE);
288
289 EXPECT_NE(AVCodecServiceErrCode::AVCS_ERR_OK, flacEncPlugin_->ProcessSendData(inputBuffer));
290 }
291
292 HWTEST_F(AudioEncPluginUnitTest, FlacEncodeProcess_001, TestSize.Level1)
293 {
294 PrepareFlacEncoder();
295
296 const int sampleRate = FLAC_ENC_SAMPLE_RATE;
297 const int durationSeconds = 5;
298 const int numSamples = sampleRate * durationSeconds;
299 const float amplitude = 32760.0f;
300
301 std::vector<int16_t> pcmData(numSamples * FLAC_CHANNELS);
302 for (int i = 0; i < numSamples; ++i) {
303 for (int ch = 0; ch < FLAC_CHANNELS; ++ch) {
304 float frequency = 440.0f * (ch + 1);
305 float value = amplitude * sin(2.0f * M_PI * frequency * i / sampleRate);
306 pcmData[i * FLAC_CHANNELS + ch] = static_cast<int16_t>(value);
307 }
308 }
309
310 int32_t frameSize = 1024;
311 const int bytesPerSample = 2;
312 const int bytesPerChunk = frameSize * FLAC_CHANNELS * bytesPerSample;
313 const int64_t timeIncrementUs = (frameSize * 1000000LL) / sampleRate;
314
315 int64_t pts = 0;
316 for (size_t offset = 0; offset < pcmData.size() * bytesPerSample; offset += bytesPerChunk) {
317 size_t chunkSize = std::min(bytesPerChunk, static_cast<int>(pcmData.size() * bytesPerSample - offset));
318 if (chunkSize == 0) break;
319 if (!ProcessAudioData(pcmData, offset / bytesPerSample, chunkSize, pts)) {
320 break;
321 }
322 pts += timeIncrementUs;
323 }
324 EXPECT_EQ(FlushEncoder(), true);
325 }
326 } // namespace MediaAVCodec
327 } // namespace OHOS