From 66a0143f14459947f3389670e55cfa7a3cb90419 Mon Sep 17 00:00:00 2001 From: winlin Date: Mon, 17 Aug 2020 18:15:34 +0800 Subject: [PATCH] RTC: Refine source state to created and delivering --- trunk/src/app/srs_app_rtc_conn.cpp | 13 ++++++++++--- trunk/src/app/srs_app_rtc_server.cpp | 1 - trunk/src/app/srs_app_rtc_source.cpp | 25 +++++++++++++++++++------ trunk/src/app/srs_app_rtc_source.hpp | 9 +++++++-- trunk/src/kernel/srs_kernel_error.hpp | 13 ++++++------- 5 files changed, 42 insertions(+), 19 deletions(-) diff --git a/trunk/src/app/srs_app_rtc_conn.cpp b/trunk/src/app/srs_app_rtc_conn.cpp index 0b4eab0a8..e976f8018 100644 --- a/trunk/src/app/srs_app_rtc_conn.cpp +++ b/trunk/src/app/srs_app_rtc_conn.cpp @@ -1538,6 +1538,7 @@ srs_error_t SrsRtcConnection::add_publisher(SrsRequest* req, const SrsSdp& remot SrsRtcStreamDescription* stream_desc = new SrsRtcStreamDescription(); SrsAutoFree(SrsRtcStreamDescription, stream_desc); + if ((err = negotiate_publish_capability(req, remote_sdp, stream_desc)) != srs_success) { return srs_error_wrap(err, "publish negotiate"); } @@ -1551,8 +1552,16 @@ srs_error_t SrsRtcConnection::add_publisher(SrsRequest* req, const SrsSdp& remot return srs_error_wrap(err, "create source"); } + // When SDP is done, we set the stream to create state, to prevent multiple publisher. + if (!source->can_publish()) { + return srs_error_new(ERROR_RTC_SOURCE_BUSY, "stream %s busy", req->get_stream_url().c_str()); + } + source->set_stream_created(); + + // Apply the SDP to source. source->set_stream_desc(stream_desc->copy()); + // TODO: FIXME: What happends when error? if ((err = create_publisher(req, stream_desc)) != srs_success) { return srs_error_wrap(err, "create publish"); } @@ -3060,9 +3069,7 @@ srs_error_t SrsRtcConnection::create_publisher(SrsRequest* req, SrsRtcStreamDesc { srs_error_t err = srs_success; - if (!stream_desc) { - return srs_error_new(ERROR_RTC_STREAM_DESC, "rtc publisher init"); - } + srs_assert(stream_desc); // Ignore if exists. if(publishers_.end() != publishers_.find(req->get_stream_url())) { diff --git a/trunk/src/app/srs_app_rtc_server.cpp b/trunk/src/app/srs_app_rtc_server.cpp index f97f7b15f..393ee709e 100644 --- a/trunk/src/app/srs_app_rtc_server.cpp +++ b/trunk/src/app/srs_app_rtc_server.cpp @@ -417,7 +417,6 @@ srs_error_t SrsRtcServer::create_session( return srs_error_wrap(err, "create source"); } - // TODO: FIXME: Refine the API for stream status manage. if (publish && !source->can_publish()) { return srs_error_new(ERROR_RTC_SOURCE_BUSY, "stream %s busy", req->get_stream_url().c_str()); } diff --git a/trunk/src/app/srs_app_rtc_source.cpp b/trunk/src/app/srs_app_rtc_source.cpp index 4340961b8..8b9b8e1b8 100644 --- a/trunk/src/app/srs_app_rtc_source.cpp +++ b/trunk/src/app/srs_app_rtc_source.cpp @@ -290,7 +290,9 @@ ISrsRtcPublishStream::~ISrsRtcPublishStream() SrsRtcStream::SrsRtcStream() { - _can_publish = true; + is_created_ = false; + is_delivering_packets_ = false; + publish_stream_ = NULL; stream_desc_ = NULL; @@ -408,7 +410,13 @@ void SrsRtcStream::on_consumer_destroy(SrsRtcConsumer* consumer) bool SrsRtcStream::can_publish() { - return _can_publish; + return !is_created_; +} + +void SrsRtcStream::set_stream_created() +{ + srs_assert(!is_created_ && !is_delivering_packets_); + is_created_ = true; } srs_error_t SrsRtcStream::on_publish() @@ -418,7 +426,10 @@ srs_error_t SrsRtcStream::on_publish() // update the request object. srs_assert(req); - _can_publish = false; + // For RTC, DTLS is done, and we are ready to deliver packets. + // @note For compatible with RTMP, we also set the is_created_, it MUST be created here. + is_created_ = true; + is_delivering_packets_ = true; // whatever, the publish thread is the source or edge source, // save its id to srouce id. @@ -434,13 +445,15 @@ srs_error_t SrsRtcStream::on_publish() void SrsRtcStream::on_unpublish() { // ignore when already unpublished. - if (_can_publish) { + if (!is_created_) { return; } - srs_trace("cleanup when unpublish"); + srs_trace("cleanup when unpublish, created=%u, deliver=%u", is_created_, is_delivering_packets_); + + is_created_ = false; + is_delivering_packets_ = false; - _can_publish = true; _source_id = SrsContextId(); // TODO: FIXME: Handle by statistic. diff --git a/trunk/src/app/srs_app_rtc_source.hpp b/trunk/src/app/srs_app_rtc_source.hpp index a36c1b344..005a875a4 100644 --- a/trunk/src/app/srs_app_rtc_source.hpp +++ b/trunk/src/app/srs_app_rtc_source.hpp @@ -152,8 +152,10 @@ private: private: // To delivery stream to clients. std::vector consumers; - // Whether source is avaiable for publishing. - bool _can_publish; + // Whether stream is created, that is, SDP is done. + bool is_created_; + // Whether stream is delivering data, that is, DTLS is done. + bool is_delivering_packets_; public: SrsRtcStream(); virtual ~SrsRtcStream(); @@ -179,7 +181,10 @@ public: virtual srs_error_t consumer_dumps(SrsRtcConsumer* consumer, bool ds = true, bool dm = true, bool dg = true); virtual void on_consumer_destroy(SrsRtcConsumer* consumer); // Whether we can publish stream to the source, return false if it exists. + // @remark Note that when SDP is done, we set the stream is not able to publish. virtual bool can_publish(); + // For RTC, the stream is created when SDP is done, and then do DTLS + virtual void set_stream_created(); // When start publish stream. virtual srs_error_t on_publish(); // When stop publish stream. diff --git a/trunk/src/kernel/srs_kernel_error.hpp b/trunk/src/kernel/srs_kernel_error.hpp index fb3a7f2b7..80a43cf68 100644 --- a/trunk/src/kernel/srs_kernel_error.hpp +++ b/trunk/src/kernel/srs_kernel_error.hpp @@ -354,13 +354,12 @@ #define ERROR_RTC_INVALID_PARAMS 5023 #define ERROR_RTC_DUMMY_BRIDGER 5024 #define ERROR_RTC_STREM_STARTED 5025 -#define ERROR_RTC_STREAM_DESC 5026 -#define ERROR_RTC_TRACK_CODEC 5027 -#define ERROR_RTC_NO_PLAYER 5028 -#define ERROR_RTC_NO_PUBLISHER 5029 -#define ERROR_RTC_DUPLICATED_SSRC 5030 -#define ERROR_RTC_NO_TRACK 5031 -#define ERROR_RTC_RTCP_EMPTY_RR 5032 +#define ERROR_RTC_TRACK_CODEC 5026 +#define ERROR_RTC_NO_PLAYER 5027 +#define ERROR_RTC_NO_PUBLISHER 5028 +#define ERROR_RTC_DUPLICATED_SSRC 5029 +#define ERROR_RTC_NO_TRACK 5030 +#define ERROR_RTC_RTCP_EMPTY_RR 5031 /////////////////////////////////////////////////////// // GB28181 API error.