SRT: Support default_mode config for short streamid format. v7.0.131 (#4598)

This commit is contained in:
OSSRS-AI 2025-11-30 16:26:04 -05:00 committed by GitHub
parent 18c30dc07b
commit f47e3ab458
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 406 additions and 44 deletions

View File

@ -0,0 +1,13 @@
---
title: CDK
sidebar_label: CDK
hide_title: false
hide_table_of_contents: false
---
# CDK
Please use [srs-cdk](https://github.com/ossrs/srs-cdk) to deploy SRS on AWS.
![](https://ossrs.io/gif/v1/sls.gif?site=ossrs.io&path=/lts/doc/en/v7/getting-started-cdk)

View File

@ -7,14 +7,16 @@ hide_table_of_contents: false
# K8s # K8s
We recommend using the HELM method to deploy SRS, see [srs-helm](https://github.com/ossrs/srs-helm). Of course, > **Note:** SRS K8s is deprecated. Please use [CDK](./getting-started-cdk.md) instead.
We recommend using the HELM method to deploy SRS, see [srs-helm](https://github.com/ossrs/srs-helm). Of course,
SRS also supports direct deployment with K8s, refer to [SRS K8s](./k8s.md). SRS also supports direct deployment with K8s, refer to [SRS K8s](./k8s.md).
Actually, HELM is based on K8s and deploys K8s pods, which can be managed with kubectl. However, HELM offers a Actually, HELM is based on K8s and deploys K8s pods, which can be managed with kubectl. However, HELM offers a
more convenient way to manage and install applications, so SRS will mainly support HELM in the future. more convenient way to manage and install applications, so SRS will mainly support HELM in the future.
Compared to Docker, HELM and K8s are mainly for medium to large scale deployments. If your business is not that Compared to Docker, HELM and K8s are mainly for medium to large scale deployments. If your business is not that
big, we recommend using Docker or Oryx directly. Generally, if you have less than a thousand streams, please big, we recommend using Docker or Oryx directly. Generally, if you have less than a thousand streams, please
do not use HELM or K8s. do not use HELM or K8s.
![](https://ossrs.io/gif/v1/sls.gif?site=ossrs.io&path=/lts/doc/en/v7/getting-started-k8s) ![](https://ossrs.io/gif/v1/sls.gif?site=ossrs.io&path=/lts/doc/en/v7/getting-started-k8s)

View File

@ -7,6 +7,8 @@ hide_table_of_contents: false
# K8S # K8S
> **Note:** SRS K8s is deprecated. Please use [CDK](./getting-started-cdk.md) instead.
> Cloud+Docker+K8S enable everyone to build live video streaming cluster and service. > Cloud+Docker+K8S enable everyone to build live video streaming cluster and service.
Why should you use [k8s](https://docs.kubernetes.io/docs/concepts/overview/what-is-kubernetes) to build your SRS cluster? Why should you use [k8s](https://docs.kubernetes.io/docs/concepts/overview/what-is-kubernetes) to build your SRS cluster?

View File

@ -58,12 +58,13 @@ srt_server {
# Overwrite by env SRS_SRT_SERVER_ENABLED # Overwrite by env SRS_SRT_SERVER_ENABLED
# default: off # default: off
enabled on; enabled on;
# The UDP listen port for SRT. # The UDP listen endpoints for SRT, each with format as <[ip:]port>. The ip can be either ipv4 or ipv6,
# or both. For example:
# listen 10080 [::]:10080 192.168.1.100:10080 10.10.10.100:10080;
# Overwrite by env SRS_SRT_SERVER_LISTEN # Overwrite by env SRS_SRT_SERVER_LISTEN
listen 10080; listen 10080;
# For detail parameters, please read wiki: # For detail parameters, please read wiki:
# @see https://ossrs.net/lts/zh-cn/docs/v5/doc/srt-params # @see https://ossrs.io/lts/en-us/docs/v7/doc/srt#config
# @see https://ossrs.io/lts/en-us/docs/v5/doc/srt-params
# The maxbw is the max bandwidth of the sender side. # The maxbw is the max bandwidth of the sender side.
# -1: Means the biggest bandwidth is infinity. # -1: Means the biggest bandwidth is infinity.
# 0: Means the bandwidth is determined by SRTO_INPUTBW. # 0: Means the bandwidth is determined by SRTO_INPUTBW.
@ -77,12 +78,12 @@ srt_server {
# Overwrite by env SRS_SRT_SERVER_MSS # Overwrite by env SRS_SRT_SERVER_MSS
# default: 1500 # default: 1500
mss 1500; mss 1500;
# The timeout time of the SRT connection on the sender side in ms. When SRT connects to a peer costs time # The timeout time of the SRT connection on the sender side in ms. When SRT connects to a peer costs time
# more than this config, it will be close. # more than this config, it will be close.
# Overwrite by env SRS_SRT_SERVER_CONNECT_TIMEOUT # Overwrite by env SRS_SRT_SERVER_CONNECT_TIMEOUT
# default: 3000 # default: 3000
connect_timeout 4000; connect_timeout 4000;
# The timeout time of SRT connection on the receiver side in ms. When the SRT connection is idle # The timeout time of SRT connection on the receiver side in ms. When the SRT connection is idle
# more than this config, it will be close. # more than this config, it will be close.
# Overwrite by env SRS_SRT_SERVER_PEER_IDLE_TIMEOUT # Overwrite by env SRS_SRT_SERVER_PEER_IDLE_TIMEOUT
# default: 10000 # default: 10000
@ -91,36 +92,52 @@ srt_server {
# Overwrite by env SRS_SRT_SERVER_DEFAULT_APP # Overwrite by env SRS_SRT_SERVER_DEFAULT_APP
# default: live # default: live
default_app live; default_app live;
# The peerlatency is set by the sender side and will notify the receiver side. # Default mode for short streamid format (without #!:: prefix).
# When client uses short streamid like "live/stream" or "stream", this config
# determines whether it's a publisher or player by default.
# Options: publish, request
# - publish: short streamid is treated as publisher
# - request: short streamid is treated as player (default)
# Example: with default_mode=publish, "srt://host:port?streamid=live/stream" publishes.
# Overwrite by env SRS_SRT_SERVER_DEFAULT_MODE
# default: request
default_mode request;
# Default streamid when client doesn't provide one.
# This is used when SRT client connects without setting SRTO_STREAMID socket option.
# The streamid format follows SRT standard: #!::r=app/stream,m=publish|request
# Overwrite by env SRS_SRT_SERVER_DEFAULT_STREAMID
# default: #!::r=live/livestream,m=request
default_streamid "#!::r=live/livestream,m=request";
# The peerlatency is set by the sender side and will notify the receiver side.
# Overwrite by env SRS_SRT_SERVER_PEERLATENCY # Overwrite by env SRS_SRT_SERVER_PEERLATENCY
# default: 0 # default: 0
peerlatency 0; peerlatency 0;
# The recvlatency means latency from sender to receiver. # The recvlatency means latency from sender to receiver.
# Overwrite by env SRS_SRT_SERVER_RECVLATENCY # Overwrite by env SRS_SRT_SERVER_RECVLATENCY
# default: 120 # default: 120
recvlatency 0; recvlatency 0;
# This latency configuration configures both recvlatency and peerlatency to the same value. # This latency configuration configures both recvlatency and peerlatency to the same value.
# Overwrite by env SRS_SRT_SERVER_LATENCY # Overwrite by env SRS_SRT_SERVER_LATENCY
# default: 120 # default: 120
latency 0; latency 0;
# The tsbpd mode means timestamp based packet delivery. # The tsbpd mode means timestamp based packet delivery.
# SRT sender side will pack timestamp in each packet. If this config is true, # SRT sender side will pack timestamp in each packet. If this config is true,
# the receiver will read the packet according to the timestamp in the head of the packet. # the receiver will read the packet according to the timestamp in the head of the packet.
# Overwrite by env SRS_SRT_SERVER_TSBPDMODE # Overwrite by env SRS_SRT_SERVER_TSBPDMODE
# default: on # default: on
tsbpdmode off; tsbpdmode off;
# The tlpkdrop means too-late Packet Drop # The tlpkdrop means too-late Packet Drop
# SRT sender side will pack timestamp in each packet, When the network is congested, # SRT sender side will pack timestamp in each packet, When the network is congested,
# the packet will drop if latency is bigger than the configuration in both sender side and receiver side. # the packet will drop if latency is bigger than the configuration in both sender side and receiver side.
# And on the sender side, it also will be dropped because latency is bigger than configuration. # And on the sender side, it also will be dropped because latency is bigger than configuration.
# Overwrite by env SRS_SRT_SERVER_TLPKTDROP # Overwrite by env SRS_SRT_SERVER_TLPKTDROP
# default: on # default: on
tlpktdrop off; tlpktdrop off;
# The send buffer size of SRT. # The send buffer size of SRT.
# Overwrite by env SRS_SRT_SERVER_SENDBUF # Overwrite by env SRS_SRT_SERVER_SENDBUF
# default: 8192 * (1500-28) # default: 8192 * (1500-28)
sendbuf 2000000; sendbuf 2000000;
# The recv buffer size of SRT. # The recv buffer size of SRT.
# Overwrite by env SRS_SRT_SERVER_RECVBUF # Overwrite by env SRS_SRT_SERVER_RECVBUF
# default: 8192 * (1500-28) # default: 8192 * (1500-28)
recvbuf 2000000; recvbuf 2000000;
@ -336,6 +353,64 @@ In other words, the following two addresses are equivalent:
* `srt://127.0.0.1:10080` * `srt://127.0.0.1:10080`
* `srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=publish` * `srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=publish`
## SRT URL with short streamid
SRS supports a short streamid format without the `#!::` prefix for simpler URLs. When using short streamid format like `live/livestream` or just `livestream`, SRS uses the `default_mode` configuration to determine whether it's a publish or play request.
The `default_mode` configuration accepts two values:
* `publish`: Short streamid will be treated as publish/push mode.
* `request`: Short streamid will be treated as request/play/pull mode (this is the default).
For publisher-friendly setup where clients can push with simple URLs, configure `default_mode` to `publish`:
```bash
srt_server {
enabled on;
listen 10080;
# Short streamid format will be treated as publisher
default_mode publish;
}
```
With this configuration, you can publish with a simple URL:
```bash
# Publish with short streamid (uses default_mode=publish)
ffmpeg -re -i source.flv -c copy -pes_payload_size 0 -f mpegts \
'srt://127.0.0.1:10080?streamid=live/livestream'
# Play with explicit mode (must specify m=request)
ffplay 'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request'
```
For player-friendly setup where clients can play with simple URLs, use the default `default_mode=request`:
```bash
srt_server {
enabled on;
listen 10080;
# Short streamid format will be treated as player (default)
default_mode request;
}
```
With this configuration, you can play with a simple URL:
```bash
# Publish with explicit mode (must specify m=publish)
ffmpeg -re -i source.flv -c copy -pes_payload_size 0 -f mpegts \
'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=publish'
# Play with short streamid (uses default_mode=request)
ffplay 'srt://127.0.0.1:10080?streamid=live/livestream'
```
SRS provides two ready-to-use configuration files:
* `conf/srt.shortstreamid.publish.conf`: For publisher-friendly setup with `default_mode publish`.
* `conf/srt.shortstreamid.play.conf`: For player-friendly setup with `default_mode request`.
Note that explicit mode specification with the full `#!::` prefix always takes precedence over `default_mode`. This allows clients that support full streamid format to override the default behavior.
## Authentication ## Authentication
For the definition of SRT URLs, please refer to [SRT URL Schema](#srt-url). For the definition of SRT URLs, please refer to [SRT URL Schema](#srt-url).

View File

@ -689,6 +689,16 @@ srt_server {
# Overwrite by env SRS_SRT_SERVER_DEFAULT_APP # Overwrite by env SRS_SRT_SERVER_DEFAULT_APP
# default: live # default: live
default_app live; default_app live;
# Default mode for short streamid format (without #!:: prefix).
# When client uses short streamid like "live/stream" or "stream", this config
# determines whether it's a publisher or player by default.
# Options: publish, request
# - publish: short streamid is treated as publisher
# - request: short streamid is treated as player (default)
# Example: with default_mode=publish, "srt://host:port?streamid=live/stream" publishes.
# Overwrite by env SRS_SRT_SERVER_DEFAULT_MODE
# default: request
default_mode request;
# Default streamid when client doesn't provide one. # Default streamid when client doesn't provide one.
# This is used when SRT client connects without setting SRTO_STREAMID socket option. # This is used when SRT client connects without setting SRTO_STREAMID socket option.
# The streamid format follows SRT standard: #!::r=app/stream,m=publish|request # The streamid format follows SRT standard: #!::r=app/stream,m=publish|request

View File

@ -0,0 +1,51 @@
# SRT with short streamid format and default_mode=request (play/pull)
# For publishing: ffmpeg -re -i source.flv -c copy -pes_payload_size 0 -f mpegts 'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=publish'
# For playing: ffprobe 'srt://127.0.0.1:10080?streamid=live/livestream'
# For playing HTTP-FLV: ffprobe 'http://127.0.0.1:8080/live/livestream.flv'
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_api {
enabled on;
listen 1985;
}
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
srt_server {
enabled on;
listen 10080;
maxbw 1000000000;
connect_timeout 4000;
peerlatency 0;
recvlatency 0;
latency 0;
tsbpdmode off;
tlpktdrop off;
sendbuf 2000000;
recvbuf 2000000;
payloadsize 1316;
# Short streamid format (without #!::) will be treated as player/puller by default.
# This allows: srt://host:port?streamid=live/stream to play directly.
default_mode request;
}
vhost __defaultVhost__ {
srt {
enabled on;
srt_to_rtmp on;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
}

View File

@ -0,0 +1,51 @@
# SRT with short streamid format and default_mode=publish
# For publishing: ffmpeg -re -i source.flv -c copy -pes_payload_size 0 -f mpegts 'srt://127.0.0.1:10080?streamid=live/livestream'
# For playing: ffprobe 'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request'
# For playing HTTP-FLV: ffprobe 'http://127.0.0.1:8080/live/livestream.flv'
listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_api {
enabled on;
listen 1985;
}
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
srt_server {
enabled on;
listen 10080;
maxbw 1000000000;
connect_timeout 4000;
peerlatency 0;
recvlatency 0;
latency 0;
tsbpdmode off;
tlpktdrop off;
sendbuf 2000000;
recvbuf 2000000;
payloadsize 1316;
# Short streamid format (without #!::) will be treated as publisher by default.
# This allows: srt://host:port?streamid=live/stream to publish directly.
default_mode publish;
}
vhost __defaultVhost__ {
srt {
enabled on;
srt_to_rtmp on;
}
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}
}

View File

@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v7-changes"></a> <a name="v7-changes"></a>
## SRS 7.0 Changelog ## SRS 7.0 Changelog
* v7.0, 2025-11-30, SRT: Support default_mode config for short streamid format. v7.0.131
* v7.0, 2025-11-28, SRT: Fix player not exiting when publisher disconnects. v7.0.130 (#4591) * v7.0, 2025-11-28, SRT: Fix player not exiting when publisher disconnects. v7.0.130 (#4591)
* v7.0, 2025-11-27, Merge [#4588](https://github.com/ossrs/srs/pull/4588): RTMP: Ignore FMLE start packet after flash publish. v7.0.129 (#4588) * v7.0, 2025-11-27, Merge [#4588](https://github.com/ossrs/srs/pull/4588): RTMP: Ignore FMLE start packet after flash publish. v7.0.129 (#4588)
* v7.0, 2025-11-18, AI: API: Change pagination default count to 10, minimum 1. v7.0.128 * v7.0, 2025-11-18, AI: API: Change pagination default count to 10, minimum 1. v7.0.128

View File

@ -1935,7 +1935,7 @@ srs_error_t SrsConfig::check_normal_config()
SrsConfDirective *conf = root_->get("srt_server"); SrsConfDirective *conf = root_->get("srt_server");
for (int i = 0; conf && i < (int)conf->directives_.size(); i++) { for (int i = 0; conf && i < (int)conf->directives_.size(); i++) {
string n = conf->at(i)->name_; string n = conf->at(i)->name_;
if (n != "enabled" && n != "listen" && n != "maxbw" && n != "mss" && n != "latency" && n != "recvlatency" && n != "peerlatency" && n != "connect_timeout" && n != "peer_idle_timeout" && n != "sendbuf" && n != "recvbuf" && n != "payloadsize" && n != "default_app" && n != "sei_filter" && n != "mix_correct" && n != "tlpktdrop" && n != "tsbpdmode" && n != "passphrase" && n != "pbkeylen" && n != "default_streamid") { if (n != "enabled" && n != "listen" && n != "maxbw" && n != "mss" && n != "latency" && n != "recvlatency" && n != "peerlatency" && n != "connect_timeout" && n != "peer_idle_timeout" && n != "sendbuf" && n != "recvbuf" && n != "payloadsize" && n != "default_app" && n != "sei_filter" && n != "mix_correct" && n != "tlpktdrop" && n != "tsbpdmode" && n != "passphrase" && n != "pbkeylen" && n != "default_streamid" && n != "default_mode") {
return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal srt_server.%s", n.c_str()); return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal srt_server.%s", n.c_str());
} }
} }
@ -7687,6 +7687,23 @@ string SrsConfig::get_srt_default_streamid()
return conf->arg0(); return conf->arg0();
} }
string SrsConfig::get_srt_default_mode()
{
SRS_OVERWRITE_BY_ENV_STRING("srs.srt_server.default_mode"); // SRS_SRT_SERVER_DEFAULT_MODE
static string DEFAULT = "request";
SrsConfDirective *conf = root_->get("srt_server");
if (!conf) {
return DEFAULT;
}
conf = conf->get("default_mode");
if (!conf || conf->arg0().empty()) {
return DEFAULT;
}
return conf->arg0();
}
SrsConfDirective *SrsConfig::get_srt(std::string vhost) SrsConfDirective *SrsConfig::get_srt(std::string vhost)
{ {
SrsConfDirective *conf = get_vhost(vhost); SrsConfDirective *conf = get_vhost(vhost);

View File

@ -488,6 +488,7 @@ public:
virtual bool get_srt_enabled() = 0; virtual bool get_srt_enabled() = 0;
virtual bool get_srt_enabled(std::string vhost) = 0; virtual bool get_srt_enabled(std::string vhost) = 0;
virtual std::string get_srt_default_streamid() = 0; virtual std::string get_srt_default_streamid() = 0;
virtual std::string get_srt_default_mode() = 0;
virtual bool get_srt_to_rtmp(std::string vhost) = 0; virtual bool get_srt_to_rtmp(std::string vhost) = 0;
virtual bool get_rtc_to_rtmp(std::string vhost) = 0; virtual bool get_rtc_to_rtmp(std::string vhost) = 0;
virtual srs_utime_t get_rtc_stun_timeout(std::string vhost) = 0; virtual srs_utime_t get_rtc_stun_timeout(std::string vhost) = 0;
@ -1078,6 +1079,9 @@ public:
virtual std::string get_default_app_name(); virtual std::string get_default_app_name();
// Get the default streamid when client doesn't provide one. // Get the default streamid when client doesn't provide one.
virtual std::string get_srt_default_streamid(); virtual std::string get_srt_default_streamid();
// Get the default mode for short streamid format.
// @return "publish" or "request", default is "request".
virtual std::string get_srt_default_mode();
// clang-format off // clang-format off
SRS_DECLARE_PRIVATE: // clang-format on SRS_DECLARE_PRIVATE: // clang-format on

View File

@ -299,6 +299,11 @@ std::string SrsConfigProxy::get_default_app_name()
{ {
return _srs_config->get_default_app_name(); return _srs_config->get_default_app_name();
} }
std::string SrsConfigProxy::get_srt_default_mode()
{
return _srs_config->get_srt_default_mode();
}
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
SrsTrueTime::SrsTrueTime() SrsTrueTime::SrsTrueTime()

View File

@ -189,6 +189,7 @@ public:
public: public:
virtual srs_utime_t get_pithy_print(); virtual srs_utime_t get_pithy_print();
virtual std::string get_default_app_name(); virtual std::string get_default_app_name();
virtual std::string get_srt_default_mode();
}; };
// The time to use system time. // The time to use system time.

View File

@ -344,7 +344,7 @@ srs_error_t SrsMpegtsSrtConn::do_cycle()
// Detect streamid of srt to request. // Detect streamid of srt to request.
SrtMode mode = SrtModePull; SrtMode mode = SrtModePull;
if (!srs_srt_streamid_to_request(streamid, mode, req_)) { if (!srs_srt_streamid_to_request(config_, streamid, mode, req_)) {
return srs_error_new(ERROR_SRT_CONN, "invalid srt streamid=%s", streamid.c_str()); return srs_error_new(ERROR_SRT_CONN, "invalid srt streamid=%s", streamid.c_str());
} }

View File

@ -9,6 +9,6 @@
#define VERSION_MAJOR 7 #define VERSION_MAJOR 7
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 130 #define VERSION_REVISION 131
#endif #endif

View File

@ -24,6 +24,9 @@ public:
public: public:
virtual srs_utime_t get_pithy_print() = 0; virtual srs_utime_t get_pithy_print() = 0;
virtual std::string get_default_app_name() = 0; virtual std::string get_default_app_name() = 0;
// Get the default mode for short streamid format.
// @return "publish" or "request", default is "request".
virtual std::string get_srt_default_mode() = 0;
}; };
// The factory to create kernel objects. // The factory to create kernel objects.

View File

@ -753,15 +753,20 @@ utsname *SrsProtocolUtility::system_uname()
// See streamid of https://github.com/ossrs/srs/issues/2893 // See streamid of https://github.com/ossrs/srs/issues/2893
// TODO: FIMXE: We should parse SRT streamid to URL object, rather than a HTTP url subpath. // TODO: FIMXE: We should parse SRT streamid to URL object, rather than a HTTP url subpath.
bool srs_srt_streamid_info(const std::string &streamid, SrtMode &mode, std::string &vhost, std::string &url_subpath) bool srs_srt_streamid_info(ISrsConfig *config, const std::string &streamid, SrtMode &mode, std::string &vhost, std::string &url_subpath)
{ {
mode = SrtModePull; mode = SrtModePull;
size_t pos = streamid.find("#!::"); size_t pos = streamid.find("#!::");
if (pos != 0) { if (pos != 0) {
// Short format without #!:: prefix, use default_mode config.
std::string default_mode = config->get_srt_default_mode();
if (default_mode == "publish") {
mode = SrtModePush;
}
pos = streamid.find("/"); pos = streamid.find("/");
if (pos == streamid.npos) { if (pos == streamid.npos) {
SrsUniquePtr<ISrsConfig> config(_srs_kernel_factory->create_config());
url_subpath = config->get_default_app_name() + "/" + streamid; url_subpath = config->get_default_app_name() + "/" + streamid;
return true; return true;
} }
@ -849,10 +854,10 @@ bool srs_srt_streamid_info(const std::string &streamid, SrtMode &mode, std::stri
return true; return true;
} }
bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, ISrsRequest *request) bool srs_srt_streamid_to_request(ISrsConfig *config, const std::string &streamid, SrtMode &mode, ISrsRequest *request)
{ {
string url_subpath = ""; string url_subpath = "";
bool ret = srs_srt_streamid_info(streamid, mode, request->vhost_, url_subpath); bool ret = srs_srt_streamid_info(config, streamid, mode, request->vhost_, url_subpath);
if (!ret) { if (!ret) {
return ret; return ret;
} }
@ -860,7 +865,6 @@ bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, ISr
size_t pos = url_subpath.find("/"); size_t pos = url_subpath.find("/");
string stream_with_params = ""; string stream_with_params = "";
if (pos == string::npos) { if (pos == string::npos) {
SrsUniquePtr<ISrsConfig> config(_srs_kernel_factory->create_config());
request->app_ = config->get_default_app_name(); request->app_ = config->get_default_app_name();
stream_with_params = url_subpath; stream_with_params = url_subpath;
} else { } else {

View File

@ -32,6 +32,7 @@
#include <ifaddrs.h> #include <ifaddrs.h>
class ISrsHttpMessage; class ISrsHttpMessage;
class ISrsConfig;
class SrsMessageHeader; class SrsMessageHeader;
class SrsMediaPacket; class SrsMediaPacket;
@ -169,9 +170,11 @@ enum SrtMode {
}; };
// Get SRT streamid info. // Get SRT streamid info.
extern bool srs_srt_streamid_info(const std::string &streamid, SrtMode &mode, std::string &vhost, std::string &url_subpath); // @param config The config to get default_app and default_mode.
extern bool srs_srt_streamid_info(ISrsConfig *config, const std::string &streamid, SrtMode &mode, std::string &vhost, std::string &url_subpath);
// SRT streamid to request. // SRT streamid to request.
extern bool srs_srt_streamid_to_request(const std::string &streamid, SrtMode &mode, ISrsRequest *request); // @param config The config to get default_app and default_mode.
extern bool srs_srt_streamid_to_request(ISrsConfig *config, const std::string &streamid, SrtMode &mode, ISrsRequest *request);
#endif #endif

View File

@ -326,6 +326,7 @@ public:
bool rtc_enabled_; bool rtc_enabled_;
bool rtc_init_rate_from_sdp_; bool rtc_init_rate_from_sdp_;
bool asprocess_; bool asprocess_;
std::string srt_default_mode_;
public: public:
MockAppConfig() MockAppConfig()
@ -357,6 +358,7 @@ public:
rtc_enabled_ = false; rtc_enabled_ = false;
rtc_init_rate_from_sdp_ = false; rtc_init_rate_from_sdp_ = false;
asprocess_ = false; asprocess_ = false;
srt_default_mode_ = "request";
} }
virtual ~MockAppConfig() virtual ~MockAppConfig()
{ {
@ -533,6 +535,7 @@ public:
virtual bool get_srt_enabled() { return srt_enabled_; } virtual bool get_srt_enabled() { return srt_enabled_; }
virtual bool get_srt_enabled(std::string vhost) { return srt_enabled_; } virtual bool get_srt_enabled(std::string vhost) { return srt_enabled_; }
virtual std::string get_srt_default_streamid() { return "#!::r=live/livestream,m=request"; } virtual std::string get_srt_default_streamid() { return "#!::r=live/livestream,m=request"; }
virtual std::string get_srt_default_mode() { return srt_default_mode_; }
virtual bool get_srt_to_rtmp(std::string vhost) { return srt_to_rtmp_; } virtual bool get_srt_to_rtmp(std::string vhost) { return srt_to_rtmp_; }
virtual srs_utime_t get_srto_peeridletimeout() { return 10 * SRS_UTIME_SECONDS; } virtual srs_utime_t get_srto_peeridletimeout() { return 10 * SRS_UTIME_SECONDS; }
virtual bool get_rtc_to_rtmp(std::string vhost) { return rtc_to_rtmp_; } virtual bool get_rtc_to_rtmp(std::string vhost) { return rtc_to_rtmp_; }

View File

@ -360,11 +360,13 @@ VOID TEST(SrtServerTest, SrtListener)
// Test srt app // Test srt app
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoNormal) VOID TEST(ProtocolSrtTest, SrtGetStreamInfoNormal)
{ {
MockAppConfig config;
if (true) { if (true) {
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode); EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str()); EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream?key1=value1&key2=value2", subpath.c_str()); EXPECT_STREQ("live/livestream?key1=value1&key2=value2", subpath.c_str());
@ -374,7 +376,7 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoNormal)
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=host.com,r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::h=host.com,r=live/livestream,key1=value1,key2=value2", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode); EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("host.com", vhost.c_str()); EXPECT_STREQ("host.com", vhost.c_str());
EXPECT_STREQ("live/livestream?vhost=host.com&key1=value1&key2=value2", subpath.c_str()); EXPECT_STREQ("live/livestream?vhost=host.com&key1=value1&key2=value2", subpath.c_str());
@ -383,11 +385,13 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoNormal)
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoMethod) VOID TEST(ProtocolSrtTest, SrtGetStreamInfoMethod)
{ {
MockAppConfig config;
if (true) { if (true) {
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::r=live/livestream,m=request", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::r=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode); EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("live/livestream", subpath.c_str()); EXPECT_STREQ("live/livestream", subpath.c_str());
} }
@ -396,7 +400,7 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoMethod)
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::r=live/livestream,m=publish", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::r=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode); EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("live/livestream", subpath.c_str()); EXPECT_STREQ("live/livestream", subpath.c_str());
} }
@ -404,11 +408,13 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoMethod)
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible) VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
{ {
MockAppConfig config;
if (true) { if (true) {
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=live/livestream,m=request", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::h=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode); EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str()); EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str()); EXPECT_STREQ("live/livestream", subpath.c_str());
@ -418,7 +424,7 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=live/livestream,m=publish", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::h=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode); EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str()); EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str()); EXPECT_STREQ("live/livestream", subpath.c_str());
@ -428,7 +434,7 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=srs.srt.com.cn/live/livestream,m=request", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::h=srs.srt.com.cn/live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode); EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("srs.srt.com.cn", vhost.c_str()); EXPECT_STREQ("srs.srt.com.cn", vhost.c_str());
EXPECT_STREQ("live/livestream?vhost=srs.srt.com.cn", subpath.c_str()); EXPECT_STREQ("live/livestream?vhost=srs.srt.com.cn", subpath.c_str());
@ -438,7 +444,7 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=srs.srt.com.cn/live/livestream,m=publish", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::h=srs.srt.com.cn/live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode); EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("srs.srt.com.cn", vhost.c_str()); EXPECT_STREQ("srs.srt.com.cn", vhost.c_str());
EXPECT_STREQ("live/livestream?vhost=srs.srt.com.cn", subpath.c_str()); EXPECT_STREQ("live/livestream?vhost=srs.srt.com.cn", subpath.c_str());
@ -448,21 +454,132 @@ VOID TEST(ProtocolSrtTest, SrtGetStreamInfoCompatible)
SrtMode mode; SrtMode mode;
string vhost; string vhost;
string subpath; string subpath;
EXPECT_TRUE(srs_srt_streamid_info("#!::h=live/livestream?secret=d6d2be37,m=publish", mode, vhost, subpath)); EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::h=live/livestream?secret=d6d2be37,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode); EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str()); EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream?secret=d6d2be37", subpath.c_str()); EXPECT_STREQ("live/livestream?secret=d6d2be37", subpath.c_str());
} }
} }
// Test short streamid format with default_mode config
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoShortFormat)
{
MockAppConfig config;
config.srt_default_mode_ = "request";
// Test short format "live/livestream" - default mode is request (pull)
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "live/livestream", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str());
}
// Test minimal format "livestream" - uses default app "live"
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "livestream", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str());
}
// Test short format with stream name only, different stream
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "testkey", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/testkey", subpath.c_str());
}
// Test short format with custom app
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "myapp/mystream", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("myapp/mystream", subpath.c_str());
}
}
// Test short streamid format with default_mode=publish via mock config
VOID TEST(ProtocolSrtTest, SrtGetStreamInfoShortFormatPublishMode)
{
MockAppConfig config;
config.srt_default_mode_ = "publish";
// Test short format "live/livestream" - should be push mode now
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "live/livestream", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str());
}
// Test minimal format "livestream" - uses default app "live", push mode
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "livestream", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/livestream", subpath.c_str());
}
// Test short format "testkey" - push mode
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "testkey", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("", vhost.c_str());
EXPECT_STREQ("live/testkey", subpath.c_str());
}
// Full YAML format should still respect explicit mode (not affected by default_mode)
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::r=live/livestream,m=request", mode, vhost, subpath));
EXPECT_EQ(SrtModePull, mode);
EXPECT_STREQ("live/livestream", subpath.c_str());
}
if (true) {
SrtMode mode;
string vhost;
string subpath;
EXPECT_TRUE(srs_srt_streamid_info(&config, "#!::r=live/livestream,m=publish", mode, vhost, subpath));
EXPECT_EQ(SrtModePush, mode);
EXPECT_STREQ("live/livestream", subpath.c_str());
}
}
VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest) VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
{ {
MockAppConfig config;
SrsProtocolUtility utility; SrsProtocolUtility utility;
if (true) { if (true) {
SrtMode mode; SrtMode mode;
SrsRequest req; SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::r=live/livestream?key1=val1,key2=val2", mode, &req)); EXPECT_TRUE(srs_srt_streamid_to_request(&config, "#!::r=live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull); EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost_.c_str(), utility.public_internet_address().c_str()); EXPECT_STREQ(req.vhost_.c_str(), utility.public_internet_address().c_str());
EXPECT_STREQ(req.app_.c_str(), "live"); EXPECT_STREQ(req.app_.c_str(), "live");
@ -473,7 +590,7 @@ VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
if (true) { if (true) {
SrtMode mode; SrtMode mode;
SrsRequest req; SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=srs.srt.com.cn,r=live/livestream?key1=val1,key2=val2", mode, &req)); EXPECT_TRUE(srs_srt_streamid_to_request(&config, "#!::h=srs.srt.com.cn,r=live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull); EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost_.c_str(), "srs.srt.com.cn"); EXPECT_STREQ(req.vhost_.c_str(), "srs.srt.com.cn");
EXPECT_STREQ(req.app_.c_str(), "live"); EXPECT_STREQ(req.app_.c_str(), "live");
@ -484,7 +601,7 @@ VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
if (true) { if (true) {
SrtMode mode; SrtMode mode;
SrsRequest req; SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=live/livestream?key1=val1,key2=val2", mode, &req)); EXPECT_TRUE(srs_srt_streamid_to_request(&config, "#!::h=live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull); EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost_.c_str(), utility.public_internet_address().c_str()); EXPECT_STREQ(req.vhost_.c_str(), utility.public_internet_address().c_str());
EXPECT_STREQ(req.app_.c_str(), "live"); EXPECT_STREQ(req.app_.c_str(), "live");
@ -495,7 +612,7 @@ VOID TEST(ProtocolSrtTest, SrtStreamIdToRequest)
if (true) { if (true) {
SrtMode mode; SrtMode mode;
SrsRequest req; SrsRequest req;
EXPECT_TRUE(srs_srt_streamid_to_request("#!::h=srs.srt.com.cn/live/livestream?key1=val1,key2=val2", mode, &req)); EXPECT_TRUE(srs_srt_streamid_to_request(&config, "#!::h=srs.srt.com.cn/live/livestream?key1=val1,key2=val2", mode, &req));
EXPECT_EQ(mode, SrtModePull); EXPECT_EQ(mode, SrtModePull);
EXPECT_STREQ(req.vhost_.c_str(), "srs.srt.com.cn"); EXPECT_STREQ(req.vhost_.c_str(), "srs.srt.com.cn");
EXPECT_STREQ(req.app_.c_str(), "live"); EXPECT_STREQ(req.app_.c_str(), "live");