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 45using namespace std; 46using namespace OHOS::MediaAVCodec; 47using namespace OHOS::Media; 48 49static int64_t g_seekTime = 1000; 50static int64_t g_startTime = 0; 51static int64_t g_loopTime = 20; 52static uint32_t g_maxThreadNum = 16; 53static 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"}; 58static std::string g_filePath; 59 60static 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 104static 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 120static 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 149static 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 197static 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 247static 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 282static 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 334static 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 386static 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 399static 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 412static 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 424static 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 436static 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 473void 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 487void 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