test_player.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit).
  5. *
  6. * Use of this source code is governed by MIT-like license that can be found in the
  7. * LICENSE file in the root of the source tree. All contributing project authors
  8. * may be found in the AUTHORS file in the root of the source tree.
  9. */
  10. #include <signal.h>
  11. #include "Util/logger.h"
  12. #include "Util/util.h"
  13. #include <iostream>
  14. #include "Common/config.h"
  15. #include "Rtsp/UDPServer.h"
  16. #include "Player/MediaPlayer.h"
  17. #include "Util/onceToken.h"
  18. #include "Codec/Transcode.h"
  19. #include "YuvDisplayer.h"
  20. #include "AudioSRC.h"
  21. using namespace std;
  22. using namespace toolkit;
  23. using namespace mediakit;
  24. #ifdef WIN32
  25. #include <TCHAR.h>
  26. extern int __argc;
  27. extern TCHAR** __targv;
  28. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstanc, LPSTR lpCmdLine, int nShowCmd) {
  29. int argc = __argc;
  30. char **argv = __targv;
  31. //1. 首先调用AllocConsole创建一个控制台窗口
  32. AllocConsole();
  33. //2. 但此时调用cout或者printf都不能正常输出文字到窗口(包括输入流cin和scanf), 所以需要如下重定向输入输出流:
  34. FILE* stream;
  35. freopen_s(&stream, "CON", "r", stdin);//重定向输入流
  36. freopen_s(&stream, "CON", "w", stdout);//重定向输入流
  37. //3. 如果我们需要用到控制台窗口句柄,可以调用FindWindow取得:
  38. HWND _consoleHwnd;
  39. SetConsoleTitleA("test_player");//设置窗口名
  40. #else
  41. #include <unistd.h>
  42. int main(int argc, char *argv[]) {
  43. #endif
  44. static char *url = argv[1];
  45. {
  46. // 设置退出信号处理函数
  47. signal(SIGINT, [](int) { SDLDisplayerHelper::Instance().shutdown(); });
  48. // 设置日志
  49. Logger::Instance().add(std::make_shared<ConsoleChannel>());
  50. Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
  51. if (argc < 3) {
  52. ErrorL << "\r\n测试方法:./test_player rtxp_url rtp_type\r\n"
  53. << "例如:./test_player rtsp://admin:123456@127.0.0.1/live/0 0\r\n";
  54. return 0;
  55. }
  56. auto player = std::make_shared<MediaPlayer>();
  57. // sdl要求在main线程初始化
  58. auto displayer = std::make_shared<YuvDisplayer>(nullptr, url);
  59. weak_ptr<MediaPlayer> weakPlayer = player;
  60. player->setOnPlayResult([weakPlayer, displayer](const SockException &ex) {
  61. InfoL << "OnPlayResult:" << ex.what();
  62. auto strongPlayer = weakPlayer.lock();
  63. if (ex || !strongPlayer) {
  64. return;
  65. }
  66. auto videoTrack = dynamic_pointer_cast<VideoTrack>(strongPlayer->getTrack(TrackVideo, false));
  67. auto audioTrack = dynamic_pointer_cast<AudioTrack>(strongPlayer->getTrack(TrackAudio, false));
  68. if (videoTrack) {
  69. auto decoder = std::make_shared<FFmpegDecoder>(videoTrack);
  70. decoder->setOnDecode([displayer](const FFmpegFrame::Ptr &yuv) {
  71. SDLDisplayerHelper::Instance().doTask([yuv, displayer]() {
  72. // sdl要求在main线程渲染
  73. displayer->displayYUV(yuv->get());
  74. return true;
  75. });
  76. });
  77. videoTrack->addDelegate([decoder](const Frame::Ptr &frame) { return decoder->inputFrame(frame, false, true); });
  78. }
  79. if (audioTrack) {
  80. auto decoder = std::make_shared<FFmpegDecoder>(audioTrack);
  81. auto audio_player = std::make_shared<AudioPlayer>();
  82. // FFmpeg解码时已经统一转换为16位整型pcm
  83. audio_player->setup(audioTrack->getAudioSampleRate(), audioTrack->getAudioChannel(), AUDIO_S16);
  84. FFmpegSwr::Ptr swr;
  85. decoder->setOnDecode([audio_player, swr](const FFmpegFrame::Ptr &frame) mutable {
  86. if (!swr) {
  87. swr = std::make_shared<FFmpegSwr>(AV_SAMPLE_FMT_S16, frame->get()->channels, frame->get()->channel_layout, frame->get()->sample_rate);
  88. }
  89. auto pcm = swr->inputFrame(frame);
  90. auto len = pcm->get()->nb_samples * pcm->get()->channels * av_get_bytes_per_sample((enum AVSampleFormat)pcm->get()->format);
  91. audio_player->playPCM((const char *)(pcm->get()->data[0]), MIN(len, frame->get()->linesize[0]));
  92. });
  93. audioTrack->addDelegate([decoder](const Frame::Ptr &frame) { return decoder->inputFrame(frame, false, true); });
  94. }
  95. });
  96. player->setOnShutdown([](const SockException &ex) { WarnL << "play shutdown: " << ex.what(); });
  97. (*player)[Client::kRtpType] = atoi(argv[2]);
  98. // 不等待track ready再回调播放成功事件,这样可以加快秒开速度
  99. (*player)[Client::kWaitTrackReady] = false;
  100. if (argc > 3) {
  101. (*player)[Client::kPlayTrack] = atoi(argv[3]);
  102. }
  103. player->play(argv[1]);
  104. SDLDisplayerHelper::Instance().runLoop();
  105. }
  106. sleep(1);
  107. return 0;
  108. }