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