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