From 54f74104331f2303069eae3d17ab4623a1d07cc3 Mon Sep 17 00:00:00 2001 From: industriousonesoft Date: Sun, 10 Jul 2022 14:01:16 +0800 Subject: [PATCH 1/8] supports to kick off publish as no one watching. --- trunk/conf/rtmp.kickoff.conf | 14 +++++++ trunk/src/app/srs_app_config.cpp | 53 +++++++++++++++++++++++++ trunk/src/app/srs_app_config.hpp | 6 +++ trunk/src/app/srs_app_rtmp_conn.cpp | 13 ++++++ trunk/src/app/srs_app_source.cpp | 31 ++++++++++++++- trunk/src/app/srs_app_source.hpp | 7 ++++ trunk/src/core/srs_core_performance.hpp | 5 +++ 7 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 trunk/conf/rtmp.kickoff.conf diff --git a/trunk/conf/rtmp.kickoff.conf b/trunk/conf/rtmp.kickoff.conf new file mode 100644 index 0000000000..eca6ec133e --- /dev/null +++ b/trunk/conf/rtmp.kickoff.conf @@ -0,0 +1,14 @@ +# the config for srs to delivery RTMP with kicking off publish as no one watching. +# @see https://github.com/ossrs/srs/wiki/v1_CN_SampleRTMP +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; +daemon off; +srs_log_tank console; +vhost __defaultVhost__ { + publish { + kickoff_enabled on; + kickoff_timeout 60000; + } +} \ No newline at end of file diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index c877a4feb8..d6a07f4edb 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2654,7 +2654,12 @@ srs_error_t SrsConfig::check_normal_config() } else if (n == "publish") { for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name; +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + if (m != "mr" && m != "mr_latency" && m != "firstpkt_timeout" && m != "normal_timeout" && m != "parse_sps" + && m != "kickoff_enabled" && m != "kickoff_timeout") { +#else if (m != "mr" && m != "mr_latency" && m != "firstpkt_timeout" && m != "normal_timeout" && m != "parse_sps") { +#endif return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.publish.%s of %s", m.c_str(), vhost->arg0().c_str()); } } @@ -4501,6 +4506,54 @@ srs_utime_t SrsConfig::get_publish_normal_timeout(string vhost) return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); } +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING +bool SrsConfig::get_publish_kickoff_enabled(std::string vhost) +{ + static bool DEFAULT = false; + + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("publish"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("kickoff_enabled"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return SRS_CONF_PERFER_FALSE(conf->arg0()); +} + +srs_utime_t SrsConfig::get_publish_kickoff_timeout(std::string vhost) +{ + // the timeout to kickoff publish as no one watching, + // the default value is 3 minutes. + static srs_utime_t DEFAULT = 180 * SRS_UTIME_SECONDS; + + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("publish"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("kickoff_timeout"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); +} +#endif + int SrsConfig::get_global_chunk_size() { SrsConfDirective* conf = root->get("chunk_size"); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 409de2fd73..c65da2bce6 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -610,6 +610,12 @@ class SrsConfig virtual srs_utime_t get_publish_1stpkt_timeout(std::string vhost); // The normal packet timeout in srs_utime_t for encoder. virtual srs_utime_t get_publish_normal_timeout(std::string vhost); +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + // Whether kickoff publish as no one watching. + virtual bool get_publish_kickoff_enabled(std::string vhost); + // The kickoff timeout in srs_utime_t for publish. + virtual srs_utime_t get_publish_kickoff_timeout(std::string vhost); +#endif private: // Get the global chunk size. virtual int get_global_chunk_size(); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 5542747adf..6baebe8e5e 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -876,6 +876,10 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre // initialize the publish timeout. publish_1stpkt_timeout = _srs_config->get_publish_1stpkt_timeout(req->vhost); publish_normal_timeout = _srs_config->get_publish_normal_timeout(req->vhost); +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + bool publish_kickoff_enabled = _srs_config->get_publish_kickoff_enabled(req->vhost); + srs_utime_t publish_kickoff_timeout = _srs_config->get_publish_kickoff_timeout(req->vhost); +#endif // set the sock options. set_sock_options(); @@ -894,6 +898,15 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre return srs_error_wrap(err, "rtmp: thread quit"); } +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + // Check if the source is expired or not as no one watching. + if (publish_kickoff_enabled && source->expired_as_no_one_watching(publish_kickoff_timeout)) + { + srs_trace("kickoff %s as no one watching for more than %d seconds.", req->tcUrl.c_str(), publish_kickoff_timeout / SRS_UTIME_SECONDS); + return srs_error_wrap(err, "rtmp: kickoff pusher as no one watching."); + } +#endif + pprint->elapse(); // cond wait for timeout. diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index f7120d9d64..2d310ade43 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1926,6 +1926,9 @@ SrsLiveSource::SrsLiveSource() _can_publish = true; die_at = 0; +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + no_one_wating_at = 0; +#endif handler = NULL; bridge_ = NULL; @@ -2005,6 +2008,20 @@ bool SrsLiveSource::expired() return false; } +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING +bool SrsLiveSource::expired_as_no_one_watching(srs_utime_t timeout) +{ + if (no_one_wating_at == 0) { + return false; + } + srs_utime_t now = srs_get_system_time(); + if (now > no_one_wating_at + timeout) { + return true; + } + return false; +} +#endif + srs_error_t SrsLiveSource::initialize(SrsRequest* r, ISrsLiveSourceHandler* h) { srs_error_t err = srs_success; @@ -2592,6 +2609,12 @@ srs_error_t SrsLiveSource::on_publish() SrsStatistic* stat = SrsStatistic::instance(); stat->on_stream_publish(req, _source_id.c_str()); + +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + if (consumers.empty()) { + no_one_wating_at = srs_get_system_time(); + } +#endif return err; } @@ -2648,7 +2671,10 @@ srs_error_t SrsLiveSource::create_consumer(SrsLiveConsumer*& consumer) consumer = new SrsLiveConsumer(this); consumers.push_back(consumer); - +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + no_one_wating_at = 0; +#endif + // for edge, when play edge stream, check the state if (_srs_config->get_vhost_is_edge(req->vhost)) { // notice edge to start for the first client. @@ -2714,6 +2740,9 @@ void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer* consumer) if (consumers.empty()) { play_edge->on_all_client_stop(); die_at = srs_get_system_time(); +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + no_one_wating_at = srs_get_system_time(); +#endif } } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index f26f2945b9..e0031cc535 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -531,6 +531,10 @@ class SrsLiveSource : public ISrsReloadHandler // The last die time, when all consumers quit and no publisher, // We will remove the source when source die. srs_utime_t die_at; +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + // The last time when no one wating. + srs_utime_t no_one_wating_at; +#endif public: SrsLiveSource(); virtual ~SrsLiveSource(); @@ -539,6 +543,9 @@ class SrsLiveSource : public ISrsReloadHandler virtual srs_error_t cycle(); // Remove source when expired. virtual bool expired(); +#ifdef SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + bool expired_as_no_one_watching(srs_utime_t timeout); +#endif public: // Initialize the hls with handlers. virtual srs_error_t initialize(SrsRequest* r, ISrsLiveSourceHandler* h); diff --git a/trunk/src/core/srs_core_performance.hpp b/trunk/src/core/srs_core_performance.hpp index 47bc59cc30..22f87b580e 100644 --- a/trunk/src/core/srs_core_performance.hpp +++ b/trunk/src/core/srs_core_performance.hpp @@ -171,5 +171,10 @@ #define SRS_PERF_GLIBC_MEMORY_CHECK #undef SRS_PERF_GLIBC_MEMORY_CHECK +/** + * kickoff publisher as no one watching. +*/ +#define SRS_PERF_KICKOFF_AS_NO_ONE_WATCHING + #endif From 641d72994dc142f455bca164fd9048d2c8b24032 Mon Sep 17 00:00:00 2001 From: industriousonesoft Date: Tue, 26 Jul 2022 17:41:55 +0800 Subject: [PATCH 2/8] add docker ignore files --- .dockerignore | 1 + trunk/Dockerfile.dist | 46 ++++++++++++++++++++++++++++++++++++++++++ trunk/conf/docker.conf | 4 ++++ 3 files changed, 51 insertions(+) create mode 100644 .dockerignore create mode 100644 trunk/Dockerfile.dist diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..53cbda8b78 --- /dev/null +++ b/.dockerignore @@ -0,0 +1 @@ +/trunk/objs \ No newline at end of file diff --git a/trunk/Dockerfile.dist b/trunk/Dockerfile.dist new file mode 100644 index 0000000000..ddd355e066 --- /dev/null +++ b/trunk/Dockerfile.dist @@ -0,0 +1,46 @@ +############################################################ +# build +############################################################ +ARG repo=ossrs/srs:dev +FROM ${repo} AS build + +ARG BUILDPLATFORM +ARG TARGETPLATFORM +ARG JOBS=2 +ARG SRS_AUTO_PACKAGER +RUN echo "BUILDPLATFORM: $BUILDPLATFORM, TARGETPLATFORM: $TARGETPLATFORM, JOBS: $JOBS, PACKAGER: ${#SRS_AUTO_PACKAGER}" + +# Copy source code to docker. +COPY . /tmp/srs +WORKDIR /tmp/srs/trunk + +# Build and install SRS. +# Note that SRT is enabled by default, so we configure without --srt=on. +RUN ./configure --jobs=${JOBS} && make -j${JOBS} && make install + +# All config files for SRS. +RUN cp -R conf /usr/local/srs/conf && \ + cp research/api-server/static-dir/index.html /usr/local/srs/objs/nginx/html/ && \ + cp research/api-server/static-dir/favicon.ico /usr/local/srs/objs/nginx/html/ && \ + cp research/players/crossdomain.xml /usr/local/srs/objs/nginx/html/ && \ + cp -R research/console /usr/local/srs/objs/nginx/html/ && \ + cp -R research/players /usr/local/srs/objs/nginx/html/ && \ + cp -R 3rdparty/signaling/www/demos /usr/local/srs/objs/nginx/html/ + +############################################################ +# dist +############################################################ +FROM centos:7 AS dist + +# RTMP/1935, API/1985, HTTP/8080 +EXPOSE 1935 1985 8080 8000/udp 10080/udp + +# FFMPEG 4.1 +COPY --from=build /usr/local/bin/ffmpeg /usr/local/srs/objs/ffmpeg/bin/ffmpeg + +# SRS binary, config files and srs-console. +COPY --from=build /usr/local/srs /usr/local/srs + +# Default workdir and command. +WORKDIR /usr/local/srs +CMD ["./objs/srs", "-c", "conf/docker.conf"] \ No newline at end of file diff --git a/trunk/conf/docker.conf b/trunk/conf/docker.conf index f4ae9cd351..96d1313153 100644 --- a/trunk/conf/docker.conf +++ b/trunk/conf/docker.conf @@ -37,4 +37,8 @@ vhost __defaultVhost__ { # @see https://github.com/ossrs/srs/wiki/v4_CN_WebRTC#rtc-to-rtmp rtc_to_rtmp on; } + publish { + kickoff_enabled on; + kickoff_timeout 60000; + } } From f000714a646b2e034dd5bdabd932657e1eba0ba8 Mon Sep 17 00:00:00 2001 From: industriousonesoft Date: Sun, 26 Feb 2023 22:44:21 +0800 Subject: [PATCH 3/8] Kickoff publisher when stream is idle, which means no consumers or players. --- trunk/conf/full.conf | 4 ++++ trunk/conf/rtmp.kickoff.conf | 13 +++++++++++++ trunk/src/app/srs_app_config.cpp | 26 +++++++++++++++++++++++++- trunk/src/app/srs_app_config.hpp | 2 ++ trunk/src/app/srs_app_rtmp_conn.cpp | 6 ++++++ trunk/src/app/srs_app_source.cpp | 21 ++++++++++++++++++++- trunk/src/app/srs_app_source.hpp | 3 +++ 7 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 trunk/conf/rtmp.kickoff.conf diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 9504a0a3d3..d941cfe5d6 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1341,6 +1341,10 @@ vhost publish.srs.com { # Overwrite by env SRS_VHOST_PUBLISH_TRY_ANNEXB_FIRST for all vhosts. # default: on try_annexb_first on; + # The timeout time waiting for new consumers in ms. When the publisher is idle + # more than this config, it will be kicked off. + # default: 0 (0 or negative means disabled) + kickoff_for_idle 0; } } diff --git a/trunk/conf/rtmp.kickoff.conf b/trunk/conf/rtmp.kickoff.conf new file mode 100644 index 0000000000..966b70b865 --- /dev/null +++ b/trunk/conf/rtmp.kickoff.conf @@ -0,0 +1,13 @@ +# the config for srs to delivery RTMP with kicking off publish as no one watching. +# @see https://github.com/ossrs/srs/wiki/v1_CN_SampleRTMP +# @see full.conf for detail config. + +listen 1935; +max_connections 1000; +daemon off; +srs_log_tank console; +vhost __defaultVhost__ { + publish { + kickoff_for_idle 60000; # default is 60s, 0 means disable + } +} \ No newline at end of file diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 0ee7c2f5aa..dfd2d6921a 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2559,7 +2559,7 @@ srs_error_t SrsConfig::check_normal_config() for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name; if (m != "mr" && m != "mr_latency" && m != "firstpkt_timeout" && m != "normal_timeout" - && m != "parse_sps" && m != "try_annexb_first") { + && m != "parse_sps" && m != "try_annexb_first" && m != "kickoff_for_idle") { return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "illegal vhost.publish.%s of %s", m.c_str(), vhost->arg0().c_str()); } } @@ -5340,6 +5340,30 @@ srs_utime_t SrsConfig::get_publish_normal_timeout(string vhost) return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); } +srs_utime_t SrsConfig::get_publish_kickoff_timeout(std::string vhost) +{ + // the timeout to kickoff publish as no one watching, + // the default value is 3 minutes. + static srs_utime_t DEFAULT = 180 * SRS_UTIME_SECONDS; + + SrsConfDirective* conf = get_vhost(vhost); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("publish"); + if (!conf) { + return DEFAULT; + } + + conf = conf->get("kickoff_for_idle"); + if (!conf || conf->arg0().empty()) { + return DEFAULT; + } + + return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); +} + int SrsConfig::get_global_chunk_size() { SRS_OVERWRITE_BY_ENV_INT("srs.vhost.chunk_size"); // SRS_VHOST_CHUNK_SIZE diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 4cbd4b9101..eae3637fd4 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -636,6 +636,8 @@ class SrsConfig virtual srs_utime_t get_publish_1stpkt_timeout(std::string vhost); // The normal packet timeout in srs_utime_t for encoder. virtual srs_utime_t get_publish_normal_timeout(std::string vhost); + // The kickoff timeout in srs_utime_t for publisher. + virtual srs_utime_t get_publish_kickoff_timeout(std::string vhost); private: // Get the global chunk size. virtual int get_global_chunk_size(); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 32b2bd5b48..3e41013d6d 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -985,6 +985,7 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre // initialize the publish timeout. publish_1stpkt_timeout = _srs_config->get_publish_1stpkt_timeout(req->vhost); publish_normal_timeout = _srs_config->get_publish_normal_timeout(req->vhost); + srs_utime_t publish_kickoff_timeout = _srs_config->get_publish_kickoff_timeout(req->vhost); // set the sock options. set_sock_options(); @@ -1008,6 +1009,11 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre return srs_error_wrap(err, "rtmp: thread quit"); } + // Check if the source is expired or idle (no consumers or players). + if (source->idle_for(publish_kickoff_timeout)) { + return srs_error_wrap(err, "rtmp: kickoff publisher as no one watching for a while, url=%s, timeout=%ds", req->tcUrl.c_str(), srsu2si(publish_kickoff_timeout)); + } + pprint->elapse(); // cond wait for timeout. diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 705d328fbe..00e35b2ee4 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1927,6 +1927,7 @@ SrsLiveSource::SrsLiveSource() _can_publish = true; die_at = 0; + idle_at = 0; handler = NULL; bridge_ = NULL; @@ -2008,6 +2009,18 @@ bool SrsLiveSource::expired() return false; } +bool SrsLiveSource::idle_for(srs_utime_t timeout) +{ + if (idle_at == 0 || timeout <= 0) { + return false; + } + srs_utime_t now = srs_get_system_time(); + if (now > idle_at + timeout) { + return true; + } + return false; +} + srs_error_t SrsLiveSource::initialize(SrsRequest* r, ISrsLiveSourceHandler* h) { srs_error_t err = srs_success; @@ -2634,6 +2647,10 @@ srs_error_t SrsLiveSource::on_publish() SrsStatistic* stat = SrsStatistic::instance(); stat->on_stream_publish(req, _source_id.c_str()); + + if (consumers.empty()) { + idle_at = srs_get_system_time(); + } return err; } @@ -2690,7 +2707,8 @@ srs_error_t SrsLiveSource::create_consumer(SrsLiveConsumer*& consumer) consumer = new SrsLiveConsumer(this); consumers.push_back(consumer); - + idle_at = 0; + // for edge, when play edge stream, check the state if (_srs_config->get_vhost_is_edge(req->vhost)) { // notice edge to start for the first client. @@ -2756,6 +2774,7 @@ void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer* consumer) if (consumers.empty()) { play_edge->on_all_client_stop(); die_at = srs_get_system_time(); + idle_at = srs_get_system_time(); } } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index b8025a7bbe..da4d2a6935 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -536,6 +536,8 @@ class SrsLiveSource : public ISrsReloadHandler // The last die time, when all consumers quit and no publisher, // We will remove the source when source die. srs_utime_t die_at; + // The last idle time, when all consumers quit but at least one publisher is alive. + srs_utime_t idle_at; public: SrsLiveSource(); virtual ~SrsLiveSource(); @@ -544,6 +546,7 @@ class SrsLiveSource : public ISrsReloadHandler virtual srs_error_t cycle(); // Remove source when expired. virtual bool expired(); + bool idle_for(srs_utime_t timeout); public: // Initialize the hls with handlers. virtual srs_error_t initialize(SrsRequest* r, ISrsLiveSourceHandler* h); From 3f22bca1cb375c4c1203ff0fcd0b6f582b0c8a64 Mon Sep 17 00:00:00 2001 From: industriousonesoft Date: Sat, 4 Mar 2023 14:58:10 +0800 Subject: [PATCH 4/8] Kickoff: supports env variable configuration and resets the default value. --- trunk/conf/full.conf | 1 + trunk/src/app/srs_app_config.cpp | 7 ++++--- trunk/src/app/srs_app_config.hpp | 2 +- trunk/src/app/srs_app_rtmp_conn.cpp | 2 +- trunk/src/utest/srs_utest_config.cpp | 3 +++ 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index d941cfe5d6..369abe6e8a 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1343,6 +1343,7 @@ vhost publish.srs.com { try_annexb_first on; # The timeout time waiting for new consumers in ms. When the publisher is idle # more than this config, it will be kicked off. + # Overwrite by env SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE for all vhosts. # default: 0 (0 or negative means disabled) kickoff_for_idle 0; } diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index dfd2d6921a..2491ade704 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -5340,11 +5340,12 @@ srs_utime_t SrsConfig::get_publish_normal_timeout(string vhost) return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); } -srs_utime_t SrsConfig::get_publish_kickoff_timeout(std::string vhost) +srs_utime_t SrsConfig::get_publish_kickoff_for_idle(std::string vhost) { + SRS_OVERWRITE_BY_ENV_MILLISECONDS("srs.vhost.publish.kickoff_for_idle"); // SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE // the timeout to kickoff publish as no one watching, - // the default value is 3 minutes. - static srs_utime_t DEFAULT = 180 * SRS_UTIME_SECONDS; + // the default value is 0. + static srs_utime_t DEFAULT = 0 * SRS_UTIME_SECONDS; SrsConfDirective* conf = get_vhost(vhost); if (!conf) { diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index eae3637fd4..35b8361846 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -637,7 +637,7 @@ class SrsConfig // The normal packet timeout in srs_utime_t for encoder. virtual srs_utime_t get_publish_normal_timeout(std::string vhost); // The kickoff timeout in srs_utime_t for publisher. - virtual srs_utime_t get_publish_kickoff_timeout(std::string vhost); + virtual srs_utime_t get_publish_kickoff_for_idle(std::string vhost); private: // Get the global chunk size. virtual int get_global_chunk_size(); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 3e41013d6d..06bed485d3 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -985,7 +985,7 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre // initialize the publish timeout. publish_1stpkt_timeout = _srs_config->get_publish_1stpkt_timeout(req->vhost); publish_normal_timeout = _srs_config->get_publish_normal_timeout(req->vhost); - srs_utime_t publish_kickoff_timeout = _srs_config->get_publish_kickoff_timeout(req->vhost); + srs_utime_t publish_kickoff_timeout = _srs_config->get_publish_kickoff_for_idle(req->vhost); // set the sock options. set_sock_options(); diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index 9ea532676c..cac6e6bf24 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -4461,6 +4461,9 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPublish) SrsSetEnvConfig(try_annexb_first, "SRS_VHOST_PUBLISH_TRY_ANNEXB_FIRST", "off"); EXPECT_FALSE(conf.try_annexb_first("__defaultVhost__")); + + SrsSetEnvConfig(kickoff_for_idle, "SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE", "30"); + EXPECT_EQ(30 * SRS_UTIME_MILLISECONDS, conf.get_publish_kickoff_for_idle("__defaultVhost__")); } } From 04feb8ae5ded03089f11b6ba3df91ca2c12b3d77 Mon Sep 17 00:00:00 2001 From: winlin Date: Sat, 4 Mar 2023 19:27:19 +0800 Subject: [PATCH 5/8] Update release to v5.0.144, v6.0.31 --- trunk/doc/CHANGELOG.md | 4 +++- trunk/src/core/srs_core_version5.hpp | 2 +- trunk/src/core/srs_core_version6.hpp | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 774e648244..018395bd44 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -8,6 +8,7 @@ The changelog for SRS. ## SRS 6.0 Changelog +* v6.0, 2023-03-04, Merge [#3105](https://github.com/ossrs/srs/pull/3105): Kickoff publisher when stream is idle, which means no players. v6.0.31 (#3105) * v6.0, 2023-02-25, Merge [#3438](https://github.com/ossrs/srs/pull/3438): Forward add question mark to the end. v6.0.30 (#3438) * v6.0, 2023-02-25, Merge [#3416](https://github.com/ossrs/srs/pull/3416): GB: Support HEVC for regression test and load tool for GB. v6.0.29 (#3416) * v6.0, 2023-02-25, Merge [#3424](https://github.com/ossrs/srs/pull/3424): API: Add service_id for http_hooks, which identify the process. v6.0.28 (#3424) @@ -44,7 +45,8 @@ The changelog for SRS. ## SRS 5.0 Changelog -* v5.0, 2023-02-25, Merge [#3424](https://github.com/ossrs/srs/pull/3424): API: Add service_id for http_hooks, which identify the process. v5.0.142 (#3424) +* v5.0, 2023-03-04, Merge [#3105](https://github.com/ossrs/srs/pull/3105): Kickoff publisher when stream is idle, which means no players. v5.0.144 (#3105) +* v5.0, 2023-02-25, Merge [#3424](https://github.com/ossrs/srs/pull/3424): API: Add service_id for http_hooks, which identify the process. v5.0.143 (#3424) * v5.0, 2023-02-22, Compatible with legacy RTMP URL. v5.0.142 * v5.0, 2023-02-12, Merge [#3409](https://github.com/ossrs/srs/pull/3409): SRT: Reduce latency to 200ms of srt2rtc.conf. v5.0.141 (#3409) * v5.0, 2023-02-08, Merge [#3391](https://github.com/ossrs/srs/pull/3391): Config: Error when both HLS and HTTP-TS enabled. v5.0.140 (#3391) diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 9814f77e11..46ff71091e 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 143 +#define VERSION_REVISION 144 #endif diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp index cb9ab95591..8439f0c027 100644 --- a/trunk/src/core/srs_core_version6.hpp +++ b/trunk/src/core/srs_core_version6.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 6 #define VERSION_MINOR 0 -#define VERSION_REVISION 30 +#define VERSION_REVISION 31 #endif From 944fcf29c51f4f155ed070b0e3443dbcfbdb99e7 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 6 Mar 2023 08:01:48 +0800 Subject: [PATCH 6/8] Refine code. --- trunk/conf/full.conf | 7 ++--- trunk/conf/rtmp.kickoff.conf | 2 +- trunk/doc/Features.md | 1 + trunk/src/app/srs_app_config.cpp | 18 ++++++++++--- trunk/src/app/srs_app_config.hpp | 1 + trunk/src/app/srs_app_rtmp_conn.cpp | 8 +++--- trunk/src/app/srs_app_source.cpp | 42 ++++++++++++++++++----------- trunk/src/app/srs_app_source.hpp | 16 +++++------ 8 files changed, 61 insertions(+), 34 deletions(-) diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 369abe6e8a..e3cd0f39c9 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1341,10 +1341,11 @@ vhost publish.srs.com { # Overwrite by env SRS_VHOST_PUBLISH_TRY_ANNEXB_FIRST for all vhosts. # default: on try_annexb_first on; - # The timeout time waiting for new consumers in ms. When the publisher is idle - # more than this config, it will be kicked off. + # The timeout in seconds to disconnect publisher when idle, which means no players. + # Note that 0 means no timeout or this feature is disabled. + # Note that this feature conflicts with forward, because it disconnect the publisher stream. # Overwrite by env SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE for all vhosts. - # default: 0 (0 or negative means disabled) + # default: 0 kickoff_for_idle 0; } } diff --git a/trunk/conf/rtmp.kickoff.conf b/trunk/conf/rtmp.kickoff.conf index 966b70b865..7ab0db693e 100644 --- a/trunk/conf/rtmp.kickoff.conf +++ b/trunk/conf/rtmp.kickoff.conf @@ -8,6 +8,6 @@ daemon off; srs_log_tank console; vhost __defaultVhost__ { publish { - kickoff_for_idle 60000; # default is 60s, 0 means disable + kickoff_for_idle 60000; } } \ No newline at end of file diff --git a/trunk/doc/Features.md b/trunk/doc/Features.md index 9c6b0310c5..fb890fd0f3 100644 --- a/trunk/doc/Features.md +++ b/trunk/doc/Features.md @@ -47,6 +47,7 @@ The features of SRS. - [x] Live: Support origin cluster, please read [#464](https://github.com/ossrs/srs/issues/464), [RTMP 302](https://github.com/ossrs/srs/issues/92). v3.0.0+ - [x] Live: Support NGINX HLS Cluster, see [CN](https://ossrs.net/lts/zh-cn/docs/v4/doc/sample-hls-cluster) or [EN](https://ossrs.io/lts/en-us/docs/v4/doc/sample-hls-cluster). v5.0.28+ - [x] Live: SRT: Support PUSH SRT by IP and optional port, see [#3198](https://github.com/ossrs/srs/issues/3198). v5.0.76+ +- [x] Live: Kickoff publisher when stream is idle, which means no players. v5.0.144+ - [x] Live: [Experimental] Support SRT server, read [#1147](https://github.com/ossrs/srs/issues/1147). v4.0.143+ - [x] Live: [Experimental] Support Coroutine Native SRT over ST, [#3010](https://github.com/ossrs/srs/pull/3010). v5.0.30+ - [x] Live: [Experimental] Support MPEG-DASH, Dynamic Adaptive Streaming over HTTP, read [#299](https://github.com/ossrs/srs/issues/299). v5.0.96+ diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 2491ade704..5bb4cdae96 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -2727,6 +2727,14 @@ srs_error_t SrsConfig::check_normal_config() } } + // Check forward dnd kickoff for publsher idle. + for (int n = 0; n < (int)vhosts.size(); n++) { + SrsConfDirective* vhost = vhosts[n]; + if (get_forward_enabled(vhost) && get_publish_kickoff_for_idle(vhost)) { + return srs_error_new(ERROR_SYSTEM_CONFIG_INVALID, "vhost.forward conflicts with vhost.publish.kickoff_for_idle"); + } + } + // check ingest id unique. for (int i = 0; i < (int)vhosts.size(); i++) { SrsConfDirective* vhost = vhosts[i]; @@ -5341,13 +5349,17 @@ srs_utime_t SrsConfig::get_publish_normal_timeout(string vhost) } srs_utime_t SrsConfig::get_publish_kickoff_for_idle(std::string vhost) +{ + return get_publish_kickoff_for_idle(get_vhost(vhost)); +} + +srs_utime_t SrsConfig::get_publish_kickoff_for_idle(SrsConfDirective* vhost) { SRS_OVERWRITE_BY_ENV_MILLISECONDS("srs.vhost.publish.kickoff_for_idle"); // SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE - // the timeout to kickoff publish as no one watching, - // the default value is 0. + static srs_utime_t DEFAULT = 0 * SRS_UTIME_SECONDS; - SrsConfDirective* conf = get_vhost(vhost); + SrsConfDirective* conf = vhost; if (!conf) { return DEFAULT; } diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 35b8361846..f0028b357b 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -638,6 +638,7 @@ class SrsConfig virtual srs_utime_t get_publish_normal_timeout(std::string vhost); // The kickoff timeout in srs_utime_t for publisher. virtual srs_utime_t get_publish_kickoff_for_idle(std::string vhost); + virtual srs_utime_t get_publish_kickoff_for_idle(SrsConfDirective* vhost); private: // Get the global chunk size. virtual int get_global_chunk_size(); diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 06bed485d3..3b0c4eb8f3 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -985,7 +985,7 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre // initialize the publish timeout. publish_1stpkt_timeout = _srs_config->get_publish_1stpkt_timeout(req->vhost); publish_normal_timeout = _srs_config->get_publish_normal_timeout(req->vhost); - srs_utime_t publish_kickoff_timeout = _srs_config->get_publish_kickoff_for_idle(req->vhost); + srs_utime_t publish_kickoff_for_idle = _srs_config->get_publish_kickoff_for_idle(req->vhost); // set the sock options. set_sock_options(); @@ -1009,9 +1009,9 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre return srs_error_wrap(err, "rtmp: thread quit"); } - // Check if the source is expired or idle (no consumers or players). - if (source->idle_for(publish_kickoff_timeout)) { - return srs_error_wrap(err, "rtmp: kickoff publisher as no one watching for a while, url=%s, timeout=%ds", req->tcUrl.c_str(), srsu2si(publish_kickoff_timeout)); + // Kick off the publisher when idle for a period of timeout. + if (source->publisher_is_idle_for(publish_kickoff_for_idle)) { + return srs_error_wrap(err, "kicked for idle, url=%s, timeout=%ds", req->tcUrl.c_str(), srsu2si(publish_kickoff_for_idle)); } pprint->elapse(); diff --git a/trunk/src/app/srs_app_source.cpp b/trunk/src/app/srs_app_source.cpp index 00e35b2ee4..302ef907e0 100755 --- a/trunk/src/app/srs_app_source.cpp +++ b/trunk/src/app/srs_app_source.cpp @@ -1877,7 +1877,7 @@ srs_error_t SrsLiveSourceManager::notify(int event, srs_utime_t interval, srs_ut // @see https://github.com/ossrs/srs/issues/714 #if 0 // When source expired, remove it. - if (source->expired()) { + if (source->stream_is_dead()) { int cid = source->source_id(); if (cid == -1 && source->pre_source_id() > 0) { cid = source->pre_source_id(); @@ -1926,8 +1926,8 @@ SrsLiveSource::SrsLiveSource() mix_queue = new SrsMixQueue(); _can_publish = true; - die_at = 0; - idle_at = 0; + stream_die_at_ = 0; + publisher_idle_at_ = 0; handler = NULL; bridge_ = NULL; @@ -1984,10 +1984,10 @@ srs_error_t SrsLiveSource::cycle() return srs_success; } -bool SrsLiveSource::expired() +bool SrsLiveSource::stream_is_dead() { // unknown state? - if (die_at == 0) { + if (stream_die_at_ == 0) { return false; } @@ -2002,20 +2002,21 @@ bool SrsLiveSource::expired() } srs_utime_t now = srs_get_system_time(); - if (now > die_at + SRS_SOURCE_CLEANUP) { + if (now > stream_die_at_ + SRS_SOURCE_CLEANUP) { return true; } return false; } -bool SrsLiveSource::idle_for(srs_utime_t timeout) +bool SrsLiveSource::publisher_is_idle_for(srs_utime_t timeout) { - if (idle_at == 0 || timeout <= 0) { + if (!publisher_idle_at_ || !timeout) { return false; } + srs_utime_t now = srs_get_system_time(); - if (now > idle_at + timeout) { + if (now > publisher_idle_at_ + timeout) { return true; } return false; @@ -2648,8 +2649,9 @@ srs_error_t SrsLiveSource::on_publish() SrsStatistic* stat = SrsStatistic::instance(); stat->on_stream_publish(req, _source_id.c_str()); + // When no players, the publisher is idle now. if (consumers.empty()) { - idle_at = srs_get_system_time(); + publisher_idle_at_ = srs_get_system_time(); } return err; @@ -2697,7 +2699,7 @@ void SrsLiveSource::on_unpublish() // no consumer, stream is die. if (consumers.empty()) { - die_at = srs_get_system_time(); + stream_die_at_ = srs_get_system_time(); } } @@ -2707,7 +2709,10 @@ srs_error_t SrsLiveSource::create_consumer(SrsLiveConsumer*& consumer) consumer = new SrsLiveConsumer(this); consumers.push_back(consumer); - idle_at = 0; + + // There should be one consumer, so reset the timeout. + stream_die_at_ = 0; + publisher_idle_at_ = 0; // for edge, when play edge stream, check the state if (_srs_config->get_vhost_is_edge(req->vhost)) { @@ -2770,11 +2775,18 @@ void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer* consumer) if (it != consumers.end()) { it = consumers.erase(it); } - + if (consumers.empty()) { play_edge->on_all_client_stop(); - die_at = srs_get_system_time(); - idle_at = srs_get_system_time(); + + // For edge server, the stream die when the last player quit, because the edge stream is created by player + // activities, so it should die when all players quit. + if (_srs_config->get_vhost_is_edge(req->vhost)) { + stream_die_at_ = srs_get_system_time(); + } + + // When no players, the publisher is idle now. + publisher_idle_at_ = srs_get_system_time(); } } diff --git a/trunk/src/app/srs_app_source.hpp b/trunk/src/app/srs_app_source.hpp index da4d2a6935..ae4d6da83d 100644 --- a/trunk/src/app/srs_app_source.hpp +++ b/trunk/src/app/srs_app_source.hpp @@ -533,20 +533,20 @@ class SrsLiveSource : public ISrsReloadHandler private: // Whether source is avaiable for publishing. bool _can_publish; - // The last die time, when all consumers quit and no publisher, - // We will remove the source when source die. - srs_utime_t die_at; - // The last idle time, when all consumers quit but at least one publisher is alive. - srs_utime_t idle_at; + // The last die time, while die means neither publishers nor players. + srs_utime_t stream_die_at_; + // The last idle time, while idle means no players. + srs_utime_t publisher_idle_at_; public: SrsLiveSource(); virtual ~SrsLiveSource(); public: virtual void dispose(); virtual srs_error_t cycle(); - // Remove source when expired. - virtual bool expired(); - bool idle_for(srs_utime_t timeout); + // Whether stream is dead, which is no publisher or player. + virtual bool stream_is_dead(); + // Whether publisher is idle for a period of timeout. + bool publisher_is_idle_for(srs_utime_t timeout); public: // Initialize the hls with handlers. virtual srs_error_t initialize(SrsRequest* r, ISrsLiveSourceHandler* h); From 4027d4a428e93afd331401796e45e791408314ba Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 6 Mar 2023 08:16:38 +0800 Subject: [PATCH 7/8] Refine code --- trunk/src/app/srs_app_config.cpp | 4 ++-- trunk/src/app/srs_app_gb28181.cpp | 2 +- trunk/src/app/srs_app_rtmp_conn.cpp | 2 +- trunk/src/kernel/srs_kernel_error.hpp | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index 5bb4cdae96..27c2000b05 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -5355,7 +5355,7 @@ srs_utime_t SrsConfig::get_publish_kickoff_for_idle(std::string vhost) srs_utime_t SrsConfig::get_publish_kickoff_for_idle(SrsConfDirective* vhost) { - SRS_OVERWRITE_BY_ENV_MILLISECONDS("srs.vhost.publish.kickoff_for_idle"); // SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE + SRS_OVERWRITE_BY_ENV_FLOAT_SECONDS("srs.vhost.publish.kickoff_for_idle"); // SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE static srs_utime_t DEFAULT = 0 * SRS_UTIME_SECONDS; @@ -5374,7 +5374,7 @@ srs_utime_t SrsConfig::get_publish_kickoff_for_idle(SrsConfDirective* vhost) return DEFAULT; } - return (srs_utime_t)(::atoi(conf->arg0().c_str()) * SRS_UTIME_MILLISECONDS); + return (srs_utime_t)(::atof(conf->arg0().c_str()) * SRS_UTIME_SECONDS); } int SrsConfig::get_global_chunk_size() diff --git a/trunk/src/app/srs_app_gb28181.cpp b/trunk/src/app/srs_app_gb28181.cpp index e652932592..71180f661d 100644 --- a/trunk/src/app/srs_app_gb28181.cpp +++ b/trunk/src/app/srs_app_gb28181.cpp @@ -255,7 +255,7 @@ srs_error_t SrsLazyGbSession::cycle() // It maybe success with message. if (srs_error_code(err) == ERROR_SUCCESS) { - srs_trace("client finished%s.", srs_error_summary(err).c_str()); + srs_trace("client finished %s.", srs_error_summary(err).c_str()); srs_freep(err); return err; } diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 3b0c4eb8f3..6411548a7f 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -1011,7 +1011,7 @@ srs_error_t SrsRtmpConn::do_publishing(SrsLiveSource* source, SrsPublishRecvThre // Kick off the publisher when idle for a period of timeout. if (source->publisher_is_idle_for(publish_kickoff_for_idle)) { - return srs_error_wrap(err, "kicked for idle, url=%s, timeout=%ds", req->tcUrl.c_str(), srsu2si(publish_kickoff_for_idle)); + return srs_error_new(ERROR_KICKOFF_FOR_IDLE, "kicked for idle, url=%s, timeout=%ds", req->tcUrl.c_str(), srsu2si(publish_kickoff_for_idle)); } pprint->elapse(); diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index f095d9533a..d338dfbbe9 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -167,6 +167,7 @@ XX(ERROR_RTMP_MESSAGE_CREATE , 2053, "MessageCreate", "Failed to create shared pointer message") \ XX(ERROR_RTMP_PROXY_EXCEED , 2054, "RtmpProxy", "Failed to decode message of RTMP proxy") \ XX(ERROR_RTMP_CREATE_STREAM_DEPTH , 2055, "RtmpIdentify", "Failed to identify RTMP client") \ + XX(ERROR_KICKOFF_FOR_IDLE , 2056, "KickoffForIdle", "Kickoff for publisher is idle") \ XX(ERROR_CONTROL_REDIRECT , 2997, "RtmpRedirect", "RTMP 302 redirection") \ XX(ERROR_CONTROL_RTMP_CLOSE , 2998, "RtmpClose", "RTMP connection is closed") \ XX(ERROR_CONTROL_REPUBLISH , 2999, "RtmpRepublish", "RTMP stream is republished") From 15296756351bb27a5f372d6121cb339082fb40b4 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 6 Mar 2023 08:24:46 +0800 Subject: [PATCH 8/8] Fix utest bug. --- trunk/src/utest/srs_utest_config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trunk/src/utest/srs_utest_config.cpp b/trunk/src/utest/srs_utest_config.cpp index cac6e6bf24..925c010d90 100644 --- a/trunk/src/utest/srs_utest_config.cpp +++ b/trunk/src/utest/srs_utest_config.cpp @@ -4463,7 +4463,7 @@ VOID TEST(ConfigEnvTest, CheckEnvValuesVhostPublish) EXPECT_FALSE(conf.try_annexb_first("__defaultVhost__")); SrsSetEnvConfig(kickoff_for_idle, "SRS_VHOST_PUBLISH_KICKOFF_FOR_IDLE", "30"); - EXPECT_EQ(30 * SRS_UTIME_MILLISECONDS, conf.get_publish_kickoff_for_idle("__defaultVhost__")); + EXPECT_EQ(30 * SRS_UTIME_SECONDS, conf.get_publish_kickoff_for_idle("__defaultVhost__")); } }