You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

129 lines
4.9KB

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