diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 1edbd24502..4796de3e2d 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -377,6 +377,7 @@ rtc_source_set("media_session") { "../rtc_base:checks", "../rtc_base:logging", "../rtc_base:stringutils", + "../rtc_base/memory:always_valid_pointer", "../rtc_base/third_party/base64", ] absl_deps = [ diff --git a/pc/channel_manager.cc b/pc/channel_manager.cc index e13db54806..9ee2bca4d0 100644 --- a/pc/channel_manager.cc +++ b/pc/channel_manager.cc @@ -31,6 +31,7 @@ std::unique_ptr ChannelManager::Create( bool enable_rtx, rtc::Thread* worker_thread, rtc::Thread* network_thread) { + RTC_CHECK(media_engine); RTC_DCHECK(network_thread); RTC_DCHECK(worker_thread); @@ -51,12 +52,11 @@ ChannelManager::ChannelManager( RTC_DCHECK_RUN_ON(signaling_thread_); RTC_DCHECK(worker_thread_); RTC_DCHECK(network_thread_); + RTC_CHECK(media_engine_); - if (media_engine_) { - // TODO(tommi): Change VoiceEngine to do ctor time initialization so that - // this isn't necessary. - worker_thread_->Invoke(RTC_FROM_HERE, [&] { media_engine_->Init(); }); - } + // TODO(tommi): Change VoiceEngine to do ctor time initialization so that + // this isn't necessary. + worker_thread_->Invoke(RTC_FROM_HERE, [&] { media_engine_->Init(); }); } ChannelManager::~ChannelManager() { @@ -71,27 +71,8 @@ ChannelManager::~ChannelManager() { }); } -void ChannelManager::GetSupportedAudioSendCodecs( - std::vector* codecs) const { - if (!media_engine_) { - return; - } - *codecs = media_engine_->voice().send_codecs(); -} - -void ChannelManager::GetSupportedAudioReceiveCodecs( - std::vector* codecs) const { - if (!media_engine_) { - return; - } - *codecs = media_engine_->voice().recv_codecs(); -} - void ChannelManager::GetSupportedVideoSendCodecs( std::vector* codecs) const { - if (!media_engine_) { - return; - } codecs->clear(); std::vector video_codecs = media_engine_->video().send_codecs(); @@ -106,9 +87,6 @@ void ChannelManager::GetSupportedVideoSendCodecs( void ChannelManager::GetSupportedVideoReceiveCodecs( std::vector* codecs) const { - if (!media_engine_) { - return; - } codecs->clear(); std::vector video_codecs = media_engine_->video().recv_codecs(); @@ -123,32 +101,14 @@ void ChannelManager::GetSupportedVideoReceiveCodecs( RtpHeaderExtensions ChannelManager::GetDefaultEnabledAudioRtpHeaderExtensions() const { - if (!media_engine_) - return {}; return GetDefaultEnabledRtpHeaderExtensions(media_engine_->voice()); } -std::vector -ChannelManager::GetSupportedAudioRtpHeaderExtensions() const { - if (!media_engine_) - return {}; - return media_engine_->voice().GetRtpHeaderExtensions(); -} - RtpHeaderExtensions ChannelManager::GetDefaultEnabledVideoRtpHeaderExtensions() const { - if (!media_engine_) - return {}; return GetDefaultEnabledRtpHeaderExtensions(media_engine_->video()); } -std::vector -ChannelManager::GetSupportedVideoRtpHeaderExtensions() const { - if (!media_engine_) - return {}; - return media_engine_->video().GetRtpHeaderExtensions(); -} - std::unique_ptr ChannelManager::CreateVoiceChannel( webrtc::Call* call, const MediaConfig& media_config, diff --git a/pc/channel_manager.h b/pc/channel_manager.h index 8d1ec28001..23adac3b5c 100644 --- a/pc/channel_manager.h +++ b/pc/channel_manager.h @@ -47,7 +47,7 @@ namespace cricket { class ChannelManager : public ChannelFactoryInterface { public: // Returns an initialized instance of ChannelManager. - // If media_engine is non-nullptr, then the returned ChannelManager instance + // `media_engine` cannot be null. The returned ChannelManager instance // will own that reference and media engine initialization static std::unique_ptr Create( std::unique_ptr media_engine, @@ -63,18 +63,11 @@ class ChannelManager : public ChannelFactoryInterface { MediaEngineInterface* media_engine() { return media_engine_.get(); } rtc::UniqueRandomIdGenerator& ssrc_generator() { return ssrc_generator_; } - // Retrieves the list of supported audio & video codec types. - // Can be called before starting the media engine. - void GetSupportedAudioSendCodecs(std::vector* codecs) const; - void GetSupportedAudioReceiveCodecs(std::vector* codecs) const; + // Retrieves the list of supported video codec types. void GetSupportedVideoSendCodecs(std::vector* codecs) const; void GetSupportedVideoReceiveCodecs(std::vector* codecs) const; RtpHeaderExtensions GetDefaultEnabledAudioRtpHeaderExtensions() const; - std::vector - GetSupportedAudioRtpHeaderExtensions() const; RtpHeaderExtensions GetDefaultEnabledVideoRtpHeaderExtensions() const; - std::vector - GetSupportedVideoRtpHeaderExtensions() const; // The operations below all occur on the worker thread. // The caller is responsible for ensuring that destruction happens @@ -123,7 +116,7 @@ class ChannelManager : public ChannelFactoryInterface { void DestroyVideoChannel(VideoChannel* video_channel); private: - const std::unique_ptr media_engine_; // Nullable. + const std::unique_ptr media_engine_; rtc::Thread* const signaling_thread_; rtc::Thread* const worker_thread_; rtc::Thread* const network_thread_; diff --git a/pc/connection_context.cc b/pc/connection_context.cc index 818283d636..e2e066665c 100644 --- a/pc/connection_context.cc +++ b/pc/connection_context.cc @@ -144,9 +144,11 @@ ConnectionContext::ConnectionContext( default_socket_factory_ = std::make_unique(socket_factory); - channel_manager_ = cricket::ChannelManager::Create( - std::move(dependencies->media_engine), - /*enable_rtx=*/true, worker_thread(), network_thread()); + if (dependencies->media_engine) { + channel_manager_ = cricket::ChannelManager::Create( + std::move(dependencies->media_engine), + /*enable_rtx=*/true, worker_thread(), network_thread()); + } // Set warning levels on the threads, to give warnings when response // may be slower than is expected of the thread. diff --git a/pc/media_session.cc b/pc/media_session.cc index 71a6d0a19c..91a0b88dd0 100644 --- a/pc/media_session.cc +++ b/pc/media_session.cc @@ -1557,21 +1557,22 @@ MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( const TransportDescriptionFactory* transport_desc_factory, rtc::UniqueRandomIdGenerator* ssrc_generator) : ssrc_generator_(ssrc_generator), - transport_desc_factory_(transport_desc_factory) { - RTC_DCHECK(ssrc_generator_); -} + transport_desc_factory_(transport_desc_factory) {} MediaSessionDescriptionFactory::MediaSessionDescriptionFactory( ChannelManager* channel_manager, const TransportDescriptionFactory* transport_desc_factory) - : MediaSessionDescriptionFactory(transport_desc_factory, - &channel_manager->ssrc_generator()) { - channel_manager->GetSupportedAudioSendCodecs(&audio_send_codecs_); - channel_manager->GetSupportedAudioReceiveCodecs(&audio_recv_codecs_); - channel_manager->GetSupportedVideoSendCodecs(&video_send_codecs_); - channel_manager->GetSupportedVideoReceiveCodecs(&video_recv_codecs_); - ComputeAudioCodecsIntersectionAndUnion(); - ComputeVideoCodecsIntersectionAndUnion(); + : MediaSessionDescriptionFactory( + transport_desc_factory, + channel_manager ? &channel_manager->ssrc_generator() : nullptr) { + if (channel_manager) { + audio_send_codecs_ = channel_manager->media_engine()->voice().send_codecs(); + audio_recv_codecs_ = channel_manager->media_engine()->voice().recv_codecs(); + channel_manager->GetSupportedVideoSendCodecs(&video_send_codecs_); + channel_manager->GetSupportedVideoReceiveCodecs(&video_recv_codecs_); + ComputeAudioCodecsIntersectionAndUnion(); + ComputeVideoCodecsIntersectionAndUnion(); + } } const AudioCodecs& MediaSessionDescriptionFactory::audio_sendrecv_codecs() @@ -2354,7 +2355,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForOffer( if (!CreateMediaContentOffer( media_description_options, session_options, filtered_codecs, sdes_policy, GetCryptos(current_content), crypto_suites, - audio_rtp_extensions, ssrc_generator_, current_streams, audio.get(), + audio_rtp_extensions, ssrc_generator(), current_streams, audio.get(), transport_desc_factory_->trials())) { return false; } @@ -2466,7 +2467,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForOffer( if (!CreateMediaContentOffer( media_description_options, session_options, filtered_codecs, sdes_policy, GetCryptos(current_content), crypto_suites, - video_rtp_extensions, ssrc_generator_, current_streams, video.get(), + video_rtp_extensions, ssrc_generator(), current_streams, video.get(), transport_desc_factory_->trials())) { return false; } @@ -2519,8 +2520,8 @@ bool MediaSessionDescriptionFactory::AddDataContentForOffer( if (!CreateContentOffer(media_description_options, session_options, sdes_policy, GetCryptos(current_content), - crypto_suites, RtpHeaderExtensions(), ssrc_generator_, - current_streams, data.get())) { + crypto_suites, RtpHeaderExtensions(), + ssrc_generator(), current_streams, data.get())) { return false; } @@ -2654,7 +2655,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( audio_transport->secure() ? cricket::SEC_DISABLED : secure(); if (!SetCodecsInAnswer(offer_audio_description, filtered_codecs, media_description_options, session_options, - ssrc_generator_, current_streams, audio_answer.get(), + ssrc_generator(), current_streams, audio_answer.get(), transport_desc_factory_->trials())) { return false; } @@ -2662,7 +2663,7 @@ bool MediaSessionDescriptionFactory::AddAudioContentForAnswer( offer_audio_description, media_description_options, session_options, sdes_policy, GetCryptos(current_content), filtered_rtp_header_extensions(default_audio_rtp_header_extensions), - ssrc_generator_, enable_encrypted_rtp_header_extensions_, + ssrc_generator(), enable_encrypted_rtp_header_extensions_, current_streams, bundle_enabled, audio_answer.get())) { return false; // Fails the session setup. } @@ -2783,7 +2784,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( video_transport->secure() ? cricket::SEC_DISABLED : secure(); if (!SetCodecsInAnswer(offer_video_description, filtered_codecs, media_description_options, session_options, - ssrc_generator_, current_streams, video_answer.get(), + ssrc_generator(), current_streams, video_answer.get(), transport_desc_factory_->trials())) { return false; } @@ -2791,7 +2792,7 @@ bool MediaSessionDescriptionFactory::AddVideoContentForAnswer( offer_video_description, media_description_options, session_options, sdes_policy, GetCryptos(current_content), filtered_rtp_header_extensions(default_video_rtp_header_extensions), - ssrc_generator_, enable_encrypted_rtp_header_extensions_, + ssrc_generator(), enable_encrypted_rtp_header_extensions_, current_streams, bundle_enabled, video_answer.get())) { return false; // Failed the sessin setup. } @@ -2864,7 +2865,7 @@ bool MediaSessionDescriptionFactory::AddDataContentForAnswer( if (!CreateMediaContentAnswer( offer_data_description, media_description_options, session_options, sdes_policy, GetCryptos(current_content), RtpHeaderExtensions(), - ssrc_generator_, enable_encrypted_rtp_header_extensions_, + ssrc_generator(), enable_encrypted_rtp_header_extensions_, current_streams, bundle_enabled, data_answer.get())) { return false; // Fails the session setup. } diff --git a/pc/media_session.h b/pc/media_session.h index 9a67ad1e3c..8f97538e77 100644 --- a/pc/media_session.h +++ b/pc/media_session.h @@ -34,6 +34,7 @@ #include "pc/media_protocol_names.h" #include "pc/session_description.h" #include "pc/simulcast_description.h" +#include "rtc_base/memory/always_valid_pointer.h" #include "rtc_base/unique_id_generator.h" namespace webrtc { @@ -328,6 +329,10 @@ class MediaSessionDescriptionFactory { void ComputeVideoCodecsIntersectionAndUnion(); + rtc::UniqueRandomIdGenerator* ssrc_generator() const { + return ssrc_generator_.get(); + } + bool is_unified_plan_ = false; AudioCodecs audio_send_codecs_; AudioCodecs audio_recv_codecs_; @@ -341,8 +346,9 @@ class MediaSessionDescriptionFactory { VideoCodecs video_sendrecv_codecs_; // Union of send and recv. VideoCodecs all_video_codecs_; - // This object is not owned by the channel so it must outlive it. - rtc::UniqueRandomIdGenerator* const ssrc_generator_; + // This object may or may not be owned by this class. + webrtc::AlwaysValidPointer const + ssrc_generator_; bool enable_encrypted_rtp_header_extensions_ = false; // TODO(zhihuang): Rename secure_ to sdec_policy_; rename the related getter // and setter. diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index f914fc8365..c139d0ad9d 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -646,25 +646,27 @@ RTCError PeerConnection::Initialize( sdp_handler_ = SdpOfferAnswerHandler::Create(this, configuration, dependencies, context_.get()); - rtp_manager_ = std::make_unique( - IsUnifiedPlan(), signaling_thread(), worker_thread(), channel_manager(), - &usage_pattern_, observer_, stats_.get(), [this]() { - RTC_DCHECK_RUN_ON(signaling_thread()); - sdp_handler_->UpdateNegotiationNeeded(); - }); + if (ConfiguredForMedia()) { + rtp_manager_ = std::make_unique( + IsUnifiedPlan(), signaling_thread(), worker_thread(), channel_manager(), + &usage_pattern_, observer_, stats_.get(), [this]() { + RTC_DCHECK_RUN_ON(signaling_thread()); + sdp_handler_->UpdateNegotiationNeeded(); + }); - // Add default audio/video transceivers for Plan B SDP. - if (!IsUnifiedPlan()) { - rtp_manager()->transceivers()->Add( - RtpTransceiverProxyWithInternal::Create( - signaling_thread(), - rtc::make_ref_counted(cricket::MEDIA_TYPE_AUDIO, - channel_manager()))); - rtp_manager()->transceivers()->Add( - RtpTransceiverProxyWithInternal::Create( - signaling_thread(), - rtc::make_ref_counted(cricket::MEDIA_TYPE_VIDEO, - channel_manager()))); + // Add default audio/video transceivers for Plan B SDP. + if (!IsUnifiedPlan()) { + rtp_manager()->transceivers()->Add( + RtpTransceiverProxyWithInternal::Create( + signaling_thread(), + rtc::make_ref_counted(cricket::MEDIA_TYPE_AUDIO, + channel_manager()))); + rtp_manager()->transceivers()->Add( + RtpTransceiverProxyWithInternal::Create( + signaling_thread(), + rtc::make_ref_counted(cricket::MEDIA_TYPE_VIDEO, + channel_manager()))); + } } int delay_ms = configuration.report_usage_pattern_delay_ms @@ -1178,8 +1180,10 @@ std::vector> PeerConnection::GetSenders() const { RTC_DCHECK_RUN_ON(signaling_thread()); std::vector> ret; - for (const auto& sender : rtp_manager()->GetSendersInternal()) { - ret.push_back(sender); + if (ConfiguredForMedia()) { + for (const auto& sender : rtp_manager()->GetSendersInternal()) { + ret.push_back(sender); + } } return ret; } @@ -1188,8 +1192,10 @@ std::vector> PeerConnection::GetReceivers() const { RTC_DCHECK_RUN_ON(signaling_thread()); std::vector> ret; - for (const auto& receiver : rtp_manager()->GetReceiversInternal()) { - ret.push_back(receiver); + if (ConfiguredForMedia()) { + for (const auto& receiver : rtp_manager()->GetReceiversInternal()) { + ret.push_back(receiver); + } } return ret; } @@ -1200,8 +1206,10 @@ PeerConnection::GetTransceivers() const { RTC_CHECK(IsUnifiedPlan()) << "GetTransceivers is only supported with Unified Plan SdpSemantics."; std::vector> all_transceivers; - for (const auto& transceiver : rtp_manager()->transceivers()->List()) { - all_transceivers.push_back(transceiver); + if (ConfiguredForMedia()) { + for (const auto& transceiver : rtp_manager()->transceivers()->List()) { + all_transceivers.push_back(transceiver); + } } return all_transceivers; } @@ -1680,8 +1688,7 @@ void PeerConnection::SetAudioPlayout(bool playout) { RTC_FROM_HERE, [this, playout] { SetAudioPlayout(playout); }); return; } - auto audio_state = - context_->channel_manager()->media_engine()->voice().GetAudioState(); + auto audio_state = media_engine()->voice().GetAudioState(); audio_state->SetPlayout(playout); } @@ -1691,8 +1698,7 @@ void PeerConnection::SetAudioRecording(bool recording) { RTC_FROM_HERE, [this, recording] { SetAudioRecording(recording); }); return; } - auto audio_state = - context_->channel_manager()->media_engine()->voice().GetAudioState(); + auto audio_state = media_engine()->voice().GetAudioState(); audio_state->SetRecording(recording); } @@ -1712,7 +1718,7 @@ void PeerConnection::AddAdaptationResource( } bool PeerConnection::ConfiguredForMedia() const { - return context_->channel_manager()->media_engine(); + return context_->channel_manager(); } bool PeerConnection::StartRtcEventLog(std::unique_ptr output, @@ -1822,12 +1828,13 @@ void PeerConnection::Close() { NoteUsageEvent(UsageEvent::CLOSE_CALLED); - for (const auto& transceiver : rtp_manager()->transceivers()->List()) { - transceiver->internal()->SetPeerConnectionClosed(); - if (!transceiver->stopped()) - transceiver->StopInternal(); + if (ConfiguredForMedia()) { + for (const auto& transceiver : rtp_manager()->transceivers()->List()) { + transceiver->internal()->SetPeerConnectionClosed(); + if (!transceiver->stopped()) + transceiver->StopInternal(); + } } - // Ensure that all asynchronous stats requests are completed before destroying // the transport controller below. if (stats_collector_) { @@ -1844,7 +1851,9 @@ void PeerConnection::Close() { // WebRTC session description factory, the session description factory would // call the transport controller. sdp_handler_->ResetSessionDescFactory(); - rtp_manager_->Close(); + if (ConfiguredForMedia()) { + rtp_manager_->Close(); + } network_thread()->Invoke(RTC_FROM_HERE, [this] { // Data channels will already have been unset via the DestroyAllChannels() @@ -2735,12 +2744,15 @@ void PeerConnection::ReportTransportStats() { rtc::Thread::ScopedDisallowBlockingCalls no_blocking_calls; std::map> media_types_by_transport_name; - for (const auto& transceiver : rtp_manager()->transceivers()->UnsafeList()) { - if (transceiver->internal()->channel()) { - std::string transport_name( - transceiver->internal()->channel()->transport_name()); - media_types_by_transport_name[transport_name].insert( - transceiver->media_type()); + if (ConfiguredForMedia()) { + for (const auto& transceiver : + rtp_manager()->transceivers()->UnsafeList()) { + if (transceiver->internal()->channel()) { + std::string transport_name( + transceiver->internal()->channel()->transport_name()); + media_types_by_transport_name[transport_name].insert( + transceiver->media_type()); + } } } @@ -2888,10 +2900,13 @@ bool PeerConnection::OnTransportChanged( DataChannelTransportInterface* data_channel_transport) { RTC_DCHECK_RUN_ON(network_thread()); bool ret = true; - for (const auto& transceiver : rtp_manager()->transceivers()->UnsafeList()) { - cricket::ChannelInterface* channel = transceiver->internal()->channel(); - if (channel && channel->mid() == mid) { - ret = channel->SetRtpTransport(rtp_transport); + if (ConfiguredForMedia()) { + for (const auto& transceiver : + rtp_manager()->transceivers()->UnsafeList()) { + cricket::ChannelInterface* channel = transceiver->internal()->channel(); + if (channel && channel->mid() == mid) { + ret = channel->SetRtpTransport(rtp_transport); + } } } @@ -2976,4 +2991,10 @@ PeerConnection::InitializeRtcpCallback() { }; } +cricket::MediaEngineInterface* PeerConnection::media_engine() { + RTC_DCHECK(context_); + RTC_DCHECK(context_->channel_manager()); + return context_->channel_manager()->media_engine(); +} + } // namespace webrtc diff --git a/pc/peer_connection.h b/pc/peer_connection.h index 2907cb565b..8c578d59e2 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -273,6 +273,9 @@ class PeerConnection : public PeerConnectionInternal, rtc::scoped_refptr>> GetTransceiversInternal() const override { RTC_DCHECK_RUN_ON(signaling_thread()); + if (!ConfiguredForMedia()) { + return {}; + } return rtp_manager()->transceivers()->List(); } @@ -596,6 +599,7 @@ class PeerConnection : public PeerConnectionInternal, cricket::ChannelManager* channel_manager() { return context_->channel_manager(); } + cricket::MediaEngineInterface* media_engine(); const rtc::scoped_refptr context_; // Field trials active for this PeerConnection is the first of: diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc index 6e6a72ced8..33803580de 100644 --- a/pc/peer_connection_factory.cc +++ b/pc/peer_connection_factory.cc @@ -129,14 +129,14 @@ RtpCapabilities PeerConnectionFactory::GetRtpSenderCapabilities( switch (kind) { case cricket::MEDIA_TYPE_AUDIO: { cricket::AudioCodecs cricket_codecs; - channel_manager()->GetSupportedAudioSendCodecs(&cricket_codecs); + cricket_codecs = media_engine()->voice().send_codecs(); return ToRtpCapabilities( cricket_codecs, channel_manager()->GetDefaultEnabledAudioRtpHeaderExtensions()); } case cricket::MEDIA_TYPE_VIDEO: { cricket::VideoCodecs cricket_codecs; - channel_manager()->GetSupportedVideoSendCodecs(&cricket_codecs); + cricket_codecs = media_engine()->video().send_codecs(); return ToRtpCapabilities( cricket_codecs, channel_manager()->GetDefaultEnabledVideoRtpHeaderExtensions()); @@ -156,7 +156,7 @@ RtpCapabilities PeerConnectionFactory::GetRtpReceiverCapabilities( switch (kind) { case cricket::MEDIA_TYPE_AUDIO: { cricket::AudioCodecs cricket_codecs; - channel_manager()->GetSupportedAudioReceiveCodecs(&cricket_codecs); + cricket_codecs = media_engine()->voice().recv_codecs(); return ToRtpCapabilities( cricket_codecs, channel_manager()->GetDefaultEnabledAudioRtpHeaderExtensions()); @@ -195,6 +195,12 @@ void PeerConnectionFactory::StopAecDump() { channel_manager()->StopAecDump(); } +cricket::MediaEngineInterface* PeerConnectionFactory::media_engine() const { + RTC_DCHECK(context_); + RTC_DCHECK(context_->channel_manager()); + return context_->channel_manager()->media_engine(); +} + RTCErrorOr> PeerConnectionFactory::CreatePeerConnectionOrError( const PeerConnectionInterface::RTCConfiguration& configuration, @@ -312,7 +318,7 @@ std::unique_ptr PeerConnectionFactory::CreateCall_w( RTC_DCHECK_RUN_ON(worker_thread()); webrtc::Call::Config call_config(event_log, network_thread()); - if (!channel_manager()->media_engine() || !context_->call_factory()) { + if (!channel_manager() || !context_->call_factory()) { return nullptr; } call_config.audio_state = diff --git a/pc/peer_connection_factory.h b/pc/peer_connection_factory.h index ff3d515964..917f054fd9 100644 --- a/pc/peer_connection_factory.h +++ b/pc/peer_connection_factory.h @@ -120,6 +120,8 @@ class PeerConnectionFactory : public PeerConnectionFactoryInterface { return context_->field_trials(); } + cricket::MediaEngineInterface* media_engine() const; + protected: // Constructor used by the static Create() method. Modifies the dependencies. PeerConnectionFactory(rtc::scoped_refptr context, diff --git a/pc/rtp_transceiver.cc b/pc/rtp_transceiver.cc index caa9ba5d64..1f6f879942 100644 --- a/pc/rtp_transceiver.cc +++ b/pc/rtp_transceiver.cc @@ -22,6 +22,7 @@ #include "api/sequence_checker.h" #include "media/base/codec.h" #include "media/base/media_constants.h" +#include "media/base/media_engine.h" #include "pc/channel.h" #include "pc/channel_manager.h" #include "pc/rtp_media_utils.h" @@ -562,7 +563,6 @@ void RtpTransceiver::StopTransceiverProcedure() { RTCError RtpTransceiver::SetCodecPreferences( rtc::ArrayView codec_capabilities) { RTC_DCHECK(unified_plan_); - // 3. If codecs is an empty list, set transceiver's [[PreferredCodecs]] slot // to codecs and abort these steps. if (codec_capabilities.empty()) { @@ -581,15 +581,14 @@ RTCError RtpTransceiver::SetCodecPreferences( RTCError result; if (media_type_ == cricket::MEDIA_TYPE_AUDIO) { std::vector recv_codecs, send_codecs; - channel_manager_->GetSupportedAudioReceiveCodecs(&recv_codecs); - channel_manager_->GetSupportedAudioSendCodecs(&send_codecs); + recv_codecs = media_engine()->voice().recv_codecs(); + send_codecs = media_engine()->voice().send_codecs(); result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs); } else if (media_type_ == cricket::MEDIA_TYPE_VIDEO) { std::vector recv_codecs, send_codecs; channel_manager_->GetSupportedVideoReceiveCodecs(&recv_codecs); channel_manager_->GetSupportedVideoSendCodecs(&send_codecs); - result = VerifyCodecPreferences(codecs, send_codecs, recv_codecs); } @@ -672,4 +671,8 @@ void RtpTransceiver::SetPeerConnectionClosed() { is_pc_closed_ = true; } +cricket::MediaEngineInterface* RtpTransceiver::media_engine() const { + return channel_manager_->media_engine(); +} + } // namespace webrtc diff --git a/pc/rtp_transceiver.h b/pc/rtp_transceiver.h index b61ca752d1..bbcbf2399c 100644 --- a/pc/rtp_transceiver.h +++ b/pc/rtp_transceiver.h @@ -47,6 +47,7 @@ namespace cricket { class ChannelManager; +class MediaEngineInterface; } namespace webrtc { @@ -338,6 +339,7 @@ class RtpTransceiver : public RtpTransceiverInterface, RTC_GUARDED_BY(thread_); const std::function on_negotiation_needed_; + cricket::MediaEngineInterface* media_engine() const; }; BEGIN_PRIMARY_PROXY_MAP(RtpTransceiver) diff --git a/pc/rtp_transceiver_unittest.cc b/pc/rtp_transceiver_unittest.cc index ce2eefc974..3c4b2c93e4 100644 --- a/pc/rtp_transceiver_unittest.cc +++ b/pc/rtp_transceiver_unittest.cc @@ -126,7 +126,7 @@ class RtpTransceiverUnifiedPlanTest : public ::testing::Test { rtc::Thread::Current(), receiver_), &channel_manager_, - channel_manager_.GetSupportedAudioRtpHeaderExtensions(), + channel_manager_.media_engine()->voice().GetRtpHeaderExtensions(), /* on_negotiation_needed= */ [] {})) {} static rtc::scoped_refptr MockReceiver() { diff --git a/pc/rtp_transmission_manager.cc b/pc/rtp_transmission_manager.cc index 6939a07dec..b2520d58be 100644 --- a/pc/rtp_transmission_manager.cc +++ b/pc/rtp_transmission_manager.cc @@ -273,8 +273,8 @@ RtpTransmissionManager::CreateAndAddTransceiver( rtc::make_ref_counted( sender, receiver, channel_manager(), sender->media_type() == cricket::MEDIA_TYPE_AUDIO - ? channel_manager()->GetSupportedAudioRtpHeaderExtensions() - : channel_manager()->GetSupportedVideoRtpHeaderExtensions(), + ? media_engine()->voice().GetRtpHeaderExtensions() + : media_engine()->video().GetRtpHeaderExtensions(), [this_weak_ptr = weak_ptr_factory_.GetWeakPtr()]() { if (this_weak_ptr) { this_weak_ptr->OnNegotiationNeeded(); @@ -690,4 +690,8 @@ RtpTransmissionManager::FindReceiverById(const std::string& receiver_id) const { return nullptr; } +cricket::MediaEngineInterface* RtpTransmissionManager::media_engine() const { + return channel_manager()->media_engine(); +} + } // namespace webrtc diff --git a/pc/rtp_transmission_manager.h b/pc/rtp_transmission_manager.h index 6e25f2d9b7..532adcfbfd 100644 --- a/pc/rtp_transmission_manager.h +++ b/pc/rtp_transmission_manager.h @@ -244,6 +244,8 @@ class RtpTransmissionManager : public RtpSenderBase::SetStreamsObserver { PeerConnectionObserver* Observer() const; void OnNegotiationNeeded(); + cricket::MediaEngineInterface* media_engine() const; + TransceiverList transceivers_; // These lists store sender info seen in local/remote descriptions. diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc index 1d34081bce..95f22b79f9 100644 --- a/pc/sdp_offer_answer.cc +++ b/pc/sdp_offer_answer.cc @@ -1258,10 +1258,17 @@ void SdpOfferAnswerHandler::Initialize( } // ================================================================== -// Access to pc_ variables +// Access to pc_ and context_ variables cricket::ChannelManager* SdpOfferAnswerHandler::channel_manager() const { return context_->channel_manager(); } + +cricket::MediaEngineInterface* SdpOfferAnswerHandler::media_engine() const { + RTC_DCHECK(context_); + RTC_DCHECK(context_->channel_manager()); + return context_->channel_manager()->media_engine(); +} + TransceiverList* SdpOfferAnswerHandler::transceivers() { if (!pc_->rtp_manager()) { return nullptr; @@ -1557,56 +1564,60 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription( << ")"; return error; } - std::vector> remove_list; - std::vector> removed_streams; - for (const auto& transceiver_ext : transceivers()->List()) { - auto transceiver = transceiver_ext->internal(); - if (transceiver->stopped()) { - continue; - } - - // 2.2.7.1.1.(6-9): Set sender and receiver's transport slots. - // Note that code paths that don't set MID won't be able to use - // information about DTLS transports. - if (transceiver->mid()) { - auto dtls_transport = LookupDtlsTransportByMid( - context_->network_thread(), transport_controller_s(), - *transceiver->mid()); - transceiver->sender_internal()->set_transport(dtls_transport); - transceiver->receiver_internal()->set_transport(dtls_transport); - } - - const ContentInfo* content = - FindMediaSectionForTransceiver(transceiver, local_description()); - if (!content) { - continue; - } - const MediaContentDescription* media_desc = content->media_description(); - // 2.2.7.1.6: If description is of type "answer" or "pranswer", then run - // the following steps: - if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) { - // 2.2.7.1.6.1: If direction is "sendonly" or "inactive", and - // transceiver's [[FiredDirection]] slot is either "sendrecv" or - // "recvonly", process the removal of a remote track for the media - // description, given transceiver, removeList, and muteTracks. - if (!RtpTransceiverDirectionHasRecv(media_desc->direction()) && - (transceiver->fired_direction() && - RtpTransceiverDirectionHasRecv(*transceiver->fired_direction()))) { - ProcessRemovalOfRemoteTrack(transceiver_ext, &remove_list, - &removed_streams); + if (ConfiguredForMedia()) { + std::vector> remove_list; + std::vector> removed_streams; + for (const auto& transceiver_ext : transceivers()->List()) { + auto transceiver = transceiver_ext->internal(); + if (transceiver->stopped()) { + continue; + } + + // 2.2.7.1.1.(6-9): Set sender and receiver's transport slots. + // Note that code paths that don't set MID won't be able to use + // information about DTLS transports. + if (transceiver->mid()) { + auto dtls_transport = LookupDtlsTransportByMid( + context_->network_thread(), transport_controller_s(), + *transceiver->mid()); + transceiver->sender_internal()->set_transport(dtls_transport); + transceiver->receiver_internal()->set_transport(dtls_transport); + } + + const ContentInfo* content = + FindMediaSectionForTransceiver(transceiver, local_description()); + if (!content) { + continue; + } + const MediaContentDescription* media_desc = + content->media_description(); + // 2.2.7.1.6: If description is of type "answer" or "pranswer", then run + // the following steps: + if (type == SdpType::kPrAnswer || type == SdpType::kAnswer) { + // 2.2.7.1.6.1: If direction is "sendonly" or "inactive", and + // transceiver's [[FiredDirection]] slot is either "sendrecv" or + // "recvonly", process the removal of a remote track for the media + // description, given transceiver, removeList, and muteTracks. + if (!RtpTransceiverDirectionHasRecv(media_desc->direction()) && + (transceiver->fired_direction() && + RtpTransceiverDirectionHasRecv( + *transceiver->fired_direction()))) { + ProcessRemovalOfRemoteTrack(transceiver_ext, &remove_list, + &removed_streams); + } + // 2.2.7.1.6.2: Set transceiver's [[CurrentDirection]] and + // [[FiredDirection]] slots to direction. + transceiver->set_current_direction(media_desc->direction()); + transceiver->set_fired_direction(media_desc->direction()); } - // 2.2.7.1.6.2: Set transceiver's [[CurrentDirection]] and - // [[FiredDirection]] slots to direction. - transceiver->set_current_direction(media_desc->direction()); - transceiver->set_fired_direction(media_desc->direction()); } - } - auto observer = pc_->Observer(); - for (const auto& transceiver : remove_list) { - observer->OnRemoveTrack(transceiver->receiver()); - } - for (const auto& stream : removed_streams) { - observer->OnRemoveStream(stream); + auto observer = pc_->Observer(); + for (const auto& transceiver : remove_list) { + observer->OnRemoveTrack(transceiver->receiver()); + } + for (const auto& stream : removed_streams) { + observer->OnRemoveStream(stream); + } } } else { // Media channels will be created only when offer is set. These may use new @@ -1650,35 +1661,39 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription( } if (IsUnifiedPlan()) { - // We must use List and not ListInternal here because - // transceivers()->StableState() is indexed by the non-internal refptr. - for (const auto& transceiver_ext : transceivers()->List()) { - auto transceiver = transceiver_ext->internal(); - if (transceiver->stopped()) { - continue; - } - const ContentInfo* content = - FindMediaSectionForTransceiver(transceiver, local_description()); - if (!content) { - continue; - } - cricket::ChannelInterface* channel = transceiver->channel(); - if (content->rejected || !channel || channel->local_streams().empty()) { - // 0 is a special value meaning "this sender has no associated send - // stream". Need to call this so the sender won't attempt to configure - // a no longer existing stream and run into DCHECKs in the lower - // layers. - transceiver->sender_internal()->SetSsrc(0); - } else { - // Get the StreamParams from the channel which could generate SSRCs. - const std::vector& streams = channel->local_streams(); - transceiver->sender_internal()->set_stream_ids(streams[0].stream_ids()); - auto encodings = transceiver->sender_internal()->init_send_encodings(); - transceiver->sender_internal()->SetSsrc(streams[0].first_ssrc()); - if (!encodings.empty()) { - transceivers() - ->StableState(transceiver_ext) - ->SetInitSendEncodings(encodings); + if (ConfiguredForMedia()) { + // We must use List and not ListInternal here because + // transceivers()->StableState() is indexed by the non-internal refptr. + for (const auto& transceiver_ext : transceivers()->List()) { + auto transceiver = transceiver_ext->internal(); + if (transceiver->stopped()) { + continue; + } + const ContentInfo* content = + FindMediaSectionForTransceiver(transceiver, local_description()); + if (!content) { + continue; + } + cricket::ChannelInterface* channel = transceiver->channel(); + if (content->rejected || !channel || channel->local_streams().empty()) { + // 0 is a special value meaning "this sender has no associated send + // stream". Need to call this so the sender won't attempt to configure + // a no longer existing stream and run into DCHECKs in the lower + // layers. + transceiver->sender_internal()->SetSsrc(0); + } else { + // Get the StreamParams from the channel which could generate SSRCs. + const std::vector& streams = channel->local_streams(); + transceiver->sender_internal()->set_stream_ids( + streams[0].stream_ids()); + auto encodings = + transceiver->sender_internal()->init_send_encodings(); + transceiver->sender_internal()->SetSsrc(streams[0].first_ssrc()); + if (!encodings.empty()) { + transceivers() + ->StableState(transceiver_ext) + ->SetInitSendEncodings(encodings); + } } } } @@ -1938,6 +1953,9 @@ void SdpOfferAnswerHandler::ApplyRemoteDescriptionUpdateTransceiverState( SdpType sdp_type) { RTC_DCHECK_RUN_ON(signaling_thread()); RTC_DCHECK(IsUnifiedPlan()); + if (!ConfiguredForMedia()) { + return; + } std::vector> now_receiving_transceivers; std::vector> remove_list; @@ -2725,7 +2743,9 @@ RTCError SdpOfferAnswerHandler::UpdateSessionState( } else { RTC_DCHECK(type == SdpType::kAnswer); ChangeSignalingState(PeerConnectionInterface::kStable); - transceivers()->DiscardStableStates(); + if (ConfiguredForMedia()) { + transceivers()->DiscardStableStates(); + } } // Update internal objects according to the session description's media @@ -3151,6 +3171,9 @@ bool SdpOfferAnswerHandler::CheckIfNegotiationIsNeeded() { if (!cricket::GetFirstDataContent(description->description()->contents())) return true; } + if (!ConfiguredForMedia()) { + return false; + } // 5. For each transceiver in connection's set of transceivers, perform the // following checks: @@ -3262,7 +3285,6 @@ bool SdpOfferAnswerHandler::CheckIfNegotiationIsNeeded() { } } } - // If all the preceding checks were performed and true was not returned, // nothing remains to be negotiated; return false. return false; @@ -3841,38 +3863,43 @@ void SdpOfferAnswerHandler::GetOptionsForOffer( void SdpOfferAnswerHandler::GetOptionsForPlanBOffer( const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options, cricket::MediaSessionOptions* session_options) { - // Figure out transceiver directional preferences. - bool send_audio = - !rtp_manager()->GetAudioTransceiver()->internal()->senders().empty(); - bool send_video = - !rtp_manager()->GetVideoTransceiver()->internal()->senders().empty(); - - // By default, generate sendrecv/recvonly m= sections. - bool recv_audio = true; - bool recv_video = true; + bool offer_new_data_description = + data_channel_controller()->HasDataChannels(); + bool send_audio = false; + bool send_video = false; + bool recv_audio = false; + bool recv_video = false; + if (ConfiguredForMedia()) { + // Figure out transceiver directional preferences. + send_audio = + !rtp_manager()->GetAudioTransceiver()->internal()->senders().empty(); + send_video = + !rtp_manager()->GetVideoTransceiver()->internal()->senders().empty(); + // By default, generate sendrecv/recvonly m= sections. + recv_audio = true; + recv_video = true; + } // By default, only offer a new m= section if we have media to send with it. bool offer_new_audio_description = send_audio; bool offer_new_video_description = send_video; - bool offer_new_data_description = - data_channel_controller()->HasDataChannels(); - - // The "offer_to_receive_X" options allow those defaults to be overridden. - if (offer_answer_options.offer_to_receive_audio != - PeerConnectionInterface::RTCOfferAnswerOptions::kUndefined) { - recv_audio = (offer_answer_options.offer_to_receive_audio > 0); - offer_new_audio_description = - offer_new_audio_description || - (offer_answer_options.offer_to_receive_audio > 0); + if (ConfiguredForMedia()) { + // The "offer_to_receive_X" options allow those defaults to be overridden. + if (offer_answer_options.offer_to_receive_audio != + PeerConnectionInterface::RTCOfferAnswerOptions::kUndefined) { + recv_audio = (offer_answer_options.offer_to_receive_audio > 0); + offer_new_audio_description = + offer_new_audio_description || + (offer_answer_options.offer_to_receive_audio > 0); + } + if (offer_answer_options.offer_to_receive_video != + RTCOfferAnswerOptions::kUndefined) { + recv_video = (offer_answer_options.offer_to_receive_video > 0); + offer_new_video_description = + offer_new_video_description || + (offer_answer_options.offer_to_receive_video > 0); + } } - if (offer_answer_options.offer_to_receive_video != - RTCOfferAnswerOptions::kUndefined) { - recv_video = (offer_answer_options.offer_to_receive_video > 0); - offer_new_video_description = - offer_new_video_description || - (offer_answer_options.offer_to_receive_video > 0); - } - absl::optional audio_index; absl::optional video_index; absl::optional data_index; @@ -3887,42 +3914,44 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBOffer( &audio_index, &video_index, &data_index, session_options); } - // Add audio/video/data m= sections to the end if needed. - if (!audio_index && offer_new_audio_description) { - cricket::MediaDescriptionOptions options( - cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, - RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), false); - options.header_extensions = - channel_manager()->GetSupportedAudioRtpHeaderExtensions(); - session_options->media_description_options.push_back(options); - audio_index = session_options->media_description_options.size() - 1; - } - if (!video_index && offer_new_video_description) { - cricket::MediaDescriptionOptions options( - cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, - RtpTransceiverDirectionFromSendRecv(send_video, recv_video), false); - options.header_extensions = - channel_manager()->GetSupportedVideoRtpHeaderExtensions(); - session_options->media_description_options.push_back(options); - video_index = session_options->media_description_options.size() - 1; + if (ConfiguredForMedia()) { + // Add audio/video/data m= sections to the end if needed. + if (!audio_index && offer_new_audio_description) { + cricket::MediaDescriptionOptions options( + cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, + RtpTransceiverDirectionFromSendRecv(send_audio, recv_audio), false); + options.header_extensions = + media_engine()->voice().GetRtpHeaderExtensions(); + session_options->media_description_options.push_back(options); + audio_index = session_options->media_description_options.size() - 1; + } + if (!video_index && offer_new_video_description) { + cricket::MediaDescriptionOptions options( + cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, + RtpTransceiverDirectionFromSendRecv(send_video, recv_video), false); + options.header_extensions = + media_engine()->video().GetRtpHeaderExtensions(); + session_options->media_description_options.push_back(options); + video_index = session_options->media_description_options.size() - 1; + } + cricket::MediaDescriptionOptions* audio_media_description_options = + !audio_index + ? nullptr + : &session_options->media_description_options[*audio_index]; + cricket::MediaDescriptionOptions* video_media_description_options = + !video_index + ? nullptr + : &session_options->media_description_options[*video_index]; + + AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(), + audio_media_description_options, + video_media_description_options, + offer_answer_options.num_simulcast_layers); } if (!data_index && offer_new_data_description) { session_options->media_description_options.push_back( GetMediaDescriptionOptionsForActiveData(cricket::CN_DATA)); - data_index = session_options->media_description_options.size() - 1; } - - cricket::MediaDescriptionOptions* audio_media_description_options = - !audio_index ? nullptr - : &session_options->media_description_options[*audio_index]; - cricket::MediaDescriptionOptions* video_media_description_options = - !video_index ? nullptr - : &session_options->media_description_options[*video_index]; - - AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(), - audio_media_description_options, - video_media_description_options, - offer_answer_options.num_simulcast_layers); } void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer( @@ -4028,27 +4057,29 @@ void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanOffer( // and not associated). Reuse media sections marked as recyclable first, // otherwise append to the end of the offer. New media sections should be // added in the order they were added to the PeerConnection. - for (const auto& transceiver : transceivers()->ListInternal()) { - if (transceiver->mid() || transceiver->stopping()) { - continue; + if (ConfiguredForMedia()) { + for (const auto& transceiver : transceivers()->ListInternal()) { + if (transceiver->mid() || transceiver->stopping()) { + continue; + } + size_t mline_index; + if (!recycleable_mline_indices.empty()) { + mline_index = recycleable_mline_indices.front(); + recycleable_mline_indices.pop(); + session_options->media_description_options[mline_index] = + GetMediaDescriptionOptionsForTransceiver( + transceiver, mid_generator_.GenerateString(), + /*is_create_offer=*/true); + } else { + mline_index = session_options->media_description_options.size(); + session_options->media_description_options.push_back( + GetMediaDescriptionOptionsForTransceiver( + transceiver, mid_generator_.GenerateString(), + /*is_create_offer=*/true)); + } + // See comment above for why CreateOffer changes the transceiver's state. + transceiver->set_mline_index(mline_index); } - size_t mline_index; - if (!recycleable_mline_indices.empty()) { - mline_index = recycleable_mline_indices.front(); - recycleable_mline_indices.pop(); - session_options->media_description_options[mline_index] = - GetMediaDescriptionOptionsForTransceiver( - transceiver, mid_generator_.GenerateString(), - /*is_create_offer=*/true); - } else { - mline_index = session_options->media_description_options.size(); - session_options->media_description_options.push_back( - GetMediaDescriptionOptionsForTransceiver( - transceiver, mid_generator_.GenerateString(), - /*is_create_offer=*/true)); - } - // See comment above for why CreateOffer changes the transceiver's state. - transceiver->set_mline_index(mline_index); } // Lastly, add a m-section if we have local data channels and an m section // does not already exist. @@ -4088,25 +4119,32 @@ void SdpOfferAnswerHandler::GetOptionsForAnswer( void SdpOfferAnswerHandler::GetOptionsForPlanBAnswer( const PeerConnectionInterface::RTCOfferAnswerOptions& offer_answer_options, cricket::MediaSessionOptions* session_options) { - // Figure out transceiver directional preferences. - bool send_audio = - !rtp_manager()->GetAudioTransceiver()->internal()->senders().empty(); - bool send_video = - !rtp_manager()->GetVideoTransceiver()->internal()->senders().empty(); + bool send_audio = false; + bool recv_audio = false; + bool send_video = false; + bool recv_video = false; - // By default, generate sendrecv/recvonly m= sections. The direction is also - // restricted by the direction in the offer. - bool recv_audio = true; - bool recv_video = true; + if (ConfiguredForMedia()) { + // Figure out transceiver directional preferences. + send_audio = + !rtp_manager()->GetAudioTransceiver()->internal()->senders().empty(); + send_video = + !rtp_manager()->GetVideoTransceiver()->internal()->senders().empty(); - // The "offer_to_receive_X" options allow those defaults to be overridden. - if (offer_answer_options.offer_to_receive_audio != - RTCOfferAnswerOptions::kUndefined) { - recv_audio = (offer_answer_options.offer_to_receive_audio > 0); - } - if (offer_answer_options.offer_to_receive_video != - RTCOfferAnswerOptions::kUndefined) { - recv_video = (offer_answer_options.offer_to_receive_video > 0); + // By default, generate sendrecv/recvonly m= sections. The direction is also + // restricted by the direction in the offer. + recv_audio = true; + recv_video = true; + + // The "offer_to_receive_X" options allow those defaults to be overridden. + if (offer_answer_options.offer_to_receive_audio != + RTCOfferAnswerOptions::kUndefined) { + recv_audio = (offer_answer_options.offer_to_receive_audio > 0); + } + if (offer_answer_options.offer_to_receive_video != + RTCOfferAnswerOptions::kUndefined) { + recv_video = (offer_answer_options.offer_to_receive_video > 0); + } } absl::optional audio_index; @@ -4129,10 +4167,12 @@ void SdpOfferAnswerHandler::GetOptionsForPlanBAnswer( !video_index ? nullptr : &session_options->media_description_options[*video_index]; - AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(), - audio_media_description_options, - video_media_description_options, - offer_answer_options.num_simulcast_layers); + if (ConfiguredForMedia()) { + AddPlanBRtpSenderOptions(rtp_manager()->GetSendersInternal(), + audio_media_description_options, + video_media_description_options, + offer_answer_options.num_simulcast_layers); + } } void SdpOfferAnswerHandler::GetOptionsForUnifiedPlanAnswer( @@ -4477,6 +4517,9 @@ void SdpOfferAnswerHandler::UpdateRemoteSendersList( void SdpOfferAnswerHandler::EnableSending() { TRACE_EVENT0("webrtc", "SdpOfferAnswerHandler::EnableSending"); RTC_DCHECK_RUN_ON(signaling_thread()); + if (!ConfiguredForMedia()) { + return; + } for (const auto& transceiver : transceivers()->ListInternal()) { cricket::ChannelInterface* channel = transceiver->channel(); if (channel) { @@ -4497,60 +4540,63 @@ RTCError SdpOfferAnswerHandler::PushdownMediaDescription( RTC_DCHECK_RUN_ON(signaling_thread()); RTC_DCHECK(sdesc); - // Note: This will perform an Invoke over to the worker thread, which we'll - // also do in a loop below. - if (!UpdatePayloadTypeDemuxingState(source, bundle_groups_by_mid)) { - // Note that this is never expected to fail, since RtpDemuxer doesn't return - // an error when changing payload type demux criteria, which is all this - // does. - return RTCError(RTCErrorType::INTERNAL_ERROR, - "Failed to update payload type demuxing state."); - } - - // Push down the new SDP media section for each audio/video transceiver. - auto rtp_transceivers = transceivers()->ListInternal(); - std::vector< - std::pair> - channels; - for (const auto& transceiver : rtp_transceivers) { - const ContentInfo* content_info = - FindMediaSectionForTransceiver(transceiver, sdesc); - cricket::ChannelInterface* channel = transceiver->channel(); - if (!channel || !content_info || content_info->rejected) { - continue; - } - const MediaContentDescription* content_desc = - content_info->media_description(); - if (!content_desc) { - continue; + if (ConfiguredForMedia()) { + // Note: This will perform an Invoke over to the worker thread, which we'll + // also do in a loop below. + if (!UpdatePayloadTypeDemuxingState(source, bundle_groups_by_mid)) { + // Note that this is never expected to fail, since RtpDemuxer doesn't + // return an error when changing payload type demux criteria, which is all + // this does. + return RTCError(RTCErrorType::INTERNAL_ERROR, + "Failed to update payload type demuxing state."); } - transceiver->OnNegotiationUpdate(type, content_desc); - channels.push_back(std::make_pair(channel, content_desc)); - } + // Push down the new SDP media section for each audio/video transceiver. + auto rtp_transceivers = transceivers()->ListInternal(); + std::vector< + std::pair> + channels; + for (const auto& transceiver : rtp_transceivers) { + const ContentInfo* content_info = + FindMediaSectionForTransceiver(transceiver, sdesc); + cricket::ChannelInterface* channel = transceiver->channel(); + if (!channel || !content_info || content_info->rejected) { + continue; + } + const MediaContentDescription* content_desc = + content_info->media_description(); + if (!content_desc) { + continue; + } - // This for-loop of invokes helps audio impairment during re-negotiations. - // One of the causes is that downstairs decoder creation is synchronous at the - // moment, and that a decoder is created for each codec listed in the SDP. - // - // TODO(bugs.webrtc.org/12840): consider merging the invokes again after - // these projects have shipped: - // - bugs.webrtc.org/12462 - // - crbug.com/1157227 - // - crbug.com/1187289 - for (const auto& entry : channels) { - std::string error; - bool success = - context_->worker_thread()->Invoke(RTC_FROM_HERE, [&]() { - return (source == cricket::CS_LOCAL) - ? entry.first->SetLocalContent(entry.second, type, error) - : entry.first->SetRemoteContent(entry.second, type, error); - }); - if (!success) { - return RTCError(RTCErrorType::INVALID_PARAMETER, error); + transceiver->OnNegotiationUpdate(type, content_desc); + channels.push_back(std::make_pair(channel, content_desc)); + } + + // This for-loop of invokes helps audio impairment during re-negotiations. + // One of the causes is that downstairs decoder creation is synchronous at + // the moment, and that a decoder is created for each codec listed in the + // SDP. + // + // TODO(bugs.webrtc.org/12840): consider merging the invokes again after + // these projects have shipped: + // - bugs.webrtc.org/12462 + // - crbug.com/1157227 + // - crbug.com/1187289 + for (const auto& entry : channels) { + std::string error; + bool success = + context_->worker_thread()->Invoke(RTC_FROM_HERE, [&]() { + return (source == cricket::CS_LOCAL) + ? entry.first->SetLocalContent(entry.second, type, error) + : entry.first->SetRemoteContent(entry.second, type, + error); + }); + if (!success) { + return RTCError(RTCErrorType::INVALID_PARAMETER, error); + } } } - // Need complete offer/answer with an SCTP m= section before starting SCTP, // according to https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-19 if (pc_->sctp_mid() && local_description() && remote_description()) { @@ -4604,6 +4650,9 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() { // run the following steps: if (!IsUnifiedPlan()) return; + if (!ConfiguredForMedia()) { + return; + } // Traverse a copy of the transceiver list. auto transceiver_list = transceivers()->List(); for (auto transceiver : transceiver_list) { @@ -4638,18 +4687,21 @@ void SdpOfferAnswerHandler::RemoveStoppedTransceivers() { void SdpOfferAnswerHandler::RemoveUnusedChannels( const SessionDescription* desc) { RTC_DCHECK_RUN_ON(signaling_thread()); - // Destroy video channel first since it may have a pointer to the - // voice channel. - const cricket::ContentInfo* video_info = cricket::GetFirstVideoContent(desc); - if (!video_info || video_info->rejected) { - rtp_manager()->GetVideoTransceiver()->internal()->ClearChannel(); - } + if (ConfiguredForMedia()) { + // Destroy video channel first since it may have a pointer to the + // voice channel. + const cricket::ContentInfo* video_info = + cricket::GetFirstVideoContent(desc); + if (!video_info || video_info->rejected) { + rtp_manager()->GetVideoTransceiver()->internal()->ClearChannel(); + } - const cricket::ContentInfo* audio_info = cricket::GetFirstAudioContent(desc); - if (!audio_info || audio_info->rejected) { - rtp_manager()->GetAudioTransceiver()->internal()->ClearChannel(); + const cricket::ContentInfo* audio_info = + cricket::GetFirstAudioContent(desc); + if (!audio_info || audio_info->rejected) { + rtp_manager()->GetAudioTransceiver()->internal()->ClearChannel(); + } } - const cricket::ContentInfo* data_info = cricket::GetFirstDataContent(desc); if (!data_info) { RTCError error(RTCErrorType::OPERATION_ERROR_WITH_DATA, @@ -4967,7 +5019,7 @@ void SdpOfferAnswerHandler::GenerateMediaDescriptionOptions( *audio_index = session_options->media_description_options.size() - 1; } session_options->media_description_options.back().header_extensions = - channel_manager()->GetSupportedAudioRtpHeaderExtensions(); + media_engine()->voice().GetRtpHeaderExtensions(); } else if (IsVideoContent(&content)) { // If we already have an video m= section, reject this extra one. if (*video_index) { @@ -4984,7 +5036,7 @@ void SdpOfferAnswerHandler::GenerateMediaDescriptionOptions( *video_index = session_options->media_description_options.size() - 1; } session_options->media_description_options.back().header_extensions = - channel_manager()->GetSupportedVideoRtpHeaderExtensions(); + media_engine()->video().GetRtpHeaderExtensions(); } else if (IsUnsupportedContent(&content)) { session_options->media_description_options.push_back( cricket::MediaDescriptionOptions(cricket::MEDIA_TYPE_UNSUPPORTED, @@ -5208,4 +5260,8 @@ bool SdpOfferAnswerHandler::UpdatePayloadTypeDemuxingState( }); } +bool SdpOfferAnswerHandler::ConfiguredForMedia() const { + return context_->channel_manager(); +} + } // namespace webrtc diff --git a/pc/sdp_offer_answer.h b/pc/sdp_offer_answer.h index de814ec737..6a0aaaad27 100644 --- a/pc/sdp_offer_answer.h +++ b/pc/sdp_offer_answer.h @@ -478,7 +478,7 @@ class SdpOfferAnswerHandler : public SdpStateProvider, // This enables media to flow on all configured audio/video channels. void EnableSending(); // Push the media parts of the local or remote session description - // down to all of the channels. + // down to all of the channels, and start SCTP if needed. RTCError PushdownMediaDescription( SdpType type, cricket::ContentSource source, @@ -576,6 +576,7 @@ class SdpOfferAnswerHandler : public SdpStateProvider, // ================================================================== // Access to pc_ variables cricket::ChannelManager* channel_manager() const; + cricket::MediaEngineInterface* media_engine() const; TransceiverList* transceivers(); const TransceiverList* transceivers() const; DataChannelController* data_channel_controller(); @@ -595,6 +596,7 @@ class SdpOfferAnswerHandler : public SdpStateProvider, // =================================================================== const cricket::AudioOptions& audio_options() { return audio_options_; } const cricket::VideoOptions& video_options() { return video_options_; } + bool ConfiguredForMedia() const; PeerConnectionSdpMethods* const pc_; ConnectionContext* const context_; diff --git a/pc/test/fake_peer_connection_for_stats.h b/pc/test/fake_peer_connection_for_stats.h index e612f0d10f..e7ed804814 100644 --- a/pc/test/fake_peer_connection_for_stats.h +++ b/pc/test/fake_peer_connection_for_stats.h @@ -415,7 +415,10 @@ class FakePeerConnectionForStats : public FakePeerConnectionBase { class TestChannelManager : public cricket::ChannelManager { public: TestChannelManager(rtc::Thread* worker, rtc::Thread* network) - : cricket::ChannelManager(nullptr, true, worker, network) {} + : cricket::ChannelManager(std::make_unique(), + true, + worker, + network) {} }; rtc::Thread* const network_thread_;