From 92d351ef355e412b2dd2be96b947a87142791b52 Mon Sep 17 00:00:00 2001 From: xialixin Date: Fri, 3 Apr 2020 20:19:02 +0800 Subject: [PATCH] fix 'output' format define; support 'host' auto get; time config use SRS internal format; support auto create stream channel on/off --- trunk/conf/push.gb28181.conf | 18 +++- trunk/src/app/srs_app_config.cpp | 50 ++++++--- trunk/src/app/srs_app_config.hpp | 5 +- trunk/src/app/srs_app_gb28181.cpp | 140 ++++++++++++++++++-------- trunk/src/app/srs_app_gb28181.hpp | 8 +- trunk/src/app/srs_app_gb28181_sip.cpp | 6 +- 6 files changed, 163 insertions(+), 64 deletions(-) diff --git a/trunk/conf/push.gb28181.conf b/trunk/conf/push.gb28181.conf index e128db63c..38b781723 100644 --- a/trunk/conf/push.gb28181.conf +++ b/trunk/conf/push.gb28181.conf @@ -10,14 +10,20 @@ http_api { listen 1985; } +stats { + network 0; +} + stream_caster { enabled on; caster gb28181; # 转发流到rtmp服务器地址与端口 # TODO: https://github.com/ossrs/srs/pull/1679/files#r400875104 - # [stream] is VideoChannelCodecID(视频通道编码ID) - output 127.0.0.1:1935; + # [stream] is VideoChannelCodecID(视频通道编码ID) for sip + # 自动创建的道通[stream] 是‘chid[ssrc]’ [ssrc]是rtp的ssrc + # [ssrc] rtp中的ssrc + output rtmp://127.0.0.1:1935/live/[stream]; # 接收设备端rtp流的多路复用端口 listen 9000; @@ -52,8 +58,14 @@ stream_caster { # 也就是设备端将媒体发送的地址,如果是服务器是内外网 # 需要写外网地址, # 调用api创建stream session时返回ip地址也是host + # $CANDIDATE 是系统环境变量,从环境变量获取地址,如果没有配置,用* + # *代表指定stats network 的网卡号地址,如果没有配置network,默认则是第0号网卡地址 # TODO: https://github.com/ossrs/srs/pull/1679/files#r400917594 - host 192.168.1.27; + host $CANDIDATE; + + #根据收到ps rtp包自带创建rtmp媒体通道,不需要api接口创建 + #rtmp地址参数[stream] 就是通道id 格式chid[ssrc] + auto_create_channel off; sip { # 是否启用srs内部sip信令 diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 47bfe7d85..28e63f2f5 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2164,8 +2164,11 @@ srs_error_t SrsConfig::global_to_json(SrsJsonObject* obj) sobj->set(sdir->name, sdir->dumps_arg0_to_str()); } else if (sdir->name == "auto_play") { sobj->set(sdir->name, sdir->dumps_arg0_to_str()); + } else if (sdir->name == "auto_create_channel") { + sobj->set(sdir->name, sdir->dumps_arg0_to_str()); } + } obj->set(dir->name, sobj); } else { @@ -3681,7 +3684,7 @@ srs_error_t SrsConfig::check_normal_config() && n != "listen" && n != "rtp_port_min" && n != "rtp_port_max" && n != "rtp_idle_timeout" && n != "sip" && n != "audio_enable" && n != "wait_keyframe" - && n != "host") { + && n != "host" && n != "auto_create_channel") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal stream_caster.%s", n.c_str()); } @@ -4333,9 +4336,9 @@ srs_utime_t SrsConfig::get_stream_caster_gb28181_rtp_idle_timeout(SrsConfDirecti return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_SECONDS); } -int SrsConfig::get_stream_caster_gb28181_ack_timeout(SrsConfDirective* conf) +srs_utime_t SrsConfig::get_stream_caster_gb28181_ack_timeout(SrsConfDirective* conf) { - static int DEFAULT = 30; + static srs_utime_t DEFAULT = 30 * SRS_UTIME_SECONDS; if (!conf) { return DEFAULT; @@ -4351,12 +4354,13 @@ int SrsConfig::get_stream_caster_gb28181_ack_timeout(SrsConfDirective* conf) return DEFAULT; } - return ::atoi(conf->arg0().c_str()); + return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_SECONDS); } -int SrsConfig::get_stream_caster_gb28181_keepalive_timeout(SrsConfDirective* conf) +srs_utime_t SrsConfig::get_stream_caster_gb28181_keepalive_timeout(SrsConfDirective* conf) { - static int DEFAULT = 120; + static srs_utime_t DEFAULT = 120 * SRS_UTIME_SECONDS; + if (!conf) { return DEFAULT; @@ -4372,22 +4376,28 @@ int SrsConfig::get_stream_caster_gb28181_keepalive_timeout(SrsConfDirective* con return DEFAULT; } - return ::atoi(conf->arg0().c_str()); + return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_SECONDS); } string SrsConfig::get_stream_caster_gb28181_host(SrsConfDirective* conf) { - static string DEFAULT = ""; - - if (!conf) { - return DEFAULT; - } + static string DEFAULT = "*"; conf = conf->get("host"); if (!conf || conf->arg0().empty()) { return DEFAULT; } + string eip = srs_getenv(conf->arg0()); + if (!eip.empty()) { + return eip; + } + + // If configed as ENV, but no ENV set, use default value. + if (srs_string_starts_with(conf->arg0(), "$")) { + return DEFAULT; + } + return conf->arg0(); } @@ -4573,6 +4583,22 @@ bool SrsConfig::get_stream_caster_gb28181_sip_invite_port_fixed(SrsConfDirective } +bool SrsConfig::get_stream_caster_gb28181_auto_create_channel(SrsConfDirective* conf) +{ + static bool DEFAULT = false; + + if (!conf) { + return DEFAULT; + } + + conf = conf->get("auto_create_channel"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + int SrsConfig::get_rtc_server_enabled() { SrsConfDirective* conf = root->get("rtc_server"); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index ad6670de6..06bdafa67 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -501,8 +501,8 @@ public: virtual int get_stream_caster_rtp_port_max(SrsConfDirective* conf); virtual srs_utime_t get_stream_caster_gb28181_rtp_idle_timeout(SrsConfDirective* conf); - virtual int get_stream_caster_gb28181_ack_timeout(SrsConfDirective* conf); - virtual int get_stream_caster_gb28181_keepalive_timeout(SrsConfDirective* conf); + virtual srs_utime_t get_stream_caster_gb28181_ack_timeout(SrsConfDirective* conf); + virtual srs_utime_t get_stream_caster_gb28181_keepalive_timeout(SrsConfDirective* conf); virtual bool get_stream_caster_gb28181_audio_enable(SrsConfDirective* conf); virtual std::string get_stream_caster_gb28181_host(SrsConfDirective* conf); virtual std::string get_stream_caster_gb28181_serial(SrsConfDirective* conf); @@ -513,6 +513,7 @@ public: virtual bool get_stream_caster_gb28181_sip_auto_play(SrsConfDirective* conf); virtual int get_stream_caster_gb28181_sip_listen(SrsConfDirective* conf); virtual bool get_stream_caster_gb28181_sip_invite_port_fixed(SrsConfDirective* conf); + virtual bool get_stream_caster_gb28181_auto_create_channel(SrsConfDirective* conf); // rtc section public: diff --git a/trunk/src/app/srs_app_gb28181.cpp b/trunk/src/app/srs_app_gb28181.cpp index 3fc7ab8d6..1f17c7c24 100644 --- a/trunk/src/app/srs_app_gb28181.cpp +++ b/trunk/src/app/srs_app_gb28181.cpp @@ -22,11 +22,7 @@ */ #include - -#include #include -#include -#include #include using namespace std; @@ -292,9 +288,24 @@ srs_error_t SrsGb28181PsRtpProcessor::on_udp_packet(const sockaddr* from, const muxer = _srs_gb28181->fetch_rtmpmuxer(channel_id); }else { muxer = _srs_gb28181->fetch_rtmpmuxer_by_ssrc(pkt.ssrc); - } + //auto crate channel + if (!muxer && config->auto_create_channel){ + //auto create channel generated id + std::stringstream ss, ss1; + ss << "chid" << pkt.ssrc; + std::string tmp_id = ss.str(); + + SrsGb28181StreamChannel channel; + channel.set_channel_id(tmp_id); + channel.set_port_mode(RTP_PORT_MODE_FIXED); + channel.set_ssrc(pkt.ssrc); + _srs_gb28181->create_stream_channel(&channel); + + muxer = _srs_gb28181->fetch_rtmpmuxer(tmp_id); + } + if (muxer){ //TODO: fixme: the same device uses the same SSRC to send with different local ports //record the first peer port @@ -563,12 +574,23 @@ srs_error_t SrsPsStreamDemixer::on_ps_stream(char* ps_data, int ps_size, uint32_ return err; } +static std::string get_host_candidate_ips(SrsConfDirective* c) +{ + string candidate = _srs_config->get_stream_caster_gb28181_host(c); + if (candidate == "*" || candidate == "0.0.0.0") { + std::vector ips = srs_get_local_ips(); + int index = _srs_config->get_stats_network(); + return ips.at(index); + } else { + return candidate; + } +} //Gb28181 Config SrsGb28181Config::SrsGb28181Config(SrsConfDirective* c) { // TODO: FIXME: support reload. - host = _srs_config->get_stream_caster_gb28181_host(c); + host = get_host_candidate_ips(c); output = _srs_config->get_stream_caster_output(c); rtp_mux_port = _srs_config->get_stream_caster_listen(c); rtp_port_min = _srs_config->get_stream_caster_rtp_port_min(c); @@ -577,6 +599,7 @@ SrsGb28181Config::SrsGb28181Config(SrsConfDirective* c) wait_keyframe = _srs_config->get_stream_caster_gb28181_wait_keyframe(c); audio_enable = _srs_config->get_stream_caster_gb28181_audio_enable(c); + auto_create_channel = _srs_config->get_stream_caster_gb28181_auto_create_channel(c); //sip config sip_enable = _srs_config->get_stream_caster_gb28181_sip_enable(c); @@ -1173,6 +1196,7 @@ SrsGb28181StreamChannel::SrsGb28181StreamChannel(){ ssrc = 0; rtp_peer_port = 0; rtp_peer_ip = ""; + rtmp_url = ""; } SrsGb28181StreamChannel::~SrsGb28181StreamChannel() @@ -1193,6 +1217,8 @@ void SrsGb28181StreamChannel::copy(const SrsGb28181StreamChannel *s){ rtp_peer_ip = s->get_rtp_peer_ip(); rtp_peer_port = s->get_rtp_peer_port(); + + rtmp_url = s->get_rtmp_url(); } void SrsGb28181StreamChannel::dumps(SrsJsonObject* obj) @@ -1202,12 +1228,14 @@ void SrsGb28181StreamChannel::dumps(SrsJsonObject* obj) obj->set("rtmp_port", SrsJsonAny::integer(rtmp_port)); obj->set("app", SrsJsonAny::str(app.c_str())); obj->set("stream", SrsJsonAny::str(stream.c_str())); + obj->set("rtmp_url", SrsJsonAny::str(rtmp_url.c_str())); obj->set("ssrc", SrsJsonAny::integer(ssrc)); obj->set("rtp_port", SrsJsonAny::integer(rtp_port)); obj->set("port_mode", SrsJsonAny::str(port_mode.c_str())); obj->set("rtp_peer_port", SrsJsonAny::integer(rtp_peer_port)); obj->set("rtp_peer_ip", SrsJsonAny::str(rtp_peer_ip.c_str())); + } @@ -1457,18 +1485,6 @@ uint32_t SrsGb28181Manger::create_stream_channel(SrsGb28181StreamChannel *channe return ERROR_SUCCESS; } - if (channel->get_stream().empty()){ - channel->set_stream("[stream]"); - } - - if (channel->get_app().empty()){ - channel->set_stream("[app]"); - } - - if (channel->get_port_mode().empty()){ - channel->set_port_mode(RTP_PORT_MODE_FIXED); - } - //create on rtmp muxer, gb28181 stream to rtmp srs_error_t err = srs_success; if ((err = fetch_or_create_rtmpmuxer(id, &muxer)) != srs_success){ @@ -1482,6 +1498,11 @@ uint32_t SrsGb28181Manger::create_stream_channel(SrsGb28181StreamChannel *channe //random is random allocation port int rtp_port = 0; std::string port_mode = channel->get_port_mode(); + + if (port_mode.empty()){ + port_mode = RTP_PORT_MODE_FIXED; + channel->set_port_mode(port_mode); + } if (port_mode == RTP_PORT_MODE_RANDOM){ alloc_port(&rtp_port); @@ -1503,38 +1524,75 @@ uint32_t SrsGb28181Manger::create_stream_channel(SrsGb28181StreamChannel *channe return ERROR_GB28181_PORT_MODE_INVALID; } - //Generate SSRC according to the hash code, - //of the string value of the id - uint32_t ssrc = generate_ssrc(id); + uint32_t ssrc = channel->get_ssrc(); + if (ssrc == 0){ + //auto generate SSRC according to the hash code, + //of the string value of the id + ssrc = generate_ssrc(id); + } rtmpmuxer_map_by_ssrc(muxer, ssrc); - //Generate RTMP push stream address, - std::string app = channel->get_app(); - std::string stream = channel->get_stream(); - app = srs_string_replace(app, "[app]", "live"); - stream = srs_string_replace(stream, "[stream]", id); - - std::string url = "rtmp://" + config->output + "/" + app + "/" + stream; + //generate RTMP push stream address, + //if the app and stream in the API are empty, + //RTMP URL is generated using the output template parameter + std::string url = ""; int rtmp_port; + string app = channel->get_app(); + string stream = channel->get_stream(); + if (true) { - std::string schema, host, vhost, param, _app, _stream; - srs_discovery_tc_url(url, schema, host, vhost, _app, _stream, rtmp_port, param); - url = srs_generate_rtmp_url(host, rtmp_port, "", "", app, stream, ""); + string tcUrl, stream_name; + + //get template rtmp url configuration + std::string output = config->output; + srs_parse_rtmp_url(output, tcUrl, stream_name); + + string _schema, _host, _vhost, _param, _app, _stream; + srs_discovery_tc_url(tcUrl, _schema, _host, _vhost, _app, _stream, rtmp_port, _param); + + //if the stream name is not parameterized, + //it needs to be parameterized to ensure that the stream name is different + if (!srs_string_contains(stream_name, "[stream]") && + !srs_string_contains(stream_name, "[timestamp]") && + !srs_string_contains(stream_name, "[ssrc]")){ + stream_name = stream_name + "_[stream]"; + } + + if (app.empty()){ + app = _app; + } + + if (stream.empty()) + { + stream = stream_name; + } + + url = srs_generate_rtmp_url(_host, rtmp_port, "", "", app, stream, ""); + url = srs_string_replace(url, "[app]", "live"); + url = srs_string_replace(url, "[stream]", id); std::stringstream ss; ss << ssrc; url = srs_string_replace(url, "[ssrc]", ss.str()); url = srs_path_build_timestamp(url); - } - muxer->set_rtmp_url(url); - srs_trace("gb28181: create new stream channel id:%s rtmp url=%s", id.c_str(), muxer->rtmp_url().c_str()); + + //update channel app stream value + srs_parse_rtmp_url(url, tcUrl, stream_name); + srs_discovery_tc_url(tcUrl, _schema, _host, _vhost, _app, _stream, rtmp_port, _param); + + //generate the value returned to the api response + channel->set_rtp_port(rtp_port); + channel->set_ssrc(ssrc); - //generate the value returned to the api response - channel->set_app(app); - channel->set_stream(stream); - channel->set_rtp_port(rtp_port); - channel->set_rtmp_port(rtmp_port); - channel->set_ip(config->host); - channel->set_ssrc(ssrc); + channel->set_app(_app); + channel->set_stream(stream_name); + channel->set_rtmp_port(rtmp_port); + channel->set_ip(config->host); + std::string play_url = srs_generate_rtmp_url(config->host, rtmp_port, "", "", app, stream_name, ""); + channel->set_rtmp_url(play_url); + } + + muxer->set_rtmp_url(url); + srs_trace("gb28181: create new stream channel id:%s rtmp url=%s", id.c_str(), url.c_str()); muxer->copy_channel(channel); diff --git a/trunk/src/app/srs_app_gb28181.hpp b/trunk/src/app/srs_app_gb28181.hpp index 364e71342..945cf1c08 100644 --- a/trunk/src/app/srs_app_gb28181.hpp +++ b/trunk/src/app/srs_app_gb28181.hpp @@ -299,14 +299,15 @@ public: int rtp_port_min; int rtp_port_max; int rtp_mux_port; + bool auto_create_channel; //sip config int sip_port; std::string sip_serial; std::string sip_realm; bool sip_enable; - int sip_ack_timeout; - int sip_keepalive_timeout; + srs_utime_t sip_ack_timeout; + srs_utime_t sip_keepalive_timeout; bool print_sip_message; bool sip_auto_play; bool sip_invite_port_fixed; @@ -323,6 +324,7 @@ private: std::string port_mode; std::string app; std::string stream; + std::string rtmp_url; std::string ip; int rtp_port; @@ -348,6 +350,7 @@ public: uint32_t get_ssrc() const { return ssrc; } uint32_t get_rtp_peer_port() const { return rtp_peer_port; } std::string get_rtp_peer_ip() const { return rtp_peer_ip; } + std::string get_rtmp_url() const { return rtmp_url; } void set_channel_id(const std::string &i) { channel_id = i; } void set_port_mode(const std::string &p) { port_mode = p; } @@ -359,6 +362,7 @@ public: void set_ssrc( const int &s) { ssrc = s;} void set_rtp_peer_ip( const std::string &p) { rtp_peer_ip = p; } void set_rtp_peer_port( const int &s) { rtp_peer_port = s;} + void set_rtmp_url( const std::string &u) { rtmp_url = u; } void copy(const SrsGb28181StreamChannel *s); void dumps(SrsJsonObject* obj); diff --git a/trunk/src/app/srs_app_gb28181_sip.cpp b/trunk/src/app/srs_app_gb28181_sip.cpp index 8d6f0d911..f734c648b 100644 --- a/trunk/src/app/srs_app_gb28181_sip.cpp +++ b/trunk/src/app/srs_app_gb28181_sip.cpp @@ -122,10 +122,10 @@ srs_error_t SrsGb28181SipService::on_udp_sip(string peer_ip, int peer_port, { srs_error_t err = srs_success; - if (config->print_sip_message || true) + if (config->print_sip_message) { srs_trace("gb28181: request peer_ip=%s, peer_port=%d nbbuf=%d", peer_ip.c_str(), peer_port, nb_buf); - //srs_trace("gb28181: request recv message=%s", buf); + srs_trace("gb28181: request recv message=%s", buf); } if (nb_buf < 10) { @@ -208,8 +208,6 @@ srs_error_t SrsGb28181SipService::on_udp_sip(string peer_ip, int peer_port, SrsGb28181StreamChannel ch; ch.set_channel_id(session_id); ch.set_ip(config->host); - ch.set_stream(session_id); - ch.set_app("live"); if (config->sip_invite_port_fixed){ ch.set_port_mode(RTP_PORT_MODE_FIXED); }else {