1 /*
2 * Copyright (C) 2023 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 <cstdio>
17 #include <fcntl.h>
18 #include <iostream>
19 #include <malloc.h>
20 #include <string>
21 #include <thread>
22 #include <sys/stat.h>
23 #include <fstream>
24 #include <chrono>
25
26 #include "avcodec_common.h"
27 #include "buffer/avsharedmemorybase.h"
28 #include "media_description.h"
29 #include "native_avcodec_base.h"
30 #include "native_avformat.h"
31 #include "native_avmagic.h"
32 #include "native_avmemory.h"
33 #include "native_avbuffer.h"
34
35 #include "capi_demo/avdemuxer_demo.h"
36 #include "capi_demo/avsource_demo.h"
37 #include "demo_log.h"
38 #include "inner_demo/inner_demuxer_demo.h"
39 #include "inner_demo/inner_source_demo.h"
40 #include "server_demo/file_server_demo.h"
41
42 #include "avdemuxer_demo_runner.h"
43 #include "media_data_source.h"
44
45 using namespace std;
46 using namespace OHOS::MediaAVCodec;
47 using namespace OHOS::Media;
48
49 static int64_t g_seekTime = 1000;
50 static int64_t g_startTime = 0;
51 static int64_t g_loopTime = 20;
52 static uint32_t g_maxThreadNum = 16;
53 static vector<string> g_filelist = {"AAC_44100hz_2c.aac", "ALAC_44100hz_2c.m4a",
54 "FLAC_44100hz_2c.flac", "h264_720x480_aac_44100hz_2c.mp4",
55 "h264_aac_moovlast.mp4", "h265_720x480_aac_44100hz_2c.mp4",
56 "MPEG_44100hz_2c.mp3", "MPEGTS_V1920x1080_A44100hz_2c.ts",
57 "OGG_44100hz_2c.ogg", "WAV_44100hz_2c.wav"};
58 static std::string g_filePath;
59
AVSourceReadAt(OH_AVBuffer * data,int32_t length,int64_t pos)60 static int32_t AVSourceReadAt(OH_AVBuffer *data, int32_t length, int64_t pos)
61 {
62 if (data == nullptr) {
63 printf("AVSourceReadAt : data is nullptr!\n");
64 return MediaDataSourceError::SOURCE_ERROR_IO;
65 }
66
67 std::ifstream infile(g_filePath, std::ofstream::binary);
68 if (!infile.is_open()) {
69 printf("AVSourceReadAt : open file failed! file:%s\n", g_filePath.c_str());
70 return MediaDataSourceError::SOURCE_ERROR_IO; // 打开文件失败
71 }
72
73 infile.seekg(0, std::ios::end);
74 int64_t fileSize = infile.tellg();
75 if (pos >= fileSize) {
76 printf("AVSourceReadAt : pos over or equals file size!\n");
77 return MediaDataSourceError::SOURCE_ERROR_EOF; // pos已经是文件末尾位置,无法读取
78 }
79
80 if (pos + length > fileSize) {
81 length = fileSize - pos; // pos+length长度超过文件大小时,读取从pos到文件末尾的数据
82 }
83
84 infile.seekg(pos, std::ios::beg);
85 if (length <= 0) {
86 printf("AVSourceReadAt : raed length less than zero!\n");
87 return MediaDataSourceError::SOURCE_ERROR_IO;
88 }
89 char* buffer = new char[length];
90 infile.read(buffer, length);
91 infile.close();
92
93 errno_t result = memcpy_s(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)),
94 OH_AVBuffer_GetCapacity(data), buffer, length);
95 delete[] buffer;
96 if (result != 0) {
97 printf("memcpy_s failed!");
98 return MediaDataSourceError::SOURCE_ERROR_IO;
99 }
100
101 return length;
102 }
103
AVSourceReadAtExt(OH_AVBuffer * data,int32_t length,int64_t pos,void * userData)104 static int32_t AVSourceReadAtExt(OH_AVBuffer *data, int32_t length, int64_t pos, void* userData)
105 {
106 if (data == nullptr || userData == nullptr) {
107 printf("AVSourceReadAtExt : data or userData is nullptr!\n");
108 return MediaDataSourceError::SOURCE_ERROR_IO;
109 }
110
111 std::ifstream* infile = reinterpret_cast<std::ifstream*>(userData);
112 if (!infile->is_open()) {
113 printf("AVSourceReadAtExt: file not open!\n");
114 return MediaDataSourceError::SOURCE_ERROR_IO;
115 }
116
117 infile->seekg(0, std::ios::end);
118 int64_t fileSize = infile->tellg();
119 if (pos >= fileSize) {
120 printf("AVSourceReadAtExt: pos over file size\n");
121 return MediaDataSourceError::SOURCE_ERROR_EOF;
122 }
123
124 if (pos + length > fileSize) {
125 length = fileSize - pos;
126 }
127
128 infile->seekg(pos, std::ios::beg);
129 if (length <= 0) {
130 printf("AVSourceReadAt : raed length less than zero!\n");
131 return MediaDataSourceError::SOURCE_ERROR_IO;
132 }
133 char* buffer = new char[length];
134 infile->read(buffer, length);
135
136 errno_t result = memcpy_s(reinterpret_cast<char *>(OH_AVBuffer_GetAddr(data)),
137 OH_AVBuffer_GetCapacity(data), buffer, length);
138 delete[] buffer;
139 if (result != 0) {
140 printf("memcpy_s failed!");
141 return MediaDataSourceError::SOURCE_ERROR_IO;
142 }
143
144 return length;
145 }
146
TestNativeSeek(OH_AVMemory * sampleMem,int32_t trackCount,std::shared_ptr<AVDemuxerDemo> avDemuxerDemo)147 static void TestNativeSeek(OH_AVMemory *sampleMem, int32_t trackCount, std::shared_ptr<AVDemuxerDemo> avDemuxerDemo)
148 {
149 printf("seek to 1s,mode:SEEK_MODE_NEXT_SYNC\n");
150 avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_NEXT_SYNC); // 测试seek功能
151 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
152 printf("seek to 1s,mode:SEEK_MODE_PREVIOUS_SYNC\n");
153 avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_PREVIOUS_SYNC);
154 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
155 printf("seek to 1s,mode:SEEK_MODE_CLOSEST_SYNC\n");
156 avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
157 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
158 printf("seek to 0s,mode:SEEK_MODE_CLOSEST_SYNC\n");
159 avDemuxerDemo->SeekToTime(g_startTime, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
160 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
161 }
162
ShowSourceDescription(OH_AVFormat * oh_trackformat)163 static void ShowSourceDescription(OH_AVFormat *oh_trackformat)
164 {
165 int32_t trackType = -1;
166 int64_t duration = -1;
167 const char* mimeType = nullptr;
168 int64_t bitrate = -1;
169 int32_t width = -1;
170 int32_t height = -1;
171 int32_t audioSampleFormat = -1;
172 double keyFrameRate = -1;
173 int32_t profile = -1;
174 int32_t audioChannelCount = -1;
175 int32_t audioSampleRate = -1;
176 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_TRACK_TYPE, &trackType);
177 OH_AVFormat_GetLongValue(oh_trackformat, OH_MD_KEY_DURATION, &duration);
178 OH_AVFormat_GetStringValue(oh_trackformat, OH_MD_KEY_CODEC_MIME, &mimeType);
179 OH_AVFormat_GetLongValue(oh_trackformat, OH_MD_KEY_BITRATE, &bitrate);
180 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_WIDTH, &width);
181 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_HEIGHT, &height);
182 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, &audioSampleFormat);
183 OH_AVFormat_GetDoubleValue(oh_trackformat, OH_MD_KEY_FRAME_RATE, &keyFrameRate);
184 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_PROFILE, &profile);
185 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_AUD_CHANNEL_COUNT, &audioChannelCount);
186 OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_AUD_SAMPLE_RATE, &audioSampleRate);
187 printf("===>tracks:%d duration:%" PRId64 " mimeType:%s bitrate:%" PRId64 " width:%d height:%d audioSampleFormat:%d"
188 " keyFrameRate:%.2f profile:%d audioChannelCount:%d audioSampleRate:%d\n", trackType, duration, mimeType,
189 bitrate, width, height, audioSampleFormat, keyFrameRate, profile, audioChannelCount, audioSampleRate);
190 }
191
CreateAVSource(const std::string & filePath,const std::string & fileMode,std::ifstream * & fileStream,int32_t & fd)192 static std::shared_ptr<AVSourceDemo> CreateAVSource(
193 const std::string &filePath, const std::string &fileMode, std::ifstream *&fileStream, int32_t &fd)
194 {
195 auto avSourceDemo = std::make_shared<AVSourceDemo>();
196 if (fileMode == "1") {
197 avSourceDemo->CreateWithURI((char *)(filePath.c_str()));
198 } else if (fileMode == "0" || fileMode == "2") {
199 if ((fd = open(filePath.c_str(), O_RDONLY)) < 0) {
200 printf("open file failed\n");
201 return nullptr;
202 }
203 int64_t fileSize = avSourceDemo->GetFileSize(filePath);
204 if (fileMode == "0") {
205 avSourceDemo->CreateWithFD(fd, 0, fileSize);
206 } else if (fileMode == "2") {
207 g_filePath = filePath;
208 OH_AVDataSource dataSource = {fileSize, AVSourceReadAt};
209 avSourceDemo->CreateWithDataSource(&dataSource);
210 }
211 } else if (fileMode == "3") {
212 fileStream = new std::ifstream(filePath, std::ios::binary);
213 if (!fileStream->is_open()) {
214 printf("dataSoureceExt open file fail\n");
215 return nullptr;
216 }
217 fileStream->seekg(0, std::ios::end);
218 int64_t fileSize = fileStream->tellg();
219 fileStream->seekg(0, std::ios::beg);
220 g_filePath = filePath;
221 OH_AVDataSourceExt dataSourceExt = {fileSize, AVSourceReadAtExt};
222 avSourceDemo->CreateWithDataSourceExt(&dataSourceExt, reinterpret_cast<void*>(fileStream));
223 }
224 return avSourceDemo;
225 }
226
RunNativeDemuxer(const std::string & filePath,const std::string & fileMode)227 static void RunNativeDemuxer(const std::string &filePath, const std::string &fileMode)
228 {
229 int32_t fd = -1;
230 std::ifstream* fileStream = nullptr;
231 auto avSourceDemo = CreateAVSource(filePath, fileMode, fileStream, fd);
232 if (avSourceDemo == nullptr) {
233 return;
234 }
235
236 auto avDemuxerDemo = std::make_shared<AVDemuxerDemo>();
237 OH_AVSource *av_source = avSourceDemo->GetAVSource();
238 avDemuxerDemo->CreateWithSource(av_source);
239 int32_t trackCount = 0;
240 int64_t duration = 0;
241 OH_AVFormat *oh_avformat = avSourceDemo->GetSourceFormat();
242 OH_AVFormat_GetIntValue(oh_avformat, OH_MD_KEY_TRACK_COUNT, &trackCount); // 北向获取sourceformat
243 OH_AVFormat_GetLongValue(oh_avformat, OH_MD_KEY_DURATION, &duration);
244 printf("====>total tracks:%d duration:%" PRId64 "\n", trackCount, duration);
245 for (int32_t i = 0; i < trackCount; i++) {
246 OH_AVFormat *oh_trackformat = avSourceDemo->GetTrackFormat(i);
247 ShowSourceDescription(oh_trackformat);
248 avDemuxerDemo->SelectTrackByID(i); // 添加轨道
249 }
250 uint32_t buffersize = 10 * 1024 * 1024;
251 OH_AVMemory *sampleMem = OH_AVMemory_Create(buffersize); // 创建memory
252 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
253 TestNativeSeek(sampleMem, trackCount, avDemuxerDemo);
254 OH_AVMemory_Destroy(sampleMem);
255 OH_AVFormat_Destroy(oh_avformat);
256 avDemuxerDemo->Destroy();
257 avSourceDemo->Destroy();
258 if (fileMode == "0" && fd > 0) {
259 close(fd);
260 }
261 if (fileMode == "3" && fileStream != nullptr) {
262 fileStream->close();
263 delete fileStream;
264 }
265 }
266
RunDrmNativeDemuxer(const std::string & filePath,const std::string & fileMode)267 static void RunDrmNativeDemuxer(const std::string &filePath, const std::string &fileMode)
268 {
269 auto avSourceDemo = std::make_shared<AVSourceDemo>();
270 int32_t fd = -1;
271 if (fileMode == "0") {
272 fd = open(filePath.c_str(), O_RDONLY);
273 if (fd < 0) {
274 printf("open file failed\n");
275 return;
276 }
277 size_t filesize = avSourceDemo->GetFileSize(filePath);
278 avSourceDemo->CreateWithFD(fd, 0, filesize);
279 } else if (fileMode == "1") {
280 avSourceDemo->CreateWithURI((char *)(filePath.c_str()));
281 }
282 auto avDemuxerDemo = std::make_shared<AVDemuxerDemo>();
283 OH_AVSource *av_source = avSourceDemo->GetAVSource();
284 avDemuxerDemo->CreateWithSource(av_source);
285
286 // test drm event callback
287 avDemuxerDemo->SetDrmAppCallback();
288
289 int32_t trackCount = 0;
290 int64_t duration = 0;
291 OH_AVFormat *oh_avformat = avSourceDemo->GetSourceFormat();
292 OH_AVFormat_GetIntValue(oh_avformat, OH_MD_KEY_TRACK_COUNT, &trackCount); // 北向获取sourceformat
293 OH_AVFormat_GetLongValue(oh_avformat, OH_MD_KEY_DURATION, &duration);
294 printf("====>total tracks:%d duration:%" PRId64 "\n", trackCount, duration);
295 for (int32_t i = 0; i < trackCount; i++) {
296 avDemuxerDemo->SelectTrackByID(i); // 添加轨道
297 }
298 uint32_t buffersize = 10 * 1024 * 1024;
299 OH_AVMemory *sampleMem = OH_AVMemory_Create(buffersize); // 创建memory
300 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
301 printf("seek to 1s,mode:SEEK_MODE_NEXT_SYNC\n");
302 avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_NEXT_SYNC); // 测试seek功能
303 avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
304
305 // test drm GetMediaKeySystemInfos
306 avDemuxerDemo->GetMediaKeySystemInfo();
307
308 OH_AVMemory_Destroy(sampleMem);
309 OH_AVFormat_Destroy(oh_avformat);
310 avDemuxerDemo->Destroy();
311 avSourceDemo->Destroy();
312 if (fileMode == "0" && fd > 0) {
313 close(fd);
314 }
315 }
316
ConvertPtsFrameIndexDemo(std::shared_ptr<InnerDemuxerDemo> innerDemuxerDemo)317 static void ConvertPtsFrameIndexDemo(std::shared_ptr<InnerDemuxerDemo> innerDemuxerDemo)
318 {
319 uint32_t trackIndex = 0;
320 uint64_t relativePresentationTimeUs = 0; // pts 0
321
322 using clock = std::chrono::high_resolution_clock;
323 auto start = clock::now();
324 auto end = clock::now();
325 std::chrono::duration<double> elapsed = end - start;
326
327 for (uint32_t index = 0; index < 10 ; ++index) { // get first 10 frames
328 start = clock::now();
329 int32_t ret = innerDemuxerDemo->GetRelativePresentationTimeUsByIndex(trackIndex,
330 index, relativePresentationTimeUs);
331 if (ret != 0) {
332 break;
333 }
334 end = clock::now();
335 elapsed = end - start;
336 printf("GetRelativePresentationTimeUsByIndex, relativePresentationTimeUs = %" PRId64 "\n",
337 relativePresentationTimeUs);
338 printf("Function took %f seconds to run.\n", elapsed.count());
339
340 start = clock::now();
341 ret = innerDemuxerDemo->GetIndexByRelativePresentationTimeUs(trackIndex, relativePresentationTimeUs, index);
342 if (ret != 0) {
343 break;
344 }
345 end = clock::now();
346 elapsed = end - start;
347 printf("GetIndexByRelativePresentationTimeUs, index = %u\n", index);
348 printf("Function took %f seconds to run.\n", elapsed.count());
349 }
350 }
351
RunInnerSourceDemuxer(const std::string & filePath,const std::string & fileMode)352 static void RunInnerSourceDemuxer(const std::string &filePath, const std::string &fileMode)
353 {
354 auto innerSourceDemo = std::make_shared<InnerSourceDemo>();
355 int32_t fd = -1;
356 if (fileMode == "0") {
357 fd = open(filePath.c_str(), O_RDONLY);
358 if (fd < 0) {
359 printf("open file failed\n");
360 return;
361 }
362 size_t filesize = innerSourceDemo->GetFileSize(filePath);
363 innerSourceDemo->CreateWithFD(fd, 0, filesize);
364 } else if (fileMode == "1") {
365 innerSourceDemo->CreateWithURI(filePath);
366 }
367 auto innerDemuxerDemo = std::make_shared<InnerDemuxerDemo>();
368 innerDemuxerDemo->CreateWithSource(innerSourceDemo->avsource_);
369 int32_t trackCount = 0;
370 int64_t duration = 0;
371 Format source_format = innerSourceDemo->GetSourceFormat();
372 source_format.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_COUNT, trackCount);
373 source_format.GetLongValue(MediaDescriptionKey::MD_KEY_DURATION, duration);
374 printf("====>duration:%" PRId64 " total tracks:%d\n", duration, trackCount);
375 ConvertPtsFrameIndexDemo(innerDemuxerDemo);
376 for (int32_t i = 0; i < trackCount; i++) {
377 innerDemuxerDemo->SelectTrackByID(i); // 添加轨道
378 }
379 innerDemuxerDemo->UnselectTrackByID(0); // 去掉轨道
380 innerDemuxerDemo->SelectTrackByID(0);
381 uint32_t buffersize = 1024 * 1024;
382 std::shared_ptr<AVSharedMemoryBase> sharedMemory =
383 std::make_shared<AVSharedMemoryBase>(buffersize, AVSharedMemory::FLAGS_READ_WRITE, "userBuffer");
384 sharedMemory->Init();
385 innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount); // demuxer run
386 printf("seek to 1s,mode:SEEK_NEXT_SYNC\n");
387 innerDemuxerDemo->SeekToTime(g_seekTime, SeekMode::SEEK_NEXT_SYNC); // 测试seek功能
388 innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
389 printf("seek to 1s,mode:SEEK_PREVIOUS_SYNC\n");
390 innerDemuxerDemo->SeekToTime(g_seekTime, SeekMode::SEEK_PREVIOUS_SYNC);
391 innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
392 printf("seek to 1s,mode:SEEK_CLOSEST_SYNC\n");
393 innerDemuxerDemo->SeekToTime(g_seekTime, SeekMode::SEEK_CLOSEST_SYNC);
394 innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
395 printf("seek to 0s,mode:SEEK_CLOSEST_SYNC\n");
396 innerDemuxerDemo->SeekToTime(g_startTime, SeekMode::SEEK_CLOSEST_SYNC);
397 innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
398 innerDemuxerDemo->Destroy();
399 if (fileMode == "0" && fd > 0) {
400 close(fd);
401 }
402 }
403
RunRefParserDemuxer(const std::string & filePath,const std::string & fileMode)404 static void RunRefParserDemuxer(const std::string &filePath, const std::string &fileMode)
405 {
406 auto innerSourceDemo = std::make_shared<InnerSourceDemo>();
407 int32_t fd = open(filePath.c_str(), O_RDONLY);
408 if (fd < 0) {
409 printf("open file failed\n");
410 return;
411 }
412 innerSourceDemo->CreateWithFD(fd, 0, innerSourceDemo->GetFileSize(filePath));
413 auto innerDemuxerDemo = std::make_shared<InnerDemuxerDemo>();
414 innerDemuxerDemo->CreateWithSource(innerSourceDemo->avsource_);
415 int32_t trackCount = 0;
416 int64_t duration = 0;
417 Format source_format = innerSourceDemo->GetSourceFormat();
418 source_format.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_COUNT, trackCount);
419 source_format.GetLongValue(MediaDescriptionKey::MD_KEY_DURATION, duration);
420 printf("====>duration:%" PRId64 " total tracks:%d\n", duration, trackCount);
421 int32_t trackType = 0;
422 int32_t videoTrackIdx = 0;
423 for (int32_t i = 0; i < trackCount; i++) {
424 Format trackFormat = innerSourceDemo->GetTrackFormat(i);
425 trackFormat.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_TYPE, trackType);
426 if (trackType == 1) { // 视频轨道
427 innerDemuxerDemo->SelectTrackByID(i); // 添加轨道
428 videoTrackIdx = i;
429 }
430 }
431 uint32_t buffersize = 1024 * 1024;
432 std::shared_ptr<AVAllocator> allocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
433 std::shared_ptr<OHOS::Media::AVBuffer> avBuffer = OHOS::Media::AVBuffer::CreateAVBuffer(allocator, buffersize);
434 innerDemuxerDemo->StartReferenceParser(0);
435 FrameLayerInfo frameLayerInfo;
436 bool isEosFlag = true;
437 while (isEosFlag) {
438 innerDemuxerDemo->ReadSampleBuffer(videoTrackIdx, avBuffer);
439 if (avBuffer->flag_ == AVCODEC_BUFFER_FLAG_EOS) {
440 cout << "read sample end" << endl;
441 isEosFlag = false;
442 }
443 cout << "size: " << avBuffer->memory_->GetSize() << ",pts: " << avBuffer->pts_ << ", dts: " << avBuffer->dts_
444 << endl;
445 innerDemuxerDemo->GetFrameLayerInfo(avBuffer, frameLayerInfo);
446 cout << "isDiscardable: " << frameLayerInfo.isDiscardable << ", gopId: " << frameLayerInfo.gopId
447 << ", layer: " << frameLayerInfo.layer << endl;
448 }
449 innerDemuxerDemo->Destroy();
450 if (fileMode == "0" && fd > 0) {
451 close(fd);
452 fd = -1;
453 }
454 }
455
RunNativeDemuxerLoop(const std::string & filePath,const std::string & fileMode)456 static void RunNativeDemuxerLoop(const std::string &filePath, const std::string &fileMode)
457 {
458 time_t startTime = 0;
459 time_t curTime = 0;
460 (void)time(&startTime);
461 (void)time(&curTime);
462 while (difftime(curTime, startTime) < g_loopTime) {
463 RunNativeDemuxer(filePath, fileMode);
464 (void)time(&curTime);
465 }
466 return;
467 }
468
RunInnerSourceDemuxerLoop(const std::string & filePath,const std::string & fileMode)469 static void RunInnerSourceDemuxerLoop(const std::string &filePath, const std::string &fileMode)
470 {
471 time_t startTime = 0;
472 time_t curTime = 0;
473 (void)time(&startTime);
474 (void)time(&curTime);
475 while (difftime(curTime, startTime) < g_loopTime) {
476 RunInnerSourceDemuxer(filePath, fileMode);
477 (void)time(&curTime);
478 }
479 return;
480 }
481
RunNativeDemuxerMulti(const std::string & filePath,const std::string & fileMode)482 static void RunNativeDemuxerMulti(const std::string &filePath, const std::string &fileMode)
483 {
484 vector<thread> vecThread;
485 for (uint32_t i = 0; i < g_maxThreadNum; ++i) {
486 vecThread.emplace_back(RunNativeDemuxerLoop, filePath, fileMode);
487 }
488 for (thread &val : vecThread) {
489 val.join();
490 }
491 return;
492 }
493
RunInnerSourceDemuxerMulti(const std::string & filePath,const std::string & fileMode)494 static void RunInnerSourceDemuxerMulti(const std::string &filePath, const std::string &fileMode)
495 {
496 vector<thread> vecThread;
497 for (uint32_t i = 0; i < g_maxThreadNum; ++i) {
498 vecThread.emplace_back(RunInnerSourceDemuxerLoop, filePath, fileMode);
499 }
500 for (thread &val : vecThread) {
501 val.join();
502 }
503 return;
504 }
505
RunNativeDemuxerAllFormat(const std::string & fileMode)506 static void RunNativeDemuxerAllFormat(const std::string &fileMode)
507 {
508 string pathRoot;
509 if (fileMode == "0") {
510 pathRoot = "/data/test/media/";
511 } else if (fileMode == "1") {
512 pathRoot = "http://127.0.0.1:46666/";
513 }
514 int64_t groupNum = g_filelist.size() / g_maxThreadNum;
515 groupNum = (g_loopTime % g_maxThreadNum) == 0 ? groupNum : (groupNum + 1);
516 int64_t looptime = g_loopTime / groupNum;
517 std::mutex mutexPrint;
518 auto loopfunc = [pathRoot, looptime, fileMode, &mutexPrint](uint32_t i) {
519 const string filePath = pathRoot + g_filelist[i];
520 time_t startTime = 0;
521 time_t curTime = 0;
522 (void)time(&startTime);
523 (void)time(&curTime);
524 while (difftime(curTime, startTime) < looptime) {
525 RunNativeDemuxer(filePath, fileMode);
526 (void)time(&curTime);
527 }
528 unique_lock<mutex> lock(mutexPrint);
529 cout << filePath << " loop done" << endl;
530 };
531 for (uint32_t index = 0; index < g_filelist.size(); index += g_maxThreadNum) {
532 vector<thread> vecThread;
533 for (uint32_t i = 0; (i < g_maxThreadNum) && ((index + i) < g_filelist.size()); ++i) {
534 vecThread.emplace_back(loopfunc, index + i);
535 }
536 for (thread &val : vecThread) {
537 val.join();
538 }
539 }
540 return;
541 }
542
PrintPrompt()543 void PrintPrompt()
544 {
545 cout << "Please select a demuxer demo(default native demuxer demo): " << endl;
546 cout << "0:native_demuxer" << endl;
547 cout << "1:ffmpeg_demuxer" << endl;
548 cout << "2:native_demuxer loop" << endl;
549 cout << "3:ffmpeg_demuxer loop" << endl;
550 cout << "4:native_demuxer multithread" << endl;
551 cout << "5:ffmpeg_demuxer multithread" << endl;
552 cout << "6:native_demuxer all format" << endl;
553 cout << "7:native_demuxer drm test" << endl;
554 cout << "8:ffmpeg_demuxe ref test" << endl;
555 }
556
AVSourceDemuxerDemoCase(void)557 void AVSourceDemuxerDemoCase(void)
558 {
559 PrintPrompt();
560 string mode;
561 string fileMode;
562 string filePath;
563 std::unique_ptr<FileServerDemo> server = nullptr;
564 (void)getline(cin, mode);
565 cout << "Please select file path (0) or uri (1) or dataSource (2) or dataSourceExt (3)" << endl;
566 (void)getline(cin, fileMode);
567 if (fileMode == "1") {
568 server = std::make_unique<FileServerDemo>();
569 server->StartServer();
570 }
571 if (mode != "6") {
572 cout << "Please input file path or uri:" << endl;
573 (void)getline(cin, filePath);
574 }
575 if (mode >= "2" && mode <= "6") {
576 cout << "Please set the time spent:" << endl;
577 cin >> g_loopTime;
578 }
579 if (mode == "0" || mode == "") {
580 RunNativeDemuxer(filePath, fileMode);
581 } else if (mode == "1") {
582 RunInnerSourceDemuxer(filePath, fileMode);
583 } else if (mode == "2") {
584 RunNativeDemuxerLoop(filePath, fileMode);
585 } else if (mode == "3") {
586 RunInnerSourceDemuxerLoop(filePath, fileMode);
587 } else if (mode == "4") {
588 RunNativeDemuxerMulti(filePath, fileMode);
589 } else if (mode == "5") {
590 RunInnerSourceDemuxerMulti(filePath, fileMode);
591 } else if (mode == "6") {
592 RunNativeDemuxerAllFormat(fileMode);
593 } else if (mode == "7") {
594 RunDrmNativeDemuxer(filePath, fileMode);
595 } else if (mode == "8") {
596 if (fileMode == "0") {
597 RunRefParserDemuxer(filePath, fileMode);
598 return;
599 }
600 printf("only support local file\n");
601 } else {
602 printf("select 0 or 1\n");
603 }
604 if (fileMode == "1") {
605 server->StopServer();
606 }
607 }
608