Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

368 řádky
12KB

  1. #include "Util/util.h"
  2. #include <memory>
  3. #include "Common/Parser.h"
  4. #include "Common/config.h"
  5. #include "SrtTransportImp.hpp"
  6. namespace SRT {
  7. SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller)
  8. : SrtTransport(poller) {}
  9. SrtTransportImp::~SrtTransportImp() {
  10. InfoP(this);
  11. uint64_t duration = _alive_ticker.createdTime() / 1000;
  12. WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") << _media_info.shortUrl() << ")断开,耗时(s):" << duration;
  13. // 流量统计事件广播
  14. GET_CONFIG(uint32_t, iFlowThreshold, General::kFlowThreshold);
  15. if (_total_bytes >= iFlowThreshold * 1024) {
  16. NoticeCenter::Instance().emitEvent(
  17. Broadcast::kBroadcastFlowReport, _media_info, _total_bytes, duration, !_is_pusher,
  18. static_cast<SockInfo &>(*this));
  19. }
  20. }
  21. void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr_storage *addr) {
  22. SrtTransport::onHandShakeFinished(streamid,addr);
  23. // TODO parse stream id like this zlmediakit.com/live/test?token=1213444&type=push
  24. if (!_addr) {
  25. _addr.reset(new sockaddr_storage(*((sockaddr_storage *)addr)));
  26. }
  27. _is_pusher = false;
  28. TraceL << " stream id " << streamid;
  29. if (!parseStreamid(streamid)) {
  30. onShutdown(SockException(Err_shutdown, "stream id not vaild"));
  31. return;
  32. }
  33. auto params = Parser::parseArgs(_media_info._param_strs);
  34. if (params["m"] == "publish") {
  35. _is_pusher = true;
  36. _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this);
  37. emitOnPublish();
  38. } else {
  39. _is_pusher = false;
  40. emitOnPlay();
  41. }
  42. }
  43. //
  44. bool SrtTransportImp::parseStreamid(std::string &streamid) {
  45. if (!toolkit::start_with(streamid, "#!::")) {
  46. return false;
  47. }
  48. _media_info._schema = SRT_SCHEMA;
  49. std::string real_streamid = streamid.substr(4);
  50. std::string vhost, app, stream_name;
  51. auto params = Parser::parseArgs(real_streamid, ",", "=");
  52. for (auto it : params) {
  53. if (it.first == "h") {
  54. vhost = it.second;
  55. } else if (it.first == "r") {
  56. auto tmps = toolkit::split(it.second, "/");
  57. if (tmps.size() < 2) {
  58. continue;
  59. }
  60. app = tmps[0];
  61. stream_name = tmps[1];
  62. } else {
  63. if (_media_info._param_strs.empty()) {
  64. _media_info._param_strs = it.first + "=" + it.second;
  65. } else {
  66. _media_info._param_strs += "&" + it.first + "=" + it.second;
  67. }
  68. }
  69. }
  70. if (app == "" || stream_name == "") {
  71. return false;
  72. }
  73. if (vhost != "") {
  74. _media_info._vhost = vhost;
  75. } else {
  76. _media_info._vhost = DEFAULT_VHOST;
  77. }
  78. _media_info._app = app;
  79. _media_info._streamid = stream_name;
  80. TraceL << " mediainfo=" << _media_info.shortUrl() << " params=" << _media_info._param_strs;
  81. return true;
  82. }
  83. void SrtTransportImp::onSRTData(DataPacket::Ptr pkt) {
  84. if (!_is_pusher) {
  85. WarnP(this) << "this is a player data ignore";
  86. return;
  87. }
  88. if (_decoder) {
  89. _decoder->input(reinterpret_cast<const uint8_t *>(pkt->payloadData()), pkt->payloadSize());
  90. //TraceL<<" size "<<pkt->payloadSize();
  91. } else {
  92. WarnP(this) << " not reach this";
  93. }
  94. }
  95. void SrtTransportImp::onShutdown(const SockException &ex) {
  96. if (_decoder) {
  97. _decoder->flush();
  98. }
  99. SrtTransport::onShutdown(ex);
  100. }
  101. bool SrtTransportImp::close(mediakit::MediaSource &sender) {
  102. std::string err = StrPrinter << "close media: " << sender.getUrl();
  103. weak_ptr<SrtTransportImp> weak_self = static_pointer_cast<SrtTransportImp>(shared_from_this());
  104. getPoller()->async([weak_self, err]() {
  105. auto strong_self = weak_self.lock();
  106. if (strong_self) {
  107. strong_self->onShutdown(SockException(Err_shutdown, err));
  108. // 主动关闭推流,那么不延时注销
  109. strong_self->_muxer = nullptr;
  110. }
  111. });
  112. return true;
  113. }
  114. // 获取媒体源类型
  115. mediakit::MediaOriginType SrtTransportImp::getOriginType(mediakit::MediaSource &sender) const {
  116. return MediaOriginType::srt_push;
  117. }
  118. // 获取媒体源url或者文件路径
  119. std::string SrtTransportImp::getOriginUrl(mediakit::MediaSource &sender) const {
  120. return _media_info._full_url;
  121. }
  122. // 获取媒体源客户端相关信息
  123. std::shared_ptr<SockInfo> SrtTransportImp::getOriginSock(mediakit::MediaSource &sender) const {
  124. return static_pointer_cast<SockInfo>(getSession());
  125. }
  126. void SrtTransportImp::emitOnPublish() {
  127. std::weak_ptr<SrtTransportImp> weak_self = static_pointer_cast<SrtTransportImp>(shared_from_this());
  128. Broadcast::PublishAuthInvoker invoker = [weak_self](const std::string &err, const ProtocolOption &option) {
  129. auto strong_self = weak_self.lock();
  130. if (!strong_self) {
  131. return;
  132. }
  133. strong_self->getPoller()->async([weak_self, err, option](){
  134. auto strong_self = weak_self.lock();
  135. if (!strong_self) {
  136. return;
  137. }
  138. if (err.empty()) {
  139. strong_self->_muxer = std::make_shared<MultiMediaSourceMuxer>(strong_self->_media_info._vhost,
  140. strong_self->_media_info._app,
  141. strong_self->_media_info._streamid,0.0f,
  142. option);
  143. strong_self->_muxer->setMediaListener(strong_self);
  144. strong_self->doCachedFunc();
  145. InfoP(strong_self) << "允许 srt 推流";
  146. } else {
  147. WarnP(strong_self) << "禁止 srt 推流:" << err;
  148. strong_self->onShutdown(SockException(Err_refused, err));
  149. }
  150. });
  151. };
  152. // 触发推流鉴权事件
  153. auto flag = NoticeCenter::Instance().emitEvent(
  154. Broadcast::kBroadcastMediaPublish, MediaOriginType::srt_push, _media_info, invoker,
  155. static_cast<SockInfo &>(*this));
  156. if (!flag) {
  157. // 该事件无人监听,默认不鉴权
  158. invoker("", ProtocolOption());
  159. }
  160. }
  161. void SrtTransportImp::emitOnPlay() {
  162. std::weak_ptr<SrtTransportImp> weak_self = static_pointer_cast<SrtTransportImp>(shared_from_this());
  163. Broadcast::AuthInvoker invoker = [weak_self](const string &err) {
  164. auto strong_self = weak_self.lock();
  165. if (!strong_self) {
  166. return;
  167. }
  168. strong_self->getPoller()->async([strong_self, err] {
  169. if (err != "") {
  170. strong_self->onShutdown(SockException(Err_refused, err));
  171. } else {
  172. strong_self->doPlay();
  173. }
  174. });
  175. };
  176. auto flag = NoticeCenter::Instance().emitEvent(
  177. Broadcast::kBroadcastMediaPlayed, _media_info, invoker, static_cast<SockInfo &>(*this));
  178. if (!flag) {
  179. doPlay();
  180. }
  181. }
  182. void SrtTransportImp::doPlay() {
  183. // 异步查找直播流
  184. MediaInfo info = _media_info;
  185. info._schema = TS_SCHEMA;
  186. std::weak_ptr<SrtTransportImp> weak_self = static_pointer_cast<SrtTransportImp>(shared_from_this());
  187. MediaSource::findAsync(info, getSession(), [weak_self](const MediaSource::Ptr &src) {
  188. auto strong_self = weak_self.lock();
  189. if (!strong_self) {
  190. // 本对象已经销毁
  191. TraceL << "本对象已经销毁";
  192. return;
  193. }
  194. if (!src) {
  195. // 未找到该流
  196. TraceL << "未找到该流";
  197. strong_self->onShutdown(SockException(Err_shutdown));
  198. } else {
  199. TraceL << "找到该流";
  200. auto ts_src = dynamic_pointer_cast<TSMediaSource>(src);
  201. assert(ts_src);
  202. ts_src->pause(false);
  203. strong_self->_ts_reader = ts_src->getRing()->attach(strong_self->getPoller());
  204. weak_ptr<Session> weak_session = strong_self->getSession();
  205. strong_self->_ts_reader->setGetInfoCB([weak_session]() { return weak_session.lock(); });
  206. strong_self->_ts_reader->setDetachCB([weak_self]() {
  207. auto strong_self = weak_self.lock();
  208. if (!strong_self) {
  209. // 本对象已经销毁
  210. return;
  211. }
  212. strong_self->onShutdown(SockException(Err_shutdown));
  213. });
  214. strong_self->_ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) {
  215. auto strong_self = weak_self.lock();
  216. if (!strong_self) {
  217. // 本对象已经销毁
  218. return;
  219. }
  220. size_t i = 0;
  221. auto size = ts_list->size();
  222. ts_list->for_each([&](const TSPacket::Ptr &ts) { strong_self->onSendTSData(ts, ++i == size); });
  223. });
  224. }
  225. });
  226. }
  227. std::string SrtTransportImp::get_peer_ip() {
  228. if (!_addr) {
  229. return "::";
  230. }
  231. return SockUtil::inet_ntoa((sockaddr *)_addr.get());
  232. }
  233. uint16_t SrtTransportImp::get_peer_port() {
  234. if (!_addr) {
  235. return 0;
  236. }
  237. return SockUtil::inet_port((sockaddr *)_addr.get());
  238. }
  239. std::string SrtTransportImp::get_local_ip() {
  240. auto s = getSession();
  241. if (s) {
  242. return s->get_local_ip();
  243. }
  244. return "::";
  245. }
  246. uint16_t SrtTransportImp::get_local_port() {
  247. auto s = getSession();
  248. if (s) {
  249. return s->get_local_port();
  250. }
  251. return 0;
  252. }
  253. std::string SrtTransportImp::getIdentifier() const {
  254. return _media_info._streamid;
  255. }
  256. bool SrtTransportImp::inputFrame(const Frame::Ptr &frame) {
  257. if (_muxer) {
  258. //TraceL<<"before type "<<frame->getCodecName()<<" dts "<<frame->dts()<<" pts "<<frame->pts();
  259. auto frame_tmp = std::make_shared<FrameStamp>(frame, _type_to_stamp[frame->getTrackType()],false);
  260. //TraceL<<"after type "<<frame_tmp->getCodecName()<<" dts "<<frame_tmp->dts()<<" pts "<<frame_tmp->pts();
  261. return _muxer->inputFrame(frame_tmp);
  262. }
  263. if (_cached_func.size() > 200) {
  264. WarnL << "cached frame of track(" << frame->getCodecName() << ") is too much, now dropped";
  265. return false;
  266. }
  267. auto frame_cached = Frame::getCacheAbleFrame(frame);
  268. lock_guard<recursive_mutex> lck(_func_mtx);
  269. _cached_func.emplace_back([this, frame_cached]() {
  270. //TraceL<<"before type "<<frame_cached->getCodecName()<<" dts "<<frame_cached->dts()<<" pts "<<frame_cached->pts();
  271. auto frame_tmp = std::make_shared<FrameStamp>(frame_cached, _type_to_stamp[frame_cached->getTrackType()],false);
  272. //TraceL<<"after type "<<frame_tmp->getCodecName()<<" dts "<<frame_tmp->dts()<<" pts "<<frame_tmp->pts();
  273. _muxer->inputFrame(frame_tmp);
  274. });
  275. return true;
  276. }
  277. bool SrtTransportImp::addTrack(const Track::Ptr &track) {
  278. _type_to_stamp.emplace(track->getTrackType(),Stamp());
  279. if (_muxer) {
  280. return _muxer->addTrack(track);
  281. }
  282. lock_guard<recursive_mutex> lck(_func_mtx);
  283. _cached_func.emplace_back([this, track]() { _muxer->addTrack(track); });
  284. return true;
  285. }
  286. void SrtTransportImp::addTrackCompleted() {
  287. if (_muxer) {
  288. _muxer->addTrackCompleted();
  289. } else {
  290. lock_guard<recursive_mutex> lck(_func_mtx);
  291. _cached_func.emplace_back([this]() { _muxer->addTrackCompleted(); });
  292. }
  293. if(_type_to_stamp.size() >1){
  294. _type_to_stamp[TrackType::TrackAudio].syncTo(_type_to_stamp[TrackType::TrackVideo]);
  295. }
  296. }
  297. void SrtTransportImp::doCachedFunc() {
  298. lock_guard<recursive_mutex> lck(_func_mtx);
  299. for (auto &func : _cached_func) {
  300. func();
  301. }
  302. _cached_func.clear();
  303. }
  304. int SrtTransportImp::getLatencyMul() {
  305. GET_CONFIG(int, latencyMul, kLatencyMul);
  306. if (latencyMul <= 0) {
  307. WarnL << "config srt " << kLatencyMul << " not vaild";
  308. return 4;
  309. }
  310. return latencyMul;
  311. }
  312. float SrtTransportImp::getTimeOutSec() {
  313. GET_CONFIG(float, timeOutSec, kTimeOutSec);
  314. if (timeOutSec <= 0) {
  315. WarnL << "config srt " << kTimeOutSec << " not vaild";
  316. return 5.0;
  317. }
  318. return timeOutSec;
  319. }
  320. int SrtTransportImp::getPktBufSize() {
  321. // kPktBufSize
  322. GET_CONFIG(int, pktBufSize, kPktBufSize);
  323. if (pktBufSize <= 0) {
  324. WarnL << "config srt " << kPktBufSize << " not vaild";
  325. return 8912;
  326. }
  327. return pktBufSize;
  328. }
  329. } // namespace SRT