Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kickoff publisher when stream is idle, which means no players. v6.0.31, v5.0.144 #3105

Merged
merged 9 commits into from
Mar 6, 2023
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/trunk/objs
46 changes: 46 additions & 0 deletions trunk/Dockerfile.dist
Original file line number Diff line number Diff line change
@@ -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"]
4 changes: 4 additions & 0 deletions trunk/conf/docker.conf
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
14 changes: 14 additions & 0 deletions trunk/conf/rtmp.kickoff.conf
Original file line number Diff line number Diff line change
@@ -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;
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved
}
}
53 changes: 53 additions & 0 deletions trunk/src/app/srs_app_config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
Expand Down Expand Up @@ -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)
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved
{
// the timeout to kickoff publish as no one watching,
// the default value is 3 minutes.
static srs_utime_t DEFAULT = 180 * SRS_UTIME_SECONDS;
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved

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");
Expand Down
6 changes: 6 additions & 0 deletions trunk/src/app/srs_app_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
13 changes: 13 additions & 0 deletions trunk/src/app/srs_app_rtmp_conn.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
winlinvip marked this conversation as resolved.
Show resolved Hide resolved
#endif

// set the sock options.
set_sock_options();
Expand All @@ -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))
{
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved
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.");
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved
}
#endif

pprint->elapse();

// cond wait for timeout.
Expand Down
31 changes: 30 additions & 1 deletion trunk/src/app/srs_app_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved
{
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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
industriousonesoft marked this conversation as resolved.
Show resolved Hide resolved
#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.
Expand Down Expand Up @@ -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
}
}

Expand Down
7 changes: 7 additions & 0 deletions trunk/src/app/srs_app_source.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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);
Expand Down
5 changes: 5 additions & 0 deletions trunk/src/core/srs_core_performance.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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