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 <string>
18 #include <vector>
19 #include <fcntl.h>
20 #include <fstream>
21 #include "avmuxer_sample.h"
22 #include "buffer/avbuffer.h"
23 #include "buffer/avbuffer_queue_producer.h"
24 #include "nocopyable.h"
25 #include "avmuxer.h"
26 #include "native_avbuffer.h"
27 #include "avcodec_audio_channel_layout.h"
28 #ifdef AVMUXER_UNITTEST_CAPI
29 #include "native_avmuxer.h"
30 #include "native_avformat.h"
31 #endif
32
33 using namespace testing::ext;
34 using namespace OHOS::Media;
35 namespace OHOS {
36 namespace MediaAVCodec {
37 const std::string TEST_FILE_PATH = "/data/test/media/";
38
39 class AVMuxerFlacUnitTest : public testing::Test {
40 public:
41 static void SetUpTestCase(void);
42 static void TearDownTestCase(void);
43 void SetUp(void);
44 void TearDown(void);
45 int32_t WriteSample(int32_t trackId, std::shared_ptr<std::ifstream> file, bool &eosFlag, uint32_t flag);
46
47 protected:
48 std::shared_ptr<AVMuxerSample> avmuxer_ {nullptr};
49 std::shared_ptr<std::ifstream> inputFile_ = nullptr;
50 int32_t fd_ {-1};
51 };
52
SetUpTestCase()53 void AVMuxerFlacUnitTest::SetUpTestCase()
54 {}
55
TearDownTestCase()56 void AVMuxerFlacUnitTest::TearDownTestCase()
57 {}
58
SetUp()59 void AVMuxerFlacUnitTest::SetUp()
60 {
61 avmuxer_ = std::make_shared<AVMuxerSample>();
62 }
63
TearDown()64 void AVMuxerFlacUnitTest::TearDown()
65 {
66 if (fd_ >= 0) {
67 close(fd_);
68 fd_ = -1;
69 }
70
71 if (inputFile_ != nullptr) {
72 if (inputFile_->is_open()) {
73 inputFile_->close();
74 }
75 }
76
77 if (avmuxer_ != nullptr) {
78 avmuxer_->Destroy();
79 avmuxer_ = nullptr;
80 }
81 }
82
WriteSample(int32_t trackId,std::shared_ptr<std::ifstream> file,bool & eosFlag,uint32_t flag)83 int32_t AVMuxerFlacUnitTest::WriteSample(int32_t trackId, std::shared_ptr<std::ifstream> file,
84 bool &eosFlag, uint32_t flag)
85 {
86 OH_AVCodecBufferAttr info;
87
88 if (file->eof()) {
89 eosFlag = true;
90 return 0;
91 }
92 file->read(reinterpret_cast<char*>(&info.pts), sizeof(info.pts));
93
94 if (file->eof()) {
95 eosFlag = true;
96 return 0;
97 }
98 file->read(reinterpret_cast<char*>(&info.flags), sizeof(info.flags));
99
100 if (file->eof()) {
101 eosFlag = true;
102 return 0;
103 }
104 file->read(reinterpret_cast<char*>(&info.size), sizeof(info.size));
105
106 if (file->eof()) {
107 eosFlag = true;
108 return 0;
109 }
110
111 OH_AVBuffer *buffer = nullptr;
112 if (info.size == 0) {
113 buffer = OH_AVBuffer_Create(1);
114 } else {
115 buffer = OH_AVBuffer_Create(info.size);
116 file->read(reinterpret_cast<char*>(OH_AVBuffer_GetAddr(buffer)), info.size);
117 }
118
119 OH_AVBuffer_SetBufferAttr(buffer, &info);
120 int32_t ret = avmuxer_->WriteSampleBuffer(trackId, buffer);
121 OH_AVBuffer_Destroy(buffer);
122 return ret;
123 }
124
125 /**
126 * @tc.name: Muxer_FLAC_001
127 * @tc.desc: supported muxer flac
128 * @tc.type: FUNC
129 */
130 HWTEST_F(AVMuxerFlacUnitTest, Muxer_FLAC_001, TestSize.Level0)
131 {
132 int32_t trackId = -1;
133 std::string outputFile = TEST_FILE_PATH + std::string("Muxer_FLAC_48000_1.flac");
134 OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_FLAC;
135
136 fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
137 bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat);
138 ASSERT_TRUE(isCreated);
139
140 std::shared_ptr<FormatMock> audioParams = FormatMockFactory::CreateFormat();
141 audioParams->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_FLAC);
142 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 48000); // 48000 sample rate
143 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 1); // 1 channels
144 audioParams->PutIntValue(OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
145 int32_t ret = avmuxer_->AddTrack(trackId, audioParams);
146 ASSERT_EQ(ret, 0);
147 ASSERT_GE(trackId, 0);
148 ASSERT_EQ(avmuxer_->Start(), 0);
149
150 inputFile_ = std::make_shared<std::ifstream>("/data/test/media/flac_48000_1_s16le.dat", std::ios::binary);
151
152 int32_t extSize = 0;
153 inputFile_->read(reinterpret_cast<char*>(&extSize), sizeof(extSize));
154 ASSERT_EQ(extSize, 34); // 34 -> flac codecConfig len
155 if (extSize > 0) {
156 std::vector<uint8_t> buffer(extSize);
157 inputFile_->read(reinterpret_cast<char*>(buffer.data()), extSize);
158 audioParams->PutBuffer(OH_MD_KEY_CODEC_CONFIG, buffer.data(), buffer.size());
159 }
160
161 bool eosFlag = false;
162 uint32_t flag = AVCODEC_BUFFER_FLAGS_SYNC_FRAME;
163 ret = WriteSample(trackId, inputFile_, eosFlag, flag);
164 while (!eosFlag && (ret == 0)) {
165 ret = WriteSample(trackId, inputFile_, eosFlag, flag);
166 }
167 ASSERT_EQ(ret, 0);
168 ASSERT_EQ(avmuxer_->Stop(), 0);
169 }
170
171 /**
172 * @tc.name: Muxer_FLAC_002
173 * @tc.desc: supported muxer flac with no codec config
174 * @tc.type: FUNC
175 */
176 HWTEST_F(AVMuxerFlacUnitTest, Muxer_FLAC_002, TestSize.Level0)
177 {
178 int32_t trackId = -1;
179 std::string outputFile = TEST_FILE_PATH + std::string("Muxer_FLAC_48000_1.flac");
180 OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_FLAC;
181
182 fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
183 bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat);
184 ASSERT_TRUE(isCreated);
185
186 std::shared_ptr<FormatMock> audioParams = FormatMockFactory::CreateFormat();
187 audioParams->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_FLAC);
188 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 48000); // 48000 sample rate
189 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 1); // 1 channels
190 audioParams->PutIntValue(OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
191 int32_t ret = avmuxer_->AddTrack(trackId, audioParams);
192 ASSERT_EQ(ret, 0);
193 ASSERT_GE(trackId, 0);
194 ASSERT_EQ(avmuxer_->Start(), 0);
195
196 inputFile_ = std::make_shared<std::ifstream>("/data/test/media/flac_48000_1_s16le.dat", std::ios::binary);
197
198 int32_t extSize = 0;
199 inputFile_->read(reinterpret_cast<char*>(&extSize), sizeof(extSize));
200 ASSERT_EQ(extSize, 34); // 34 -> flac codecConfig len
201 if (extSize > 0) {
202 std::vector<uint8_t> buffer(extSize);
203 inputFile_->read(reinterpret_cast<char*>(buffer.data()), extSize);
204 }
205
206 bool eosFlag = false;
207 uint32_t flag = AVCODEC_BUFFER_FLAGS_SYNC_FRAME;
208 ret = WriteSample(trackId, inputFile_, eosFlag, flag);
209 while (!eosFlag && (ret == 0)) {
210 ret = WriteSample(trackId, inputFile_, eosFlag, flag);
211 }
212 ASSERT_EQ(ret, 0);
213 ASSERT_EQ(avmuxer_->Stop(), 0);
214 }
215
216 /**
217 * @tc.name: AddTrack_001
218 * @tc.desc: test muxer flac add track
219 * @tc.type: FUNC
220 */
221 HWTEST_F(AVMuxerFlacUnitTest, AddTrack_001, TestSize.Level0)
222 {
223 int32_t trackId = -1;
224 std::string outputFile = TEST_FILE_PATH + std::string("Muxer_FLAC_48000_1.flac");
225 OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_FLAC;
226
227 fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
228 bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat);
229 ASSERT_TRUE(isCreated);
230
231 std::shared_ptr<FormatMock> audioParams = FormatMockFactory::CreateFormat();
232 audioParams->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_FLAC);
233 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 48000); // 48000 sample rate
234 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 9); // 9 channels
235 audioParams->PutIntValue(OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
236 int32_t ret = avmuxer_->AddTrack(trackId, audioParams);
237 EXPECT_NE(ret, 0);
238 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 0); // 9 channels
239 ret = avmuxer_->AddTrack(trackId, audioParams);
240 EXPECT_NE(ret, 0);
241 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 2); // 2 channels
242 ret = avmuxer_->AddTrack(trackId, audioParams);
243 EXPECT_EQ(ret, 0);
244 }
245
246 /**
247 * @tc.name: AddTrack_002
248 * @tc.desc: test muxer flac add track
249 * @tc.type: FUNC
250 */
251 HWTEST_F(AVMuxerFlacUnitTest, AddTrack_002, TestSize.Level0)
252 {
253 int32_t trackId = -1;
254 std::string outputFile = TEST_FILE_PATH + std::string("Muxer_FLAC_48000_1.flac");
255 OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_FLAC;
256
257 fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
258 bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat);
259 ASSERT_TRUE(isCreated);
260
261 std::shared_ptr<FormatMock> audioParams = FormatMockFactory::CreateFormat();
262 audioParams->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_FLAC);
263 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, -1); // -1 sample rate
264 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 1); // 1 channels
265 audioParams->PutIntValue(OH_MD_KEY_AUDIO_SAMPLE_FORMAT, SAMPLE_S16LE);
266 int32_t ret = avmuxer_->AddTrack(trackId, audioParams);
267 EXPECT_NE(ret, 0);
268 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 0); // 48000 sample rate
269 ret = avmuxer_->AddTrack(trackId, audioParams);
270 EXPECT_NE(ret, 0);
271 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 96000); // 96000 sample rate
272 ret = avmuxer_->AddTrack(trackId, audioParams);
273 EXPECT_EQ(ret, 0);
274 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 192000); // 192000 sample rate
275 ret = avmuxer_->AddTrack(trackId, audioParams);
276 EXPECT_EQ(ret, 0);
277 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 384000); // 384000 sample rate
278 ret = avmuxer_->AddTrack(trackId, audioParams);
279 EXPECT_EQ(ret, 0);
280 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 768000); // 768000 sample rate
281 ret = avmuxer_->AddTrack(trackId, audioParams);
282 EXPECT_EQ(ret, 0);
283 }
284
285 /**
286 * @tc.name: AddTrack_003
287 * @tc.desc: test muxer flac add track
288 * @tc.type: FUNC
289 */
290 HWTEST_F(AVMuxerFlacUnitTest, AddTrack_003, TestSize.Level0)
291 {
292 int32_t trackId = -1;
293 std::string outputFile = TEST_FILE_PATH + std::string("Muxer_FLAC_48000_1.flac");
294 OH_AVOutputFormat outputFormat = AV_OUTPUT_FORMAT_FLAC;
295
296 fd_ = open(outputFile.c_str(), O_CREAT | O_RDWR | O_TRUNC, S_IRUSR | S_IWUSR);
297 bool isCreated = avmuxer_->CreateMuxer(fd_, outputFormat);
298 ASSERT_TRUE(isCreated);
299
300 std::shared_ptr<FormatMock> audioParams = FormatMockFactory::CreateFormat();
301 audioParams->PutStringValue(OH_MD_KEY_CODEC_MIME, OH_AVCODEC_MIMETYPE_AUDIO_FLAC);
302 audioParams->PutIntValue(OH_MD_KEY_AUD_SAMPLE_RATE, 48000); // 48000 sample rate
303 audioParams->PutIntValue(OH_MD_KEY_AUD_CHANNEL_COUNT, 1); // 1 channels
304 audioParams->PutIntValue(OH_MD_KEY_AUDIO_SAMPLE_FORMAT, static_cast<int32_t>(0xff));
305 int32_t ret = avmuxer_->AddTrack(trackId, audioParams);
306 EXPECT_NE(ret, 0);
307 audioParams->PutIntValue(OH_MD_KEY_AUDIO_SAMPLE_FORMAT, static_cast<int32_t>(-1));
308 ret = avmuxer_->AddTrack(trackId, audioParams);
309 EXPECT_NE(ret, 0);
310 }
311 } // namespace MediaAVCodec
312 } // namespace OHOS