mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
fix 'output' format define; support 'host' auto get; time config use SRS internal format; support auto create stream channel on/off
This commit is contained in:
parent
5e4fdfd1d4
commit
92d351ef35
6 changed files with 163 additions and 64 deletions
|
@ -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信令
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -22,11 +22,7 @@
|
|||
*/
|
||||
|
||||
#include <srs_app_gb28181.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
|
||||
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<std::string> 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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue