From f8373302d02b5e4bfee84ad48a0c9309525c4ceb Mon Sep 17 00:00:00 2001 From: xiongguangjie Date: Sat, 11 Jun 2022 21:37:41 +0800 Subject: [PATCH] change srt streamid like srs srt streamid --- src/Common/macros.h | 62 ++++++++++++++-------------- srt/SrtTransportImp.cpp | 89 +++++++++++++++++++++++++++++++---------- srt/SrtTransportImp.hpp | 5 ++- srt/srt.md | 29 +++++++++++--- srt/srt_en.md | 27 +++++++++++-- 5 files changed, 151 insertions(+), 61 deletions(-) diff --git a/src/Common/macros.h b/src/Common/macros.h index c0cefe92..be3da752 100644 --- a/src/Common/macros.h +++ b/src/Common/macros.h @@ -11,50 +11,53 @@ #ifndef ZLMEDIAKIT_MACROS_H #define ZLMEDIAKIT_MACROS_H +#include "Util/logger.h" #include #include -#include "Util/logger.h" #if defined(__MACH__) #include - #include - #define __BYTE_ORDER BYTE_ORDER - #define __BIG_ENDIAN BIG_ENDIAN - #define __LITTLE_ENDIAN LITTLE_ENDIAN +#include +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN #elif defined(__linux__) - #include - #include +#include +#include #elif defined(_WIN32) - #define BIG_ENDIAN 1 - #define LITTLE_ENDIAN 0 - #define BYTE_ORDER LITTLE_ENDIAN - #define __BYTE_ORDER BYTE_ORDER - #define __BIG_ENDIAN BIG_ENDIAN - #define __LITTLE_ENDIAN LITTLE_ENDIAN +#define BIG_ENDIAN 1 +#define LITTLE_ENDIAN 0 +#define BYTE_ORDER LITTLE_ENDIAN +#define __BYTE_ORDER BYTE_ORDER +#define __BIG_ENDIAN BIG_ENDIAN +#define __LITTLE_ENDIAN LITTLE_ENDIAN #endif #ifndef PACKED - #if !defined(_WIN32) - #define PACKED __attribute__((packed)) - #else - #define PACKED - #endif //!defined(_WIN32) +#if !defined(_WIN32) +#define PACKED __attribute__((packed)) +#else +#define PACKED +#endif //! defined(_WIN32) #endif #ifndef CHECK -#define CHECK(exp,...) mediakit::Assert_ThrowCpp(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) -#endif//CHECK +#define CHECK(exp, ...) mediakit::Assert_ThrowCpp(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__) +#endif // CHECK #ifndef MAX -#define MAX(a,b) ((a) > (b) ? (a) : (b) ) -#endif //MAX +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#endif // MAX #ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b) ) -#endif //MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif // MIN #ifndef CLEAR_ARR -#define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;} -#endif //CLEAR_ARR +#define CLEAR_ARR(arr) \ + for (auto &item : arr) { \ + item = 0; \ + } +#endif // CLEAR_ARR #define VHOST_KEY "vhost" #define HTTP_SCHEMA "http" @@ -64,6 +67,7 @@ #define HLS_SCHEMA "hls" #define TS_SCHEMA "ts" #define FMP4_SCHEMA "fmp4" +#define SRT_SCHEMA "srt" #define DEFAULT_VHOST "__defaultVhost__" #ifdef __cplusplus @@ -78,7 +82,7 @@ namespace mediakit { extern const char kServerName[]; -template +template void Assert_ThrowCpp(int failed, const char *exp, const char *func, const char *file, int line, ARGS &&...args) { if (failed) { std::stringstream ss; @@ -87,5 +91,5 @@ void Assert_ThrowCpp(int failed, const char *exp, const char *func, const char * } } -}//namespace mediakit -#endif //ZLMEDIAKIT_MACROS_H +} // namespace mediakit +#endif // ZLMEDIAKIT_MACROS_H diff --git a/srt/SrtTransportImp.cpp b/srt/SrtTransportImp.cpp index 1ae37064..275b3ba3 100644 --- a/srt/SrtTransportImp.cpp +++ b/srt/SrtTransportImp.cpp @@ -1,10 +1,11 @@ -#include -#include "Util/util.h" +#include "Util/util.h" +#include #include "SrtTransportImp.hpp" namespace SRT { -SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) : SrtTransport(poller) {} +SrtTransportImp::SrtTransportImp(const EventPoller::Ptr &poller) + : SrtTransport(poller) {} SrtTransportImp::~SrtTransportImp() { InfoP(this); @@ -12,7 +13,7 @@ SrtTransportImp::~SrtTransportImp() { WarnP(this) << (_is_pusher ? "srt 推流器(" : "srt 播放器(") << _media_info._vhost << "/" << _media_info._app << "/" << _media_info._streamid << ")断开,耗时(s):" << duration; - //流量统计事件广播 + // 流量统计事件广播 GET_CONFIG(uint32_t, iFlowThreshold, General::kFlowThreshold); if (_total_bytes >= iFlowThreshold * 1024) { NoticeCenter::Instance().emitEvent( @@ -28,15 +29,13 @@ void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr } _is_pusher = false; TraceL << " stream id " << streamid; - if (streamid.empty()) { - onShutdown(SockException(Err_shutdown, "stream id not empty")); + if (!parseStreamid(streamid)) { + onShutdown(SockException(Err_shutdown, "stream id not vaild")); return; } - _media_info.parse("srt://" + streamid); - auto params = Parser::parseArgs(_media_info._param_strs); - if (params["type"] == "push") { + if (params["m"] == "publish") { _is_pusher = true; _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, this); emitOnPublish(); @@ -46,6 +45,56 @@ void SrtTransportImp::onHandShakeFinished(std::string &streamid, struct sockaddr } } +// +bool SrtTransportImp::parseStreamid(std::string &streamid) { + + if (!toolkit::start_with(streamid, "#!::")) { + return false; + } + _media_info._schema = SRT_SCHEMA; + + std::string real_streamid = streamid.substr(4); + std::string vhost, app, stream_name; + + auto params = Parser::parseArgs(real_streamid, ",", "="); + + for (auto it : params) { + if (it.first == "h") { + vhost = it.second; + } else if (it.first == "r") { + auto tmps = toolkit::split(it.second, "/"); + if (tmps.size() < 2) { + continue; + } + app = tmps[0]; + stream_name = tmps[1]; + } else { + if (_media_info._param_strs.empty()) { + _media_info._param_strs = it.first + "=" + it.second; + } else { + _media_info._param_strs += "&" + it.first + "=" + it.second; + } + } + } + if (app == "" || stream_name == "") { + return false; + } + + if (vhost != "") { + _media_info._vhost = vhost; + } else { + _media_info._vhost = DEFAULT_VHOST; + } + + _media_info._app = app; + _media_info._streamid = stream_name; + + TraceL << " vhost=" << _media_info._vhost << " app=" << _media_info._app << " streamid=" << _media_info._streamid + << " params=" << _media_info._param_strs; + + return true; +} + void SrtTransportImp::onSRTData(DataPacket::Ptr pkt) { if (!_is_pusher) { WarnP(this) << "this is a player data ignore"; @@ -66,16 +115,14 @@ bool SrtTransportImp::close(mediakit::MediaSource &sender, bool force) { if (!force && totalReaderCount(sender)) { return false; } - std::string err = StrPrinter << "close media:" << sender.getSchema() << "/" - << sender.getVhost() << "/" - << sender.getApp() << "/" - << sender.getId() << " " << force; + std::string err = StrPrinter << "close media:" << sender.getSchema() << "/" << sender.getVhost() << "/" + << sender.getApp() << "/" << sender.getId() << " " << force; weak_ptr weak_self = static_pointer_cast(shared_from_this()); getPoller()->async([weak_self, err]() { auto strong_self = weak_self.lock(); if (strong_self) { strong_self->onShutdown(SockException(Err_shutdown, err)); - //主动关闭推流,那么不延时注销 + // 主动关闭推流,那么不延时注销 strong_self->_muxer = nullptr; } }); @@ -122,12 +169,12 @@ void SrtTransportImp::emitOnPublish() { } }; - //触发推流鉴权事件 + // 触发推流鉴权事件 auto flag = NoticeCenter::Instance().emitEvent( Broadcast::kBroadcastMediaPublish, MediaOriginType::srt_push, _media_info, invoker, static_cast(*this)); if (!flag) { - //该事件无人监听,默认不鉴权 + // 该事件无人监听,默认不鉴权 invoker("", ProtocolOption()); } } @@ -156,19 +203,19 @@ void SrtTransportImp::emitOnPlay() { } void SrtTransportImp::doPlay() { - //异步查找直播流 + // 异步查找直播流 MediaInfo info = _media_info; info._schema = TS_SCHEMA; std::weak_ptr weak_self = static_pointer_cast(shared_from_this()); MediaSource::findAsync(info, getSession(), [weak_self](const MediaSource::Ptr &src) { auto strong_self = weak_self.lock(); if (!strong_self) { - //本对象已经销毁 + // 本对象已经销毁 TraceL << "本对象已经销毁"; return; } if (!src) { - //未找到该流 + // 未找到该流 TraceL << "未找到该流"; strong_self->onShutdown(SockException(Err_shutdown)); } else { @@ -180,7 +227,7 @@ void SrtTransportImp::doPlay() { strong_self->_ts_reader->setDetachCB([weak_self]() { auto strong_self = weak_self.lock(); if (!strong_self) { - //本对象已经销毁 + // 本对象已经销毁 return; } strong_self->onShutdown(SockException(Err_shutdown)); @@ -188,7 +235,7 @@ void SrtTransportImp::doPlay() { strong_self->_ts_reader->setReadCB([weak_self](const TSMediaSource::RingDataType &ts_list) { auto strong_self = weak_self.lock(); if (!strong_self) { - //本对象已经销毁 + // 本对象已经销毁 return; } size_t i = 0; diff --git a/srt/SrtTransportImp.hpp b/srt/SrtTransportImp.hpp index 67cd23ec..e9df2024 100644 --- a/srt/SrtTransportImp.hpp +++ b/srt/SrtTransportImp.hpp @@ -1,11 +1,11 @@ #ifndef ZLMEDIAKIT_SRT_TRANSPORT_IMP_H #define ZLMEDIAKIT_SRT_TRANSPORT_IMP_H -#include +#include "Common/MultiMediaSourceMuxer.h" #include "Rtp/Decoder.h" #include "SrtTransport.hpp" #include "TS/TSMediaSource.h" -#include "Common/MultiMediaSourceMuxer.h" +#include namespace SRT { @@ -66,6 +66,7 @@ protected: bool inputFrame(const Frame::Ptr &frame) override; private: + bool parseStreamid(std::string &streamid); void emitOnPublish(); void emitOnPlay(); diff --git a/srt/srt.md b/srt/srt.md index 2d504720..ca25f524 100644 --- a/srt/srt.md +++ b/srt/srt.md @@ -9,17 +9,36 @@ ## 使用 -zlm中的srt更加streamid 来确定是推流还是拉流,来确定vhost,app,streamid(ZLM中的) -srt中的streamid 为 `//?type=& =` +zlm中的srt根据streamid 来确定是推流还是拉流,来确定vhost,app,streamid(ZLM中的)、 + +srt中的streamid 为 `#!::key1=value1,key2=value2,key3=value4......` + +h,r为特殊的key,来确定vhost,app,streamid,如果没有h则vhost为默认值 + +m 为特殊key来确定是推流还是拉流,如果为publish 则为推流,否则为拉流 ,如果不存在m,则默认为拉流 + +其他key与m会作为webhook的鉴权参数 + +如: + #!::h=zlmediakit.com,r=live/test,m=publish + + vhost = zlmediakit.com + + app = live + + streamid = test + + 是推流 + - OBS 推流地址 - `srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test?type=push` + `srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish` - ffmpeg 推流 - `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid="__defaultVhost__/live/test?type=push"` + `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish` - ffplay 拉流 - `ffplay -i srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test` + `ffplay -i srt://192.168.1.105:9000?streamid=#!::r=live/test` - vlc 不支持,因为无法指定streamid[参考](https://github.com/Haivision/srt/issues/1015) \ No newline at end of file diff --git a/srt/srt_en.md b/srt/srt_en.md index c4ef2b1d..b30f660d 100644 --- a/srt/srt_en.md +++ b/srt/srt_en.md @@ -9,16 +9,35 @@ ## usage -zlm get vhost,app,streamid and push or play by streamid of srt like this `//?type=& =` +zlm get vhost,app,streamid and push or play by streamid of srt like this +`#!::key1=value1,key2=value2,key3=value4......` + +h and r is special key,to get vhost app streamid, if h not exist ,vhost is default value + +m is special key, to judge is push or pull, if vaule is publish the mode is push,otherwise is play, if m not exist, mode is play + +other key and m ,can use by webhook to auth for play or push + + +like: + #!::h=zlmediakit.com,r=live/test,m=publish + + vhost = zlmediakit.com + + app = live + + streamid = test + + mode is push - OBS push stream url - `srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test?type=push` + `srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish` - ffmpeg push - `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid="__defaultVhost__/live/test?type=push"` + `ffmpeg -re -stream_loop -1 -i test.ts -c:v copy -c:a copy -f mpegts srt://192.168.1.105:9000?streamid=#!::r=live/test,m=publish` - ffplay pull - `ffplay -i srt://192.168.1.105:9000?streamid=__defaultVhost__/live/test` + `ffplay -i srt://192.168.1.105:9000?streamid=#!::r=live/test` - vlc not support ,because can't set stream id [reference](https://github.com/Haivision/srt/issues/1015) \ No newline at end of file