diff --git a/trunk/conf/edge.conf b/trunk/conf/edge.conf index 1dc2a3e40..5e7403320 100644 --- a/trunk/conf/edge.conf +++ b/trunk/conf/edge.conf @@ -15,6 +15,26 @@ http_server { listen 8080; dir ./objs/nginx/html; } +http_api { + enabled on; + listen 1985; +} + +# Edge does not support WebRTC, so even if enabled in config, +# it will be automatically disabled at runtime. +rtc_server { + enabled on; + listen 8000; + candidate $CANDIDATE; +} + +# Edge does not support SRT, so even if enabled in config, +# it will be automatically disabled at runtime. +srt_server { + enabled on; + listen 10080; +} + vhost __defaultVhost__ { cluster { mode remote; @@ -24,4 +44,50 @@ vhost __defaultVhost__ { enabled on; mount [vhost]/[app]/[stream].flv; } + + # Edge does not support WebRTC, so even if enabled in config, + # it will be automatically disabled at runtime. + rtc { + enabled on; + rtmp_to_rtc on; + rtc_to_rtmp on; + } + + # Edge does not support SRT, so even if enabled in config, + # it will be automatically disabled at runtime. + srt { + enabled on; + srt_to_rtmp on; + } + + # Edge does not support HDS, so even if enabled in config, + # it will be automatically disabled at runtime. + hds { + enabled on; + } + + # Edge does not support HLS, so even if enabled in config, + # it will be automatically disabled at runtime. + hls { + enabled on; + } + + # Edge does not support MPEG-DASH, so even if enabled in config, + # it will be automatically disabled at runtime. + dash { + enabled on; + } + + # Edge does not support forwarding, so even if enabled in config, + # it will be automatically disabled at runtime. + forward { + enabled on; + destination 127.0.0.1:19350; + } + + # Edge does not support DVR, so even if enabled in config, + # it will be automatically disabled at runtime. + dvr { + enabled on; + } } diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 1add26045..0f1de5108 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 7.0 Changelog +* v7.0, 2025-09-27, Merge [#4513](https://github.com/ossrs/srs/pull/4513): For Edge, only support RTMP or HTTP-FLV. v7.0.94 (#4513) * v7.0, 2025-09-21, Merge [#4505](https://github.com/ossrs/srs/pull/4505): improve blackbox test for rtsp. v7.0.93 (#4505) * v7.0, 2025-09-21, Fix WHIP with transcoding bug. v7.0.92 (#4495) * v7.0, 2025-09-20, Merge [#4504](https://github.com/ossrs/srs/pull/4504): fix rtsp compiling warning. v7.0.91 (#4504) @@ -107,7 +108,8 @@ The changelog for SRS. ## SRS 6.0 Changelog -* v6.0, 2025-09-21, Fix WHIP with transcoding bug. v6.0.179 (#4495) +* v6.0, 2025-09-27, For Edge, only support RTMP or HTTP-FLV. v6.0.179 (#4512) +* v6.0, 2025-09-21, Fix WHIP with transcoding bug. v6.0.178 (#4495) * v6.0, 2025-09-15, RTC2RTMP: Fix sequence number wraparound assertion crashes. v6.0.177 (#4491) * v6.0, 2025-09-05, RTX: Fix race condition for timer. v6.0.176 (#4470) (#4474) * v6.0, 2025-08-26, Merge [#4451](https://github.com/ossrs/srs/pull/4451): RTC: Fix null pointer crash in RTC2RTMP when start packet is missing. v6.0.175 (#4451) diff --git a/trunk/src/app/srs_app_rtc_api.cpp b/trunk/src/app/srs_app_rtc_api.cpp index eb46de341..28c0931d6 100644 --- a/trunk/src/app/srs_app_rtc_api.cpp +++ b/trunk/src/app/srs_app_rtc_api.cpp @@ -206,6 +206,13 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa // Whether enabled. bool server_enabled = _srs_config->get_rtc_server_enabled(); bool rtc_enabled = _srs_config->get_rtc_enabled(ruc->req_->vhost_); + bool edge = _srs_config->get_vhost_is_edge(ruc->req_->vhost_); + + if (rtc_enabled && edge) { + rtc_enabled = false; + srs_warn("disable WebRTC for edge vhost=%s", ruc->req_->vhost_.c_str()); + } + if (server_enabled && !rtc_enabled) { srs_warn("RTC disabled in vhost %s", ruc->req_->vhost_.c_str()); } @@ -222,7 +229,13 @@ srs_error_t SrsGoApiRtcPlay::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMessa } // For RTMP to RTC, fail if disabled and RTMP is active, see https://github.com/ossrs/srs/issues/2728 - if (!is_rtc_stream_active && !_srs_config->get_rtc_from_rtmp(ruc->req_->vhost_)) { + bool rtmp_to_rtc = _srs_config->get_rtc_from_rtmp(ruc->req_->vhost_); + if (rtmp_to_rtc && edge) { + rtmp_to_rtc = false; + srs_warn("disable RTMP to WebRTC for edge vhost=%s", ruc->req_->vhost_.c_str()); + } + + if (!is_rtc_stream_active && !rtmp_to_rtc) { SrsSharedPtr live_source = _srs_sources->fetch(ruc->req_); if (live_source.get() && !live_source->inactive()) { return srs_error_new(ERROR_RTC_DISABLED, "Disabled rtmp_to_rtc of %s, see #2728", ruc->req_->vhost_.c_str()); @@ -494,6 +507,13 @@ srs_error_t SrsGoApiRtcPublish::serve_http(ISrsHttpResponseWriter *w, ISrsHttpMe // Whether enabled. bool server_enabled = _srs_config->get_rtc_server_enabled(); bool rtc_enabled = _srs_config->get_rtc_enabled(ruc->req_->vhost_); + bool edge = _srs_config->get_vhost_is_edge(ruc->req_->vhost_); + + if (rtc_enabled && edge) { + rtc_enabled = false; + srs_warn("disable WebRTC for edge vhost=%s", ruc->req_->vhost_.c_str()); + } + if (server_enabled && !rtc_enabled) { srs_warn("RTC disabled in vhost %s", ruc->req_->vhost_.c_str()); } diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 06ee140c5..7c45f808f 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1280,6 +1280,13 @@ srs_error_t SrsRtcPublishStream::initialize(ISrsRequest *r, SrsRtcSourceDescript // Bridge to RTMP. // TODO: Support bridge to RTSP. bool rtc_to_rtmp = config_->get_rtc_to_rtmp(req_->vhost_); + bool edge = _srs_config->get_vhost_is_edge(req_->vhost_); + + if (rtc_to_rtmp && edge) { + rtc_to_rtmp = false; + srs_warn("disable WebRTC to RTMP for edge vhost=%s", req_->vhost_.c_str()); + } + if (rtc_to_rtmp) { // Disable GOP cache for RTC2RTMP bridge, to keep the streams in sync, // especially for stream merging. diff --git a/trunk/src/app/srs_app_rtmp_conn.cpp b/trunk/src/app/srs_app_rtmp_conn.cpp index 1b7179809..76fb44104 100644 --- a/trunk/src/app/srs_app_rtmp_conn.cpp +++ b/trunk/src/app/srs_app_rtmp_conn.cpp @@ -1021,6 +1021,13 @@ srs_error_t SrsRtmpConn::acquire_publish(SrsSharedPtr source) SrsSharedPtr rtc; bool rtc_server_enabled = _srs_config->get_rtc_server_enabled(); bool rtc_enabled = _srs_config->get_rtc_enabled(req->vhost_); + bool edge = _srs_config->get_vhost_is_edge(req->vhost_); + + if (rtc_enabled && edge) { + rtc_enabled = false; + srs_warn("disable WebRTC for edge vhost=%s", req->vhost_.c_str()); + } + if (rtc_server_enabled && rtc_enabled && !info_->edge_) { if ((err = _srs_rtc_sources->fetch_or_create(req, rtc)) != srs_success) { return srs_error_wrap(err, "create source"); @@ -1062,7 +1069,13 @@ srs_error_t SrsRtmpConn::acquire_publish(SrsSharedPtr source) SrsRtmpBridge *bridge = new SrsRtmpBridge(); #if defined(SRS_FFMPEG_FIT) - if (rtc.get() && _srs_config->get_rtc_from_rtmp(req->vhost_)) { + bool rtmp_to_rtc = _srs_config->get_rtc_from_rtmp(req->vhost_); + if (rtmp_to_rtc && edge) { + rtmp_to_rtc = false; + srs_warn("disable RTMP to WebRTC for edge vhost=%s", req->vhost_.c_str()); + } + + if (rtc.get() && rtmp_to_rtc) { bridge->enable_rtmp2rtc(rtc); } #endif diff --git a/trunk/src/app/srs_app_rtmp_source.cpp b/trunk/src/app/srs_app_rtmp_source.cpp index 3ca219e6b..b8f8e142a 100644 --- a/trunk/src/app/srs_app_rtmp_source.cpp +++ b/trunk/src/app/srs_app_rtmp_source.cpp @@ -1719,7 +1719,7 @@ SrsLiveSource::SrsLiveSource() play_edge_ = new SrsPlayEdge(); publish_edge_ = new SrsPublishEdge(); gop_cache_ = new SrsGopCache(); - hub_ = new SrsOriginHub(); + hub_ = NULL; meta_ = new SrsMetaCache(); format_ = new SrsRtmpFormat(); @@ -1758,15 +1758,18 @@ SrsLiveSource::~SrsLiveSource() void SrsLiveSource::dispose() { - hub_->dispose(); + if (hub_) { + hub_->dispose(); + } meta_->dispose(); gop_cache_->dispose(); } srs_error_t SrsLiveSource::cycle() { - srs_error_t err = hub_->cycle(); - if (err != srs_success) { + srs_error_t err = srs_success; + + if (hub_ && (err = hub_->cycle()) != srs_success) { return srs_error_wrap(err, "hub cycle"); } @@ -1792,7 +1795,7 @@ bool SrsLiveSource::stream_is_dead() } // Origin hub delay cleanup. - if (now < stream_die_at_ + hub_->cleanup_delay()) { + if (hub_ && now < stream_die_at_ + hub_->cleanup_delay()) { return false; } @@ -1853,7 +1856,16 @@ srs_error_t SrsLiveSource::initialize(SrsSharedPtr wrapper, ISrsR srs_utime_t queue_size = _srs_config->get_queue_length(req_->vhost_); publish_edge_->set_queue_size(queue_size); - if ((err = hub_->initialize(wrapper, req_)) != srs_success) { + // Create and initialize origin hub only for origin servers, not edge servers + bool edge = _srs_config->get_vhost_is_edge(req_->vhost_); + if (!edge) { + srs_freep(hub_); + hub_ = new SrsOriginHub(); + } else { + srs_warn("disable OriginHub creation for edge vhost=%s", req_->vhost_.c_str()); + } + + if (hub_ && (err = hub_->initialize(wrapper, req_)) != srs_success) { return srs_error_wrap(err, "hub"); } @@ -1967,7 +1979,11 @@ srs_error_t SrsLiveSource::on_meta_data(SrsRtmpCommonMessage *msg, SrsOnMetaData } // Copy to hub to all utilities. - return hub_->on_meta_data(meta_->data(), metadata); + if (hub_ && (err = hub_->on_meta_data(meta_->data(), metadata)) != srs_success) { + return srs_error_wrap(err, "hub consume metadata"); + } + + return err; } srs_error_t SrsLiveSource::on_audio(SrsRtmpCommonMessage *shared_audio) @@ -2052,7 +2068,7 @@ srs_error_t SrsLiveSource::on_audio_imp(SrsMediaPacket *msg) } // Copy to hub to all utilities. - if ((err = hub_->on_audio(msg)) != srs_success) { + if (hub_ && (err = hub_->on_audio(msg)) != srs_success) { return srs_error_wrap(err, "consume audio"); } @@ -2173,7 +2189,7 @@ srs_error_t SrsLiveSource::on_video_imp(SrsMediaPacket *msg) } // Copy to hub to all utilities. - if ((err = hub_->on_video(msg, is_sequence_header)) != srs_success) { + if (hub_ && (err = hub_->on_video(msg, is_sequence_header)) != srs_success) { return srs_error_wrap(err, "hub consume video"); } @@ -2329,7 +2345,7 @@ srs_error_t SrsLiveSource::on_publish() last_packet_time_ = 0; // Notify the hub about the publish event. - if ((err = hub_->on_publish()) != srs_success) { + if (hub_ && (err = hub_->on_publish()) != srs_success) { return srs_error_wrap(err, "hub publish"); } @@ -2363,7 +2379,9 @@ void SrsLiveSource::on_unpublish() } // Notify the hub about the unpublish event. - hub_->on_unpublish(); + if (hub_) { + hub_->on_unpublish(); + } // only clear the gop cache, // donot clear the sequence header, for it maybe not changed, @@ -2450,7 +2468,8 @@ srs_error_t SrsLiveSource::consumer_dumps(SrsLiveConsumer *consumer, bool ds, bo } // If stream is publishing, dumps the sequence header and gop cache. - if (hub_->active()) { + bool hub_active = hub_ ? hub_->active() : false; + if (hub_active) { // Copy metadata and sequence header to consumer. if ((err = meta_->dumps(consumer, atc_, jitter_algorithm_, dm, ds)) != srs_success) { return srs_error_wrap(err, "meta dumps"); @@ -2464,9 +2483,9 @@ srs_error_t SrsLiveSource::consumer_dumps(SrsLiveConsumer *consumer, bool ds, bo // print status. if (dg) { - srs_trace("create consumer, active=%d, queue_size=%dms, jitter=%d", hub_->active(), srsu2msi(queue_size), jitter_algorithm_); + srs_trace("create consumer, active=%d, queue_size=%dms, jitter=%d", hub_active, srsu2msi(queue_size), jitter_algorithm_); } else { - srs_trace("create consumer, active=%d, ignore gop cache, jitter=%d", hub_->active(), jitter_algorithm_); + srs_trace("create consumer, active=%d, ignore gop cache, jitter=%d", hub_active, jitter_algorithm_); } return err; diff --git a/trunk/src/app/srs_app_srt_conn.cpp b/trunk/src/app/srs_app_srt_conn.cpp index 6d9f68a02..58e345612 100644 --- a/trunk/src/app/srs_app_srt_conn.cpp +++ b/trunk/src/app/srs_app_srt_conn.cpp @@ -278,7 +278,15 @@ srs_error_t SrsMpegtsSrtConn::do_cycle() req_->vhost_ = parsed_vhost->arg0(); } - if (!_srs_config->get_srt_enabled(req_->vhost_)) { + bool srt_enabled = _srs_config->get_srt_enabled(req_->vhost_); + bool edge = _srs_config->get_vhost_is_edge(req_->vhost_); + + if (srt_enabled && edge) { + srt_enabled = false; + srs_warn("disable SRT for edge vhost=%s", req_->vhost_.c_str()); + } + + if (!srt_enabled) { return srs_error_new(ERROR_SRT_CONN, "srt disabled, vhost=%s", req_->vhost_.c_str()); } @@ -403,7 +411,13 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish() bool rtc_server_enabled = _srs_config->get_rtc_server_enabled(); bool rtc_enabled = _srs_config->get_rtc_enabled(req_->vhost_); bool edge = _srs_config->get_vhost_is_edge(req_->vhost_); - if (rtc_server_enabled && rtc_enabled && !edge) { + + if (rtc_enabled && edge) { + rtc_enabled = false; + srs_warn("disable WebRTC for edge vhost=%s", req_->vhost_.c_str()); + } + + if (rtc_server_enabled && rtc_enabled) { if ((err = _srs_rtc_sources->fetch_or_create(req_, rtc)) != srs_success) { return srs_error_wrap(err, "create source"); } @@ -416,11 +430,23 @@ srs_error_t SrsMpegtsSrtConn::acquire_publish() // Bridge to RTMP and RTC streaming. SrsSrtBridge *bridge = new SrsSrtBridge(); - if (_srs_config->get_srt_to_rtmp(req_->vhost_)) { + bool srt_to_rtmp = _srs_config->get_srt_to_rtmp(req_->vhost_); + if (srt_to_rtmp && edge) { + srt_to_rtmp = false; + srs_warn("disable SRT to RTMP for edge vhost=%s", req_->vhost_.c_str()); + } + + if (srt_to_rtmp) { bridge->enable_srt2rtmp(live_source); } - if (rtc.get() && _srs_config->get_rtc_from_rtmp(req_->vhost_)) { + bool rtmp_to_rtc = _srs_config->get_rtc_from_rtmp(req_->vhost_); + if (rtmp_to_rtc && edge) { + rtmp_to_rtc = false; + srs_warn("disable RTMP to WebRTC for edge vhost=%s", req_->vhost_.c_str()); + } + + if (rtc.get() && rtmp_to_rtc) { bridge->enable_srt2rtc(rtc); } diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 5e0b34ce7..cab4a8651 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 93 +#define VERSION_REVISION 94 #endif \ No newline at end of file diff --git a/trunk/src/utest/srs_utest_app7.cpp b/trunk/src/utest/srs_utest_app7.cpp index 98d0fddbb..1654cf96f 100644 --- a/trunk/src/utest/srs_utest_app7.cpp +++ b/trunk/src/utest/srs_utest_app7.cpp @@ -516,7 +516,7 @@ VOID TEST(SrsRtcPublishStreamTest, UpdateRttTypicalScenario) // Test typical RTT update scenario for audio track uint32_t test_ssrc = 0x87654321; // Matches audio track SSRC - int test_rtt = 50; // 50ms RTT + int test_rtt = 50; // 50ms RTT // Call update_rtt - should find audio track and update its RTT publish_stream->update_rtt(test_ssrc, test_rtt);