• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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