1 /*
2 * Copyright (C) 2024 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 #include "avcodec_codec_name.h"
16 #include "common/native_mfmagic.h"
17 #include "native_avbuffer.h"
18 #include "native_avcodec_audiocodec.h"
19 #include <atomic>
20 #include <fstream>
21 #include <gtest/gtest.h>
22 #include <iostream>
23 #include <mutex>
24 #include <queue>
25 #include <string>
26 #include <thread>
27 #include <unistd.h>
28 #include <vector>
29
30 #include "avcodec_common.h"
31 #include "avcodec_errors.h"
32 #include "media_description.h"
33 #include "native_avcodec_audiocodec.h"
34 #include "native_avcodec_base.h"
35 #include "native_avformat.h"
36 #include "securec.h"
37
38 using namespace std;
39 using namespace testing::ext;
40 using namespace OHOS::MediaAVCodec;
41
42 namespace {
43 const string CODEC_VIVID_NAME = std::string(AVCodecCodecName::AUDIO_DECODER_VIVID_NAME);
44 const string INPUT_SOURCE_PATH = "/data/test/media/";
45 const int VIVID_TESTCASES_NUMS = 10;
46
47 const string BIT_DEPTH_16_STRING = "16";
48 const string BIT_DEPTH_24_STRING = "24";
49
50 const std::vector<std::vector<string>> INPUT_VIVID_FILE_SOURCE_PATH = {
51 {"VIVID_48k_1c.dat", "48000", "1", "16"}, {"VIVID_48k_2c.dat", "48000", "2", "16"},
52 {"VIVID_48k_6c.dat", "48000", "6", "16"}, {"VIVID_48k_6c_2o.dat", "48000", "8", "16"},
53 {"VIVID_48k_hoa.dat", "48000", "16", "16"}, {"VIVID_96k_1c.dat", "96000", "1", "16"},
54 {"VIVID_96k_2c.dat", "96000", "2", "16"}, {"VIVID_96k_6c.dat", "96000", "6", "16"},
55 {"VIVID_96k_6c_2o.dat", "96000", "8", "16"}, {"VIVID_96k_hoa.dat", "96000", "16", "16"}};
56
57 const std::vector<std::vector<string>> INPUT_VIVID_24BIT_FILE_SOURCE_PATH = {
58 {"VIVID_48k_1c.dat", "48000", "1", "24"}, {"VIVID_48k_2c.dat", "48000", "2", "24"},
59 {"VIVID_48k_6c.dat", "48000", "6", "24"}, {"VIVID_48k_6c_2o.dat", "48000", "8", "24"},
60 {"VIVID_48k_hoa.dat", "48000", "16", "24"}, {"VIVID_96k_1c.dat", "96000", "1", "24"},
61 {"VIVID_96k_2c.dat", "96000", "2", "24"}, {"VIVID_96k_6c.dat", "96000", "6", "24"},
62 {"VIVID_96k_6c_2o.dat", "96000", "8", "24"}, {"VIVID_96k_hoa.dat", "96000", "16", "24"}};
63 constexpr string_view OUTPUT_PCM_FILE_PATH = "/data/test/media/out.pcm";
64 } // namespace
65
66 namespace OHOS {
67 namespace MediaAVCodec {
68 class ADecSignal {
69 public:
70 std::mutex inMutex_;
71 std::mutex outMutex_;
72 std::mutex startMutex_;
73 std::condition_variable inCond_;
74 std::condition_variable outCond_;
75 std::condition_variable startCond_;
76 std::queue<uint32_t> inQueue_;
77 std::queue<uint32_t> outQueue_;
78 std::queue<OH_AVBuffer *> inBufferQueue_;
79 std::queue<OH_AVBuffer *> outBufferQueue_;
80 };
81
OnError(OH_AVCodec * codec,int32_t errorCode,void * userData)82 static void OnError(OH_AVCodec *codec, int32_t errorCode, void *userData)
83 {
84 (void)codec;
85 (void)errorCode;
86 (void)userData;
87 cout << "Error received, errorCode:" << errorCode << endl;
88 }
89
OnOutputFormatChanged(OH_AVCodec * codec,OH_AVFormat * format,void * userData)90 static void OnOutputFormatChanged(OH_AVCodec *codec, OH_AVFormat *format, void *userData)
91 {
92 (void)codec;
93 (void)format;
94 (void)userData;
95 cout << "OnOutputFormatChanged received" << endl;
96 }
97
OnInputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * data,void * userData)98 static void OnInputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
99 {
100 (void)codec;
101 ADecSignal *signal = static_cast<ADecSignal *>(userData);
102 unique_lock<mutex> lock(signal->inMutex_);
103 signal->inQueue_.push(index);
104 signal->inBufferQueue_.push(data);
105 signal->inCond_.notify_all();
106 }
107
OnOutputBufferAvailable(OH_AVCodec * codec,uint32_t index,OH_AVBuffer * data,void * userData)108 static void OnOutputBufferAvailable(OH_AVCodec *codec, uint32_t index, OH_AVBuffer *data, void *userData)
109 {
110 (void)codec;
111 ADecSignal *signal = static_cast<ADecSignal *>(userData);
112 unique_lock<mutex> lock(signal->outMutex_);
113 signal->outQueue_.push(index);
114 signal->outBufferQueue_.push(data);
115 signal->outCond_.notify_all();
116 }
117
118 class AudioVividDecoderCapacityUnitTest : public testing::Test {
119 public:
120 static void SetUpTestCase(void);
121 static void TearDownTestCase(void);
122 void SetUp();
123 void TearDown();
124 int32_t InitFile(const string &codecName, string inputTestFile);
125 void InputFunc();
126 void OutputFunc();
127 int32_t HandleInputBuffer(const uint32_t index);
128 int32_t Stop();
129 void Release();
130
131 protected:
132 std::atomic<bool> isRunning_ = false;
133 std::unique_ptr<std::thread> inputLoop_;
134 std::unique_ptr<std::thread> outputLoop_;
135 struct OH_AVCodecCallback cb_;
136 ADecSignal *signal_;
137 OH_AVCodec *audioDec_;
138 OH_AVFormat *format_;
139 bool isFirstFrame_ = true;
140 std::ifstream inputFile_;
141 std::ofstream pcmOutputFile_;
142 bool vorbisHasExtradata_ = true;
143 };
144
SetUpTestCase(void)145 void AudioVividDecoderCapacityUnitTest::SetUpTestCase(void)
146 {
147 cout << "[SetUpTestCase]: " << endl;
148 }
149
TearDownTestCase(void)150 void AudioVividDecoderCapacityUnitTest::TearDownTestCase(void)
151 {
152 cout << "[TearDownTestCase]: " << endl;
153 }
154
SetUp(void)155 void AudioVividDecoderCapacityUnitTest::SetUp(void)
156 {
157 cout << "[SetUp]: SetUp!!!" << endl;
158 }
159
TearDown(void)160 void AudioVividDecoderCapacityUnitTest::TearDown(void)
161 {
162 cout << "[TearDown]: over!!!" << endl;
163
164 if (signal_) {
165 delete signal_;
166 signal_ = nullptr;
167 }
168 if (inputFile_.is_open()) {
169 inputFile_.close();
170 }
171 if (pcmOutputFile_.is_open()) {
172 pcmOutputFile_.close();
173 }
174 sleep(1);
175 }
176
Release()177 void AudioVividDecoderCapacityUnitTest::Release()
178 {
179 Stop();
180 if (signal_) {
181 delete signal_;
182 signal_ = nullptr;
183 }
184 if (inputFile_.is_open()) {
185 inputFile_.close();
186 }
187 if (pcmOutputFile_.is_open()) {
188 pcmOutputFile_.close();
189 }
190 if (format_) {
191 OH_AVFormat_Destroy(format_);
192 }
193 OH_AudioCodec_Destroy(audioDec_);
194 }
195
HandleInputBuffer(const uint32_t index)196 int32_t AudioVividDecoderCapacityUnitTest::HandleInputBuffer(const uint32_t index)
197 {
198 int32_t ret = OH_AudioCodec_PushInputBuffer(audioDec_, index);
199 signal_->inBufferQueue_.pop();
200 signal_->inQueue_.pop();
201 return ret;
202 }
203
InputFunc()204 void AudioVividDecoderCapacityUnitTest::InputFunc()
205 {
206 int64_t size;
207 while (isRunning_.load()) {
208 unique_lock<mutex> lock(signal_->inMutex_);
209 signal_->inCond_.wait(lock, [this]() { return (signal_->inQueue_.size() > 0 || !isRunning_.load()); });
210 if (!isRunning_.load()) {
211 break;
212 }
213 uint32_t index = signal_->inQueue_.front();
214 auto buffer = signal_->inBufferQueue_.front();
215 if (buffer == nullptr) {
216 cout << "Fatal: GetInputBuffer fail" << endl;
217 break;
218 }
219 inputFile_.read(reinterpret_cast<char *>(&size), sizeof(size));
220 if (inputFile_.eof() || inputFile_.gcount() == 0) {
221 buffer->buffer_->memory_->SetSize(1);
222 buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_EOS;
223 HandleInputBuffer(index);
224 cout << "end buffer\n";
225 break;
226 }
227 if (inputFile_.gcount() != sizeof(size)) {
228 cout << "Fatal: read size fail" << endl;
229 break;
230 }
231 inputFile_.read(reinterpret_cast<char *>(&buffer->buffer_->pts_), sizeof(buffer->buffer_->pts_));
232 if (inputFile_.gcount() != sizeof(buffer->buffer_->pts_)) {
233 cout << "Fatal: read size fail" << endl;
234 break;
235 }
236 inputFile_.read((char *)OH_AVBuffer_GetAddr(buffer), size);
237 if (inputFile_.gcount() != size) {
238 cout << "Fatal: read buffer fail" << endl;
239 break;
240 }
241 buffer->buffer_->memory_->SetSize(size);
242 if (isFirstFrame_) {
243 buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_CODEC_DATA;
244 isFirstFrame_ = false;
245 } else {
246 buffer->buffer_->flag_ = AVCODEC_BUFFER_FLAGS_NONE;
247 }
248 if (HandleInputBuffer(index) != AV_ERR_OK) {
249 cout << "Fatal error, exit" << endl;
250 break;
251 }
252 }
253 inputFile_.close();
254 }
255
OutputFunc()256 void AudioVividDecoderCapacityUnitTest::OutputFunc()
257 {
258 if (!pcmOutputFile_.is_open()) {
259 std::cout << "open " << OUTPUT_PCM_FILE_PATH << " failed!" << std::endl;
260 }
261 while (isRunning_.load()) {
262 unique_lock<mutex> lock(signal_->outMutex_);
263 signal_->outCond_.wait(lock, [this]() { return (signal_->outQueue_.size() > 0 || !isRunning_.load()); });
264 if (!isRunning_.load()) {
265 cout << "wait to stop, exit" << endl;
266 break;
267 }
268 uint32_t index = signal_->outQueue_.front();
269 OH_AVBuffer *data = signal_->outBufferQueue_.front();
270 if (data == nullptr) {
271 std::cout << "OutputFunc OH_AVBuffer is nullptr" << std::endl;
272 isRunning_.store(false);
273 signal_->startCond_.notify_all();
274 break;
275 }
276 pcmOutputFile_.write(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)), data->buffer_->memory_->GetSize());
277 if (data->buffer_->flag_ == AVCODEC_BUFFER_FLAGS_EOS) {
278 cout << "decode eos" << endl;
279 isRunning_.store(false);
280 signal_->startCond_.notify_all();
281 }
282 signal_->outBufferQueue_.pop();
283 signal_->outQueue_.pop();
284 EXPECT_EQ(AV_ERR_OK, OH_AudioCodec_FreeOutputBuffer(audioDec_, index));
285 }
286 pcmOutputFile_.close();
287 signal_->startCond_.notify_all();
288 }
289
Stop()290 int32_t AudioVividDecoderCapacityUnitTest::Stop()
291 {
292 isRunning_.store(false);
293 if (inputLoop_ != nullptr && inputLoop_->joinable()) {
294 unique_lock<mutex> lock(signal_->inMutex_);
295 signal_->inCond_.notify_all();
296 lock.unlock();
297 inputLoop_->join();
298 }
299
300 if (outputLoop_ != nullptr && outputLoop_->joinable()) {
301 unique_lock<mutex> lock(signal_->outMutex_);
302 signal_->outCond_.notify_all();
303 lock.unlock();
304 outputLoop_->join();
305 }
306 return OH_AudioCodec_Stop(audioDec_);
307 }
308
InitFile(const string & codecName,string inputTestFile)309 int32_t AudioVividDecoderCapacityUnitTest::InitFile(const string &codecName, string inputTestFile)
310 {
311 format_ = OH_AVFormat_Create();
312 audioDec_ = OH_AudioCodec_CreateByName(codecName.c_str());
313 if (audioDec_ == nullptr) {
314 return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
315 }
316
317 inputFile_.open(INPUT_SOURCE_PATH + inputTestFile, std::ios::binary);
318 pcmOutputFile_.open(OUTPUT_PCM_FILE_PATH.data(), std::ios::out | std::ios::binary);
319 if (!inputFile_.is_open()) {
320 cout << "Fatal: open input file failed" << endl;
321 return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
322 }
323 if (!pcmOutputFile_.is_open()) {
324 cout << "Fatal: open output file failed" << endl;
325 return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
326 }
327
328 signal_ = new ADecSignal();
329 cb_ = {&OnError, &OnOutputFormatChanged, &OnInputBufferAvailable, &OnOutputBufferAvailable};
330 int32_t ret = OH_AudioCodec_RegisterCallback(audioDec_, cb_, signal_);
331 if (ret != AVCodecServiceErrCode::AVCS_ERR_OK) {
332 return AVCodecServiceErrCode::AVCS_ERR_UNKNOWN;
333 }
334 return AVCodecServiceErrCode::AVCS_ERR_OK;
335 }
336
337 HWTEST_F(AudioVividDecoderCapacityUnitTest, audioCodec_Normalcase_07, TestSize.Level1)
338 {
339 bool result;
340 for (int i = 0; i < VIVID_TESTCASES_NUMS; i++) {
341 cout << "decode start " << INPUT_VIVID_FILE_SOURCE_PATH[i][0] << endl;
342 ASSERT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK, InitFile(CODEC_VIVID_NAME, INPUT_VIVID_FILE_SOURCE_PATH[i][0]));
343
344 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(),
345 stoi(INPUT_VIVID_FILE_SOURCE_PATH[i][1]));
346 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(),
347 stoi(INPUT_VIVID_FILE_SOURCE_PATH[i][2]));
348
349 if (INPUT_VIVID_FILE_SOURCE_PATH[i][3] == BIT_DEPTH_16_STRING) {
350 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
351 Media::Plugins::AudioSampleFormat::SAMPLE_S16LE);
352 } else if (INPUT_VIVID_FILE_SOURCE_PATH[i][3] == BIT_DEPTH_24_STRING) {
353 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
354 Media::Plugins::AudioSampleFormat::SAMPLE_S24LE);
355 }
356
357 EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_));
358
359 isRunning_.store(true);
360 inputLoop_ = make_unique<thread>(&AudioVividDecoderCapacityUnitTest::InputFunc, this);
361 EXPECT_NE(nullptr, inputLoop_);
362 outputLoop_ = make_unique<thread>(&AudioVividDecoderCapacityUnitTest::OutputFunc, this);
363 EXPECT_NE(nullptr, outputLoop_);
364
365 EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Start(audioDec_));
366 {
367 unique_lock<mutex> lock(signal_->startMutex_);
__anon34629c4a0402() 368 signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); });
369 }
370 EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop());
371 result = std::filesystem::file_size(OUTPUT_PCM_FILE_PATH) < 20;
372 EXPECT_EQ(result, false) << "error occur, decode fail" << INPUT_VIVID_FILE_SOURCE_PATH[i][0] << endl;
373
374 Release();
375 }
376 }
377
378 HWTEST_F(AudioVividDecoderCapacityUnitTest, audioCodec_Normalcase_08, TestSize.Level1)
379 {
380 bool result;
381 for (int i = 0; i < VIVID_TESTCASES_NUMS; i++) {
382 cout << "decode start " << INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][0] << endl;
383 ASSERT_EQ(AVCodecServiceErrCode::AVCS_ERR_OK,
384 InitFile(CODEC_VIVID_NAME, INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][0]));
385
386 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_SAMPLE_RATE.data(),
387 stoi(INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][1]));
388 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_CHANNEL_COUNT.data(),
389 stoi(INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][2]));
390
391 if (INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][3] == BIT_DEPTH_16_STRING) {
392 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
393 Media::Plugins::AudioSampleFormat::SAMPLE_S16LE);
394 } else if (INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][3] == BIT_DEPTH_24_STRING) {
395 OH_AVFormat_SetIntValue(format_, MediaDescriptionKey::MD_KEY_AUDIO_SAMPLE_FORMAT.data(),
396 Media::Plugins::AudioSampleFormat::SAMPLE_S24LE);
397 }
398
399 EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Configure(audioDec_, format_));
400
401 isRunning_.store(true);
402 inputLoop_ = make_unique<thread>(&AudioVividDecoderCapacityUnitTest::InputFunc, this);
403 EXPECT_NE(nullptr, inputLoop_);
404 outputLoop_ = make_unique<thread>(&AudioVividDecoderCapacityUnitTest::OutputFunc, this);
405 EXPECT_NE(nullptr, outputLoop_);
406
407 EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, OH_AudioCodec_Start(audioDec_));
408 {
409 unique_lock<mutex> lock(signal_->startMutex_);
__anon34629c4a0502() 410 signal_->startCond_.wait(lock, [this]() { return (!(isRunning_.load())); });
411 }
412 EXPECT_EQ(OH_AVErrCode::AV_ERR_OK, Stop());
413 result = std::filesystem::file_size(OUTPUT_PCM_FILE_PATH) < 20;
414 EXPECT_EQ(result, false) << "error occur, decode fail" << INPUT_VIVID_24BIT_FILE_SOURCE_PATH[i][0] << endl;
415
416 Release();
417 }
418 }
419 } // namespace MediaAVCodec
420 } // namespace OHOS