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 
TestNativeSeek(OH_AVMemory * sampleMem,int32_t trackCount,std::shared_ptr<AVDemuxerDemo> avDemuxerDemo)104 static void TestNativeSeek(OH_AVMemory *sampleMem, int32_t trackCount, std::shared_ptr<AVDemuxerDemo> avDemuxerDemo)
105 {
106     printf("seek to 1s,mode:SEEK_MODE_NEXT_SYNC\n");
107     avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_NEXT_SYNC); // 测试seek功能
108     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
109     printf("seek to 1s,mode:SEEK_MODE_PREVIOUS_SYNC\n");
110     avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_PREVIOUS_SYNC);
111     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
112     printf("seek to 1s,mode:SEEK_MODE_CLOSEST_SYNC\n");
113     avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
114     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
115     printf("seek to 0s,mode:SEEK_MODE_CLOSEST_SYNC\n");
116     avDemuxerDemo->SeekToTime(g_startTime, OH_AVSeekMode::SEEK_MODE_CLOSEST_SYNC);
117     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
118 }
119 
ShowSourceDescription(OH_AVFormat * oh_trackformat)120 static void ShowSourceDescription(OH_AVFormat *oh_trackformat)
121 {
122     int32_t trackType = -1;
123     int64_t duration = -1;
124     const char* mimeType = nullptr;
125     int64_t bitrate = -1;
126     int32_t width = -1;
127     int32_t height = -1;
128     int32_t audioSampleFormat = -1;
129     double keyFrameRate = -1;
130     int32_t profile = -1;
131     int32_t audioChannelCount = -1;
132     int32_t audioSampleRate = -1;
133     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_TRACK_TYPE, &trackType);
134     OH_AVFormat_GetLongValue(oh_trackformat, OH_MD_KEY_DURATION, &duration);
135     OH_AVFormat_GetStringValue(oh_trackformat, OH_MD_KEY_CODEC_MIME, &mimeType);
136     OH_AVFormat_GetLongValue(oh_trackformat, OH_MD_KEY_BITRATE, &bitrate);
137     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_WIDTH, &width);
138     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_HEIGHT, &height);
139     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_AUDIO_SAMPLE_FORMAT, &audioSampleFormat);
140     OH_AVFormat_GetDoubleValue(oh_trackformat, OH_MD_KEY_FRAME_RATE, &keyFrameRate);
141     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_PROFILE, &profile);
142     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_AUD_CHANNEL_COUNT, &audioChannelCount);
143     OH_AVFormat_GetIntValue(oh_trackformat, OH_MD_KEY_AUD_SAMPLE_RATE, &audioSampleRate);
144     printf("===>tracks:%d duration:%" PRId64 " mimeType:%s bitrate:%" PRId64 " width:%d height:%d audioSampleFormat:%d"
145         " keyFrameRate:%.2f profile:%d audioChannelCount:%d audioSampleRate:%d\n", trackType, duration, mimeType,
146         bitrate, width, height, audioSampleFormat, keyFrameRate, profile, audioChannelCount, audioSampleRate);
147 }
148 
RunNativeDemuxer(const std::string & filePath,const std::string & fileMode)149 static void RunNativeDemuxer(const std::string &filePath, const std::string &fileMode)
150 {
151     auto avSourceDemo = std::make_shared<AVSourceDemo>();
152     int32_t fd = -1;
153     if (fileMode == "1") {
154         avSourceDemo->CreateWithURI((char *)(filePath.c_str()));
155     } else if (fileMode == "0" || fileMode == "2") {
156         if ((fd = open(filePath.c_str(), O_RDONLY)) < 0) {
157             printf("open file failed\n");
158             return;
159         }
160         int64_t fileSize = avSourceDemo->GetFileSize(filePath);
161         if (fileMode == "0") {
162             avSourceDemo->CreateWithFD(fd, 0, fileSize);
163         } else if (fileMode == "2") {
164             g_filePath = filePath;
165             OH_AVDataSource dataSource = {fileSize, AVSourceReadAt};
166             avSourceDemo->CreateWithDataSource(&dataSource);
167         }
168     }
169 
170     auto avDemuxerDemo = std::make_shared<AVDemuxerDemo>();
171     OH_AVSource *av_source = avSourceDemo->GetAVSource();
172     avDemuxerDemo->CreateWithSource(av_source);
173     int32_t trackCount = 0;
174     int64_t duration = 0;
175     OH_AVFormat *oh_avformat = avSourceDemo->GetSourceFormat();
176     OH_AVFormat_GetIntValue(oh_avformat, OH_MD_KEY_TRACK_COUNT, &trackCount); // 北向获取sourceformat
177     OH_AVFormat_GetLongValue(oh_avformat, OH_MD_KEY_DURATION, &duration);
178     printf("====>total tracks:%d duration:%" PRId64 "\n", trackCount, duration);
179     for (int32_t i = 0; i < trackCount; i++) {
180         OH_AVFormat *oh_trackformat = avSourceDemo->GetTrackFormat(i);
181         ShowSourceDescription(oh_trackformat);
182         avDemuxerDemo->SelectTrackByID(i); // 添加轨道
183     }
184     uint32_t buffersize = 10 * 1024 * 1024;
185     OH_AVMemory *sampleMem = OH_AVMemory_Create(buffersize); // 创建memory
186     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
187     TestNativeSeek(sampleMem, trackCount, avDemuxerDemo);
188     OH_AVMemory_Destroy(sampleMem);
189     OH_AVFormat_Destroy(oh_avformat);
190     avDemuxerDemo->Destroy();
191     avSourceDemo->Destroy();
192     if (fileMode == "0" && fd > 0) {
193         close(fd);
194     }
195 }
196 
RunDrmNativeDemuxer(const std::string & filePath,const std::string & fileMode)197 static void RunDrmNativeDemuxer(const std::string &filePath, const std::string &fileMode)
198 {
199     auto avSourceDemo = std::make_shared<AVSourceDemo>();
200     int32_t fd = -1;
201     if (fileMode == "0") {
202         fd = open(filePath.c_str(), O_RDONLY);
203         if (fd < 0) {
204             printf("open file failed\n");
205             return;
206         }
207         size_t filesize = avSourceDemo->GetFileSize(filePath);
208         avSourceDemo->CreateWithFD(fd, 0, filesize);
209     } else if (fileMode == "1") {
210         avSourceDemo->CreateWithURI((char *)(filePath.c_str()));
211     }
212     auto avDemuxerDemo = std::make_shared<AVDemuxerDemo>();
213     OH_AVSource *av_source = avSourceDemo->GetAVSource();
214     avDemuxerDemo->CreateWithSource(av_source);
215 
216     // test drm event callback
217     avDemuxerDemo->SetDrmAppCallback();
218 
219     int32_t trackCount = 0;
220     int64_t duration = 0;
221     OH_AVFormat *oh_avformat = avSourceDemo->GetSourceFormat();
222     OH_AVFormat_GetIntValue(oh_avformat, OH_MD_KEY_TRACK_COUNT, &trackCount); // 北向获取sourceformat
223     OH_AVFormat_GetLongValue(oh_avformat, OH_MD_KEY_DURATION, &duration);
224     printf("====>total tracks:%d duration:%" PRId64 "\n", trackCount, duration);
225     for (int32_t i = 0; i < trackCount; i++) {
226         avDemuxerDemo->SelectTrackByID(i); // 添加轨道
227     }
228     uint32_t buffersize = 10 * 1024 * 1024;
229     OH_AVMemory *sampleMem = OH_AVMemory_Create(buffersize); // 创建memory
230     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
231     printf("seek to 1s,mode:SEEK_MODE_NEXT_SYNC\n");
232     avDemuxerDemo->SeekToTime(g_seekTime, OH_AVSeekMode::SEEK_MODE_NEXT_SYNC); // 测试seek功能
233     avDemuxerDemo->ReadAllSamples(sampleMem, trackCount);
234 
235     // test drm GetMediaKeySystemInfos
236     avDemuxerDemo->GetMediaKeySystemInfo();
237 
238     OH_AVMemory_Destroy(sampleMem);
239     OH_AVFormat_Destroy(oh_avformat);
240     avDemuxerDemo->Destroy();
241     avSourceDemo->Destroy();
242     if (fileMode == "0" && fd > 0) {
243         close(fd);
244     }
245 }
246 
ConvertPtsFrameIndexDemo(std::shared_ptr<InnerDemuxerDemo> innerDemuxerDemo)247 static void ConvertPtsFrameIndexDemo(std::shared_ptr<InnerDemuxerDemo> innerDemuxerDemo)
248 {
249     uint32_t trackIndex = 0;
250     uint64_t relativePresentationTimeUs = 0;    // pts 0
251 
252     using clock = std::chrono::high_resolution_clock;
253     auto start = clock::now();
254     auto end = clock::now();
255     std::chrono::duration<double> elapsed = end - start;
256 
257     for (uint32_t index = 0; index < 10 ; ++index) { // get first 10 frames
258         start = clock::now();
259         int32_t ret = innerDemuxerDemo->GetRelativePresentationTimeUsByIndex(trackIndex,
260                                                                              index, relativePresentationTimeUs);
261         if (ret != 0) {
262             break;
263         }
264         end = clock::now();
265         elapsed = end - start;
266         printf("GetRelativePresentationTimeUsByIndex, relativePresentationTimeUs = %" PRId64 "\n",
267             relativePresentationTimeUs);
268         printf("Function took %f seconds to run.\n", elapsed.count());
269 
270         start = clock::now();
271         ret = innerDemuxerDemo->GetIndexByRelativePresentationTimeUs(trackIndex, relativePresentationTimeUs, index);
272         if (ret != 0) {
273             break;
274         }
275         end = clock::now();
276         elapsed = end - start;
277         printf("GetIndexByRelativePresentationTimeUs, index = %u\n", index);
278         printf("Function took %f seconds to run.\n", elapsed.count());
279     }
280 }
281 
RunInnerSourceDemuxer(const std::string & filePath,const std::string & fileMode)282 static void RunInnerSourceDemuxer(const std::string &filePath, const std::string &fileMode)
283 {
284     auto innerSourceDemo = std::make_shared<InnerSourceDemo>();
285     int32_t fd = -1;
286     if (fileMode == "0") {
287         fd = open(filePath.c_str(), O_RDONLY);
288         if (fd < 0) {
289             printf("open file failed\n");
290             return;
291         }
292         size_t filesize = innerSourceDemo->GetFileSize(filePath);
293         innerSourceDemo->CreateWithFD(fd, 0, filesize);
294     } else if (fileMode == "1") {
295         innerSourceDemo->CreateWithURI(filePath);
296     }
297     auto innerDemuxerDemo = std::make_shared<InnerDemuxerDemo>();
298     innerDemuxerDemo->CreateWithSource(innerSourceDemo->avsource_);
299     int32_t trackCount = 0;
300     int64_t duration = 0;
301     Format source_format = innerSourceDemo->GetSourceFormat();
302     source_format.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_COUNT, trackCount);
303     source_format.GetLongValue(MediaDescriptionKey::MD_KEY_DURATION, duration);
304     printf("====>duration:%" PRId64 " total tracks:%d\n", duration, trackCount);
305     ConvertPtsFrameIndexDemo(innerDemuxerDemo);
306     for (int32_t i = 0; i < trackCount; i++) {
307         innerDemuxerDemo->SelectTrackByID(i); // 添加轨道
308     }
309     innerDemuxerDemo->UnselectTrackByID(0); // 去掉轨道
310     innerDemuxerDemo->SelectTrackByID(0);
311     uint32_t buffersize = 1024 * 1024;
312     std::shared_ptr<AVSharedMemoryBase> sharedMemory =
313         std::make_shared<AVSharedMemoryBase>(buffersize, AVSharedMemory::FLAGS_READ_WRITE, "userBuffer");
314     sharedMemory->Init();
315     innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount); // demuxer run
316     printf("seek to 1s,mode:SEEK_NEXT_SYNC\n");
317     innerDemuxerDemo->SeekToTime(g_seekTime, SeekMode::SEEK_NEXT_SYNC); // 测试seek功能
318     innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
319     printf("seek to 1s,mode:SEEK_PREVIOUS_SYNC\n");
320     innerDemuxerDemo->SeekToTime(g_seekTime, SeekMode::SEEK_PREVIOUS_SYNC);
321     innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
322     printf("seek to 1s,mode:SEEK_CLOSEST_SYNC\n");
323     innerDemuxerDemo->SeekToTime(g_seekTime, SeekMode::SEEK_CLOSEST_SYNC);
324     innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
325     printf("seek to 0s,mode:SEEK_CLOSEST_SYNC\n");
326     innerDemuxerDemo->SeekToTime(g_startTime, SeekMode::SEEK_CLOSEST_SYNC);
327     innerDemuxerDemo->ReadAllSamples(sharedMemory, trackCount);
328     innerDemuxerDemo->Destroy();
329     if (fileMode == "0" && fd > 0) {
330         close(fd);
331     }
332 }
333 
RunRefParserDemuxer(const std::string & filePath,const std::string & fileMode)334 static void RunRefParserDemuxer(const std::string &filePath, const std::string &fileMode)
335 {
336     auto innerSourceDemo = std::make_shared<InnerSourceDemo>();
337     int32_t fd = open(filePath.c_str(), O_RDONLY);
338     if (fd < 0) {
339         printf("open file failed\n");
340         return;
341     }
342     innerSourceDemo->CreateWithFD(fd, 0, innerSourceDemo->GetFileSize(filePath));
343     auto innerDemuxerDemo = std::make_shared<InnerDemuxerDemo>();
344     innerDemuxerDemo->CreateWithSource(innerSourceDemo->avsource_);
345     int32_t trackCount = 0;
346     int64_t duration = 0;
347     Format source_format = innerSourceDemo->GetSourceFormat();
348     source_format.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_COUNT, trackCount);
349     source_format.GetLongValue(MediaDescriptionKey::MD_KEY_DURATION, duration);
350     printf("====>duration:%" PRId64 " total tracks:%d\n", duration, trackCount);
351     int32_t trackType = 0;
352     int32_t videoTrackIdx = 0;
353     for (int32_t i = 0; i < trackCount; i++) {
354         Format trackFormat = innerSourceDemo->GetTrackFormat(i);
355         trackFormat.GetIntValue(MediaDescriptionKey::MD_KEY_TRACK_TYPE, trackType);
356         if (trackType == 1) {                     // 视频轨道
357             innerDemuxerDemo->SelectTrackByID(i); // 添加轨道
358             videoTrackIdx = i;
359         }
360     }
361     uint32_t buffersize = 1024 * 1024;
362     std::shared_ptr<AVAllocator> allocator = AVAllocatorFactory::CreateSharedAllocator(MemoryFlag::MEMORY_READ_WRITE);
363     std::shared_ptr<OHOS::Media::AVBuffer> avBuffer = OHOS::Media::AVBuffer::CreateAVBuffer(allocator, buffersize);
364     innerDemuxerDemo->StartReferenceParser(0);
365     FrameLayerInfo frameLayerInfo;
366     bool isEosFlag = true;
367     while (isEosFlag) {
368         innerDemuxerDemo->ReadSampleBuffer(videoTrackIdx, avBuffer);
369         if (avBuffer->flag_ == AVCODEC_BUFFER_FLAG_EOS) {
370             cout << "read sample end" << endl;
371             isEosFlag = false;
372         }
373         cout << "size: " << avBuffer->memory_->GetSize() << ",pts: " << avBuffer->pts_ << ", dts: " << avBuffer->dts_
374              << endl;
375         innerDemuxerDemo->GetFrameLayerInfo(avBuffer, frameLayerInfo);
376         cout << "isDiscardable: " << frameLayerInfo.isDiscardable << ", gopId: " << frameLayerInfo.gopId
377              << ", layer: " << frameLayerInfo.layer << endl;
378     }
379     innerDemuxerDemo->Destroy();
380     if (fileMode == "0" && fd > 0) {
381         close(fd);
382         fd = -1;
383     }
384 }
385 
RunNativeDemuxerLoop(const std::string & filePath,const std::string & fileMode)386 static void RunNativeDemuxerLoop(const std::string &filePath, const std::string &fileMode)
387 {
388     time_t startTime = 0;
389     time_t curTime = 0;
390     (void)time(&startTime);
391     (void)time(&curTime);
392     while (difftime(curTime, startTime) < g_loopTime) {
393         RunNativeDemuxer(filePath, fileMode);
394         (void)time(&curTime);
395     }
396     return;
397 }
398 
RunInnerSourceDemuxerLoop(const std::string & filePath,const std::string & fileMode)399 static void RunInnerSourceDemuxerLoop(const std::string &filePath, const std::string &fileMode)
400 {
401     time_t startTime = 0;
402     time_t curTime = 0;
403     (void)time(&startTime);
404     (void)time(&curTime);
405     while (difftime(curTime, startTime) < g_loopTime) {
406         RunInnerSourceDemuxer(filePath, fileMode);
407         (void)time(&curTime);
408     }
409     return;
410 }
411 
RunNativeDemuxerMulti(const std::string & filePath,const std::string & fileMode)412 static void RunNativeDemuxerMulti(const std::string &filePath, const std::string &fileMode)
413 {
414     vector<thread> vecThread;
415     for (uint32_t i = 0; i < g_maxThreadNum; ++i) {
416         vecThread.emplace_back(RunNativeDemuxerLoop, filePath, fileMode);
417     }
418     for (thread &val : vecThread) {
419         val.join();
420     }
421     return;
422 }
423 
RunInnerSourceDemuxerMulti(const std::string & filePath,const std::string & fileMode)424 static void RunInnerSourceDemuxerMulti(const std::string &filePath, const std::string &fileMode)
425 {
426     vector<thread> vecThread;
427     for (uint32_t i = 0; i < g_maxThreadNum; ++i) {
428         vecThread.emplace_back(RunInnerSourceDemuxerLoop, filePath, fileMode);
429     }
430     for (thread &val : vecThread) {
431         val.join();
432     }
433     return;
434 }
435 
RunNativeDemuxerAllFormat(const std::string & fileMode)436 static void RunNativeDemuxerAllFormat(const std::string &fileMode)
437 {
438     string pathRoot;
439     if (fileMode == "0") {
440         pathRoot = "/data/test/media/";
441     } else if (fileMode == "1") {
442         pathRoot = "http://127.0.0.1:46666/";
443     }
444     int64_t groupNum = g_filelist.size() / g_maxThreadNum;
445     groupNum = (g_loopTime % g_maxThreadNum) == 0 ? groupNum : (groupNum + 1);
446     int64_t looptime = g_loopTime / groupNum;
447     std::mutex mutexPrint;
448     auto loopfunc = [pathRoot, looptime, fileMode, &mutexPrint](uint32_t i) {
449         const string filePath = pathRoot + g_filelist[i];
450         time_t startTime = 0;
451         time_t curTime = 0;
452         (void)time(&startTime);
453         (void)time(&curTime);
454         while (difftime(curTime, startTime) < looptime) {
455             RunNativeDemuxer(filePath, fileMode);
456             (void)time(&curTime);
457         }
458         unique_lock<mutex> lock(mutexPrint);
459         cout << filePath << " loop done" << endl;
460     };
461     for (uint32_t index = 0; index < g_filelist.size(); index += g_maxThreadNum) {
462         vector<thread> vecThread;
463         for (uint32_t i = 0; (i < g_maxThreadNum) && ((index + i) < g_filelist.size()); ++i) {
464             vecThread.emplace_back(loopfunc, index + i);
465         }
466         for (thread &val : vecThread) {
467             val.join();
468         }
469     }
470     return;
471 }
472 
PrintPrompt()473 void PrintPrompt()
474 {
475     cout << "Please select a demuxer demo(default native demuxer demo): " << endl;
476     cout << "0:native_demuxer" << endl;
477     cout << "1:ffmpeg_demuxer" << endl;
478     cout << "2:native_demuxer loop" << endl;
479     cout << "3:ffmpeg_demuxer loop" << endl;
480     cout << "4:native_demuxer multithread" << endl;
481     cout << "5:ffmpeg_demuxer multithread" << endl;
482     cout << "6:native_demuxer all format" << endl;
483     cout << "7:native_demuxer drm test" << endl;
484     cout << "8:ffmpeg_demuxe ref test" << endl;
485 }
486 
AVSourceDemuxerDemoCase(void)487 void AVSourceDemuxerDemoCase(void)
488 {
489     PrintPrompt();
490     string mode;
491     string fileMode;
492     string filePath;
493     std::unique_ptr<FileServerDemo> server = nullptr;
494     (void)getline(cin, mode);
495     cout << "Please select file path (0) or uri (1) or dataSource (2)" << endl;
496     (void)getline(cin, fileMode);
497     if (fileMode == "1") {
498         server = std::make_unique<FileServerDemo>();
499         server->StartServer();
500     }
501     if (mode != "6") {
502         cout << "Please input file path or uri:" << endl;
503         (void)getline(cin, filePath);
504     }
505     if (mode >= "2" && mode <= "6") {
506         cout << "Please set the time spent:" << endl;
507         cin >> g_loopTime;
508     }
509     if (mode == "0" || mode == "") {
510         RunNativeDemuxer(filePath, fileMode);
511     } else if (mode == "1") {
512         RunInnerSourceDemuxer(filePath, fileMode);
513     } else if (mode == "2") {
514         RunNativeDemuxerLoop(filePath, fileMode);
515     } else if (mode == "3") {
516         RunInnerSourceDemuxerLoop(filePath, fileMode);
517     } else if (mode == "4") {
518         RunNativeDemuxerMulti(filePath, fileMode);
519     } else if (mode == "5") {
520         RunInnerSourceDemuxerMulti(filePath, fileMode);
521     } else if (mode == "6") {
522         RunNativeDemuxerAllFormat(fileMode);
523     } else if (mode == "7") {
524         RunDrmNativeDemuxer(filePath, fileMode);
525     } else if (mode == "8") {
526         if (fileMode == "0") {
527             RunRefParserDemuxer(filePath, fileMode);
528             return;
529         }
530         printf("only support local file\n");
531     } else {
532         printf("select 0 or 1\n");
533     }
534     if (fileMode == "1") {
535         server->StopServer();
536     }
537 }
538