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.

137 lines
4.8KB

  1. /*
  2. * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
  3. *
  4. * This file is part of ZLMediaKit(https://github.com/xia-chu/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 <iostream>
  12. #include "Util/logger.h"
  13. #include "Util/NoticeCenter.h"
  14. #include "Poller/EventPoller.h"
  15. #include "Player/PlayerProxy.h"
  16. #include "Rtmp/RtmpPusher.h"
  17. #include "Common/config.h"
  18. #include "Common/Parser.h"
  19. #include "Pusher/MediaPusher.h"
  20. #include "Record/MP4Reader.h"
  21. using namespace std;
  22. using namespace toolkit;
  23. using namespace mediakit;
  24. //推流器,保持强引用
  25. MediaPusher::Ptr g_pusher;
  26. Timer::Ptr g_timer;
  27. MediaSource::Ptr g_src;
  28. //声明函数
  29. //推流失败或断开延迟2秒后重试推流
  30. void rePushDelay(const EventPoller::Ptr &poller,
  31. const string &schema,
  32. const string &vhost,
  33. const string &app,
  34. const string &stream,
  35. const string &filePath,
  36. const string &url);
  37. //创建推流器并开始推流
  38. void createPusher(const EventPoller::Ptr &poller,
  39. const string &schema,
  40. const string &vhost,
  41. const string &app,
  42. const string &stream,
  43. const string &filePath,
  44. const string &url) {
  45. if (!g_src) {
  46. //不限制APP名,并且指定文件绝对路径
  47. g_src = MediaSource::createFromMP4(schema, vhost, app, stream, filePath, false);
  48. }
  49. if (!g_src) {
  50. //文件不存在
  51. WarnL << "MP4文件不存在:" << filePath;
  52. return;
  53. }
  54. //创建推流器并绑定一个MediaSource
  55. g_pusher.reset(new MediaPusher(g_src, poller));
  56. //可以指定rtsp推流方式,支持tcp和udp方式,默认tcp
  57. //(*g_pusher)[Client::kRtpType] = Rtsp::RTP_UDP;
  58. //设置推流中断处理逻辑
  59. g_pusher->setOnShutdown([poller, schema, vhost, app, stream, filePath, url](const SockException &ex) {
  60. WarnL << "Server connection is closed:" << ex.getErrCode() << " " << ex.what();
  61. //重新推流
  62. rePushDelay(poller, schema, vhost, app, stream, filePath, url);
  63. });
  64. //设置发布结果处理逻辑
  65. g_pusher->setOnPublished([poller, schema, vhost, app, stream, filePath, url](const SockException &ex) {
  66. if (ex) {
  67. WarnL << "Publish fail:" << ex.getErrCode() << " " << ex.what();
  68. //如果发布失败,就重试
  69. rePushDelay(poller, schema, vhost, app, stream, filePath, url);
  70. } else {
  71. InfoL << "Publish success,Please play with player:" << url;
  72. }
  73. });
  74. g_pusher->publish(url);
  75. }
  76. //推流失败或断开延迟2秒后重试推流
  77. void rePushDelay(const EventPoller::Ptr &poller,
  78. const string &schema,
  79. const string &vhost,
  80. const string &app,
  81. const string &stream,
  82. const string &filePath,
  83. const string &url) {
  84. g_timer = std::make_shared<Timer>(2.0f, [poller, schema, vhost, app, stream, filePath, url]() {
  85. InfoL << "Re-Publishing...";
  86. //重新推流
  87. createPusher(poller, schema, vhost, app, stream, filePath, url);
  88. //此任务不重复
  89. return false;
  90. }, poller);
  91. }
  92. //这里才是真正执行main函数,你可以把函数名(domain)改成main,然后就可以输入自定义url了
  93. int domain(const string &filePath, const string &pushUrl) {
  94. //设置日志
  95. Logger::Instance().add(std::make_shared<ConsoleChannel>());
  96. Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
  97. //循环点播mp4文件
  98. mINI::Instance()[Record::kFileRepeat] = 1;
  99. mINI::Instance()[Protocol::kHlsDemand] = 1;
  100. mINI::Instance()[Protocol::kTSDemand] = 1;
  101. mINI::Instance()[Protocol::kFMP4Demand] = 1;
  102. //mINI::Instance()[Protocol::kRtspDemand] = 1;
  103. //mINI::Instance()[Protocol::kRtmpDemand] = 1;
  104. auto poller = EventPollerPool::Instance().getPoller();
  105. //vhost/app/stream可以随便自己填,现在不限制app应用名了
  106. createPusher(poller, FindField(pushUrl.data(), nullptr, "://").substr(0, 4), DEFAULT_VHOST, "live", "stream", filePath, pushUrl);
  107. //设置退出信号处理函数
  108. static semaphore sem;
  109. signal(SIGINT, [](int) { sem.post(); });// 设置退出信号
  110. sem.wait();
  111. g_pusher.reset();
  112. g_timer.reset();
  113. return 0;
  114. }
  115. int main(int argc, char *argv[]) {
  116. //可以使用test_server生成的mp4文件
  117. //文件使用绝对路径,推流url支持rtsp和rtmp
  118. return domain("/home/work/test2.mp4", "rtmp://127.0.0.1/live/rtsp_push");
  119. }