diff --git a/pc/BUILD.gn b/pc/BUILD.gn index 7b7f863ab7..1eb77c493e 100644 --- a/pc/BUILD.gn +++ b/pc/BUILD.gn @@ -217,6 +217,8 @@ rtc_library("peerconnection") { "stream_collection.h", "track_media_info_map.cc", "track_media_info_map.h", + "transceiver_list.cc", + "transceiver_list.h", "video_rtp_receiver.cc", "video_rtp_receiver.h", "video_rtp_track_source.cc", diff --git a/pc/peer_connection.cc b/pc/peer_connection.cc index 75dc80b7c0..64898e207e 100644 --- a/pc/peer_connection.cc +++ b/pc/peer_connection.cc @@ -435,28 +435,6 @@ bool PeerConnectionInterface::RTCConfiguration::operator!=( return !(*this == o); } -void PeerConnection::TransceiverStableState::set_newly_created() { - RTC_DCHECK(!has_m_section_); - newly_created_ = true; -} - -void PeerConnection::TransceiverStableState::SetMSectionIfUnset( - absl::optional mid, - absl::optional mline_index) { - if (!has_m_section_) { - mid_ = mid; - mline_index_ = mline_index; - has_m_section_ = true; - } -} - -void PeerConnection::TransceiverStableState::SetRemoteStreamIdsIfUnset( - const std::vector& ids) { - if (!remote_stream_ids_.has_value()) { - remote_stream_ids_ = ids; - } -} - // Generate a RTCP CNAME when a PeerConnection is created. std::string GenerateRtcpCname() { std::string cname; @@ -501,7 +479,7 @@ PeerConnection::~PeerConnection() { // Need to stop transceivers before destroying the stats collector because // AudioRtpSender has a reference to the StatsCollector it will update when // stopping. - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { transceiver->StopInternal(); } @@ -555,12 +533,12 @@ PeerConnection::~PeerConnection() { void PeerConnection::DestroyAllChannels() { // Destroy video channels first since they may have a pointer to a voice // channel. - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) { DestroyTransceiverChannel(transceiver); } } - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { DestroyTransceiverChannel(transceiver); } @@ -780,12 +758,10 @@ bool PeerConnection::Initialize( // Add default audio/video transceivers for Plan B SDP. if (!IsUnifiedPlan()) { - transceivers_.push_back( - RtpTransceiverProxyWithInternal::Create( - signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO))); - transceivers_.push_back( - RtpTransceiverProxyWithInternal::Create( - signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO))); + transceivers_.Add(RtpTransceiverProxyWithInternal::Create( + signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO))); + transceivers_.Add(RtpTransceiverProxyWithInternal::Create( + signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO))); } int delay_ms = return_histogram_very_quickly_ ? 0 : REPORT_USAGE_PATTERN_DELAY_MS; @@ -1014,7 +990,7 @@ rtc::scoped_refptr> PeerConnection::FindFirstTransceiverForAddedTrack( rtc::scoped_refptr track) { RTC_DCHECK(track); - for (auto transceiver : transceivers_) { + for (auto transceiver : transceivers_.List()) { if (!transceiver->sender()->track() && cricket::MediaTypeToString(transceiver->media_type()) == track->kind() && @@ -1075,12 +1051,7 @@ RTCError PeerConnection::RemoveTrackNew( rtc::scoped_refptr> PeerConnection::FindTransceiverBySender( rtc::scoped_refptr sender) { - for (auto transceiver : transceivers_) { - if (transceiver->sender() == sender) { - return transceiver; - } - } - return nullptr; + return transceivers_.FindBySender(sender); } RTCErrorOr> @@ -1300,7 +1271,7 @@ PeerConnection::CreateAndAddTransceiver( sender->media_type() == cricket::MEDIA_TYPE_AUDIO ? channel_manager()->GetSupportedAudioRtpHeaderExtensions() : channel_manager()->GetSupportedVideoRtpHeaderExtensions())); - transceivers_.push_back(transceiver); + transceivers_.Add(transceiver); transceiver->internal()->SignalNegotiationNeeded.connect( this, &PeerConnection::OnNegotiationNeeded); return transceiver; @@ -1375,7 +1346,7 @@ std::vector>> PeerConnection::GetSendersInternal() const { std::vector>> all_senders; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (IsUnifiedPlan() && transceiver->internal()->stopped()) continue; @@ -1401,7 +1372,7 @@ PeerConnection::GetReceiversInternal() const { std::vector< rtc::scoped_refptr>> all_receivers; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (IsUnifiedPlan() && transceiver->internal()->stopped()) continue; @@ -1418,7 +1389,7 @@ PeerConnection::GetTransceivers() const { RTC_CHECK(IsUnifiedPlan()) << "GetTransceivers is only supported with Unified Plan SdpSemantics."; std::vector> all_transceivers; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { all_transceivers.push_back(transceiver); } return all_transceivers; @@ -1464,7 +1435,7 @@ void PeerConnection::GetStats( RTC_DCHECK(stats_collector_); rtc::scoped_refptr internal_sender; if (selector) { - for (const auto& proxy_transceiver : transceivers_) { + for (const auto& proxy_transceiver : transceivers_.List()) { for (const auto& proxy_sender : proxy_transceiver->internal()->senders()) { if (proxy_sender == selector) { @@ -1493,7 +1464,7 @@ void PeerConnection::GetStats( RTC_DCHECK(stats_collector_); rtc::scoped_refptr internal_receiver; if (selector) { - for (const auto& proxy_transceiver : transceivers_) { + for (const auto& proxy_transceiver : transceivers_.List()) { for (const auto& proxy_receiver : proxy_transceiver->internal()->receivers()) { if (proxy_receiver == selector) { @@ -1670,7 +1641,7 @@ PeerConnection::GetReceivingTransceiversOfType(cricket::MediaType media_type) { std::vector< rtc::scoped_refptr>> receiving_transceivers; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (!transceiver->stopped() && transceiver->media_type() == media_type && RtpTransceiverDirectionHasRecv(transceiver->direction())) { receiving_transceivers.push_back(transceiver); @@ -1711,15 +1682,15 @@ void PeerConnection::RemoveStoppedTransceivers() { // run the following steps: if (!IsUnifiedPlan()) return; - for (auto it = transceivers_.begin(); it != transceivers_.end();) { - const auto& transceiver = *it; + // Traverse a copy of the transceiver list. + auto transceiver_list = transceivers_.List(); + for (auto transceiver : transceiver_list) { // 3.2.10.1.1: If transceiver is stopped, associated with an m= section // and the associated m= section is rejected in // connection.[[CurrentLocalDescription]] or // connection.[[CurrentRemoteDescription]], remove the // transceiver from the connection's set of transceivers. if (!transceiver->stopped()) { - ++it; continue; } const ContentInfo* local_content = @@ -1730,9 +1701,9 @@ void PeerConnection::RemoveStoppedTransceivers() { (remote_content && remote_content->rejected)) { RTC_LOG(LS_INFO) << "Dissociating transceiver" << " since the media section is being recycled."; - (*it)->internal()->set_mid(absl::nullopt); - (*it)->internal()->set_mline_index(absl::nullopt); - it = transceivers_.erase(it); + transceiver->internal()->set_mid(absl::nullopt); + transceiver->internal()->set_mline_index(absl::nullopt); + transceivers_.Remove(transceiver); continue; } if (!local_content && !remote_content) { @@ -1740,10 +1711,9 @@ void PeerConnection::RemoveStoppedTransceivers() { // See https://github.com/w3c/webrtc-pc/issues/2576 RTC_LOG(LS_INFO) << "Dropping stopped transceiver that was never associated"; - it = transceivers_.erase(it); + transceivers_.Remove(transceiver); continue; } - ++it; } } @@ -1855,24 +1825,14 @@ rtc::scoped_refptr> PeerConnection::GetAssociatedTransceiver(const std::string& mid) const { RTC_DCHECK_RUN_ON(signaling_thread()); RTC_DCHECK(IsUnifiedPlan()); - for (auto transceiver : transceivers_) { - if (transceiver->mid() == mid) { - return transceiver; - } - } - return nullptr; + return transceivers_.FindByMid(mid); } rtc::scoped_refptr> PeerConnection::GetTransceiverByMLineIndex(size_t mline_index) const { RTC_DCHECK_RUN_ON(signaling_thread()); RTC_DCHECK(IsUnifiedPlan()); - for (auto transceiver : transceivers_) { - if (transceiver->internal()->mline_index() == mline_index) { - return transceiver; - } - } - return nullptr; + return transceivers_.FindByMLineIndex(mline_index); } rtc::scoped_refptr> @@ -1885,7 +1845,7 @@ PeerConnection::FindAvailableTransceiverToReceive( // the same type that were added to the PeerConnection by addTrack and are not // associated with any m= section and are not stopped, find the first such // RtpTransceiver. - for (auto transceiver : transceivers_) { + for (auto transceiver : transceivers_.List()) { if (transceiver->media_type() == media_type && transceiver->internal()->created_by_addtrack() && !transceiver->mid() && !transceiver->stopped()) { @@ -2053,7 +2013,7 @@ RTCError PeerConnection::SetConfiguration( if (modified_config.allow_codec_switching.has_value()) { std::vector channels; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (transceiver->media_type() != cricket::MEDIA_TYPE_VIDEO) continue; @@ -2184,7 +2144,7 @@ PeerConnection::GetRemoteAudioSSLCertChain() { rtc::scoped_refptr> PeerConnection::GetFirstAudioTransceiver() const { - for (auto transceiver : transceivers_) { + for (auto transceiver : transceivers_.List()) { if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { return transceiver; } @@ -2308,7 +2268,7 @@ void PeerConnection::Close() { NoteUsageEvent(UsageEvent::CLOSE_CALLED); - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { transceiver->internal()->SetPeerConnectionClosed(); if (!transceiver->stopped()) transceiver->StopInternal(); @@ -3028,7 +2988,7 @@ void PeerConnection::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_) { + for (const auto& transceiver : transceivers_.List()) { if (transceiver->mid() || transceiver->stopping()) { continue; } @@ -3550,7 +3510,7 @@ PeerConnection::GetAudioTransceiver() const { // This method only works with Plan B SDP, where there is a single // audio/video transceiver. RTC_DCHECK(!IsUnifiedPlan()); - for (auto transceiver : transceivers_) { + for (auto transceiver : transceivers_.List()) { if (transceiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { return transceiver; } @@ -3564,7 +3524,7 @@ PeerConnection::GetVideoTransceiver() const { // This method only works with Plan B SDP, where there is a single // audio/video transceiver. RTC_DCHECK(!IsUnifiedPlan()); - for (auto transceiver : transceivers_) { + for (auto transceiver : transceivers_.List()) { if (transceiver->media_type() == cricket::MEDIA_TYPE_VIDEO) { return transceiver; } @@ -3575,7 +3535,7 @@ PeerConnection::GetVideoTransceiver() const { rtc::scoped_refptr> PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) const { - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { for (auto sender : transceiver->internal()->senders()) { if (sender->track() == track) { return sender; @@ -3587,7 +3547,7 @@ PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) const { rtc::scoped_refptr> PeerConnection::FindSenderById(const std::string& sender_id) const { - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { for (auto sender : transceiver->internal()->senders()) { if (sender->id() == sender_id) { return sender; @@ -3599,7 +3559,7 @@ PeerConnection::FindSenderById(const std::string& sender_id) const { rtc::scoped_refptr> PeerConnection::FindReceiverById(const std::string& receiver_id) const { - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { for (auto receiver : transceiver->internal()->receivers()) { if (receiver->id() == receiver_id) { return receiver; @@ -3764,7 +3724,7 @@ void PeerConnection::StopRtcEventLog_w() { cricket::ChannelInterface* PeerConnection::GetChannel( const std::string& content_name) { - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { cricket::ChannelInterface* channel = transceiver->internal()->channel(); if (channel && channel->content_name() == content_name) { return channel; @@ -3873,7 +3833,7 @@ void PeerConnection::UpdatePayloadTypeDemuxingState( // single Invoke; necessary due to thread guards. std::vector> channels_to_update; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { cricket::ChannelInterface* channel = transceiver->internal()->channel(); const ContentInfo* content = FindMediaSectionForTransceiver(transceiver, sdesc); @@ -3923,7 +3883,7 @@ RTCError PeerConnection::PushdownMediaDescription( UpdatePayloadTypeDemuxingState(source); // Push down the new SDP media section for each audio/video transceiver. - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { const ContentInfo* content_info = FindMediaSectionForTransceiver(transceiver, sdesc); cricket::ChannelInterface* channel = transceiver->internal()->channel(); @@ -4099,7 +4059,7 @@ std::map PeerConnection::GetTransportNamesByMid() const { RTC_DCHECK_RUN_ON(signaling_thread()); std::map transport_names_by_mid; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { cricket::ChannelInterface* channel = transceiver->internal()->channel(); if (channel) { transport_names_by_mid[channel->content_name()] = @@ -4278,7 +4238,7 @@ void PeerConnection::OnTransportControllerDtlsHandshakeError( void PeerConnection::EnableSending() { RTC_DCHECK_RUN_ON(signaling_thread()); - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { cricket::ChannelInterface* channel = transceiver->internal()->channel(); if (channel && !channel->enabled()) { channel->Enable(true); @@ -4848,7 +4808,7 @@ void PeerConnection::OnTransportControllerGatheringState( void PeerConnection::ReportTransportStats() { std::map> media_types_by_transport_name; - for (const auto& transceiver : transceivers_) { + for (const auto& transceiver : transceivers_.List()) { if (transceiver->internal()->channel()) { const std::string& transport_name = transceiver->internal()->channel()->transport_name(); diff --git a/pc/peer_connection.h b/pc/peer_connection.h index d1fac2f879..e57920d4ca 100644 --- a/pc/peer_connection.h +++ b/pc/peer_connection.h @@ -34,6 +34,7 @@ #include "pc/sdp_offer_answer.h" #include "pc/stats_collector.h" #include "pc/stream_collection.h" +#include "pc/transceiver_list.h" #include "pc/webrtc_session_description_factory.h" #include "rtc_base/experiments/field_trial_parser.h" #include "rtc_base/operations_chain.h" @@ -288,7 +289,7 @@ class PeerConnection : public PeerConnectionInternal, rtc::scoped_refptr>> GetTransceiversInternal() const override { RTC_DCHECK_RUN_ON(signaling_thread()); - return transceivers_; + return transceivers_.List(); } sigslot::signal1& SignalRtpDataChannelCreated() override { @@ -400,37 +401,6 @@ class PeerConnection : public PeerConnectionInternal, uint32_t first_ssrc; }; - // Captures partial state to be used for rollback. Applicable only in - // Unified Plan. - class TransceiverStableState { - public: - TransceiverStableState() {} - void set_newly_created(); - void SetMSectionIfUnset(absl::optional mid, - absl::optional mline_index); - void SetRemoteStreamIdsIfUnset(const std::vector& ids); - absl::optional mid() const { return mid_; } - absl::optional mline_index() const { return mline_index_; } - absl::optional> remote_stream_ids() const { - return remote_stream_ids_; - } - bool has_m_section() const { return has_m_section_; } - bool newly_created() const { return newly_created_; } - - private: - absl::optional mid_; - absl::optional mline_index_; - absl::optional> remote_stream_ids_; - // Indicates that mid value from stable state has been captured and - // that rollback has to restore the transceiver. Also protects against - // subsequent overwrites. - bool has_m_section_ = false; - // Indicates that the transceiver was created as part of applying a - // description to track potential need for removing transceiver during - // rollback. - bool newly_created_ = false; - }; - // Implements MessageHandler. void OnMessage(rtc::Message* msg) override; @@ -1135,22 +1105,10 @@ class PeerConnection : public PeerConnectionInternal, RTC_GUARDED_BY(signaling_thread()); // A pointer is passed to senders_ rtc::scoped_refptr stats_collector_ RTC_GUARDED_BY(signaling_thread()); - // Holds changes made to transceivers during applying descriptors for - // potential rollback. Gets cleared once signaling state goes to stable. - std::map>, - TransceiverStableState> - transceiver_stable_states_by_transceivers_; // Used when rolling back RTP data channels. bool have_pending_rtp_data_channel_ RTC_GUARDED_BY(signaling_thread()) = false; - // Holds remote stream ids for transceivers from stable state. - std::map>, - std::vector> - remote_stream_ids_by_transceivers_; - std::vector< - rtc::scoped_refptr>> - transceivers_; // TODO(bugs.webrtc.org/9987): Accessed on both signaling - // and network thread. + TransceiverList transceivers_; // MIDs will be generated using this generator which will keep track of // all the MIDs that have been seen over the life of the PeerConnection. diff --git a/pc/sdp_offer_answer.cc b/pc/sdp_offer_answer.cc index 51bb4ed32c..03d3001402 100644 --- a/pc/sdp_offer_answer.cc +++ b/pc/sdp_offer_answer.cc @@ -946,7 +946,7 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription( } std::vector> remove_list; std::vector> removed_streams; - for (const auto& transceiver : pc_->transceivers_) { + for (const auto& transceiver : pc_->transceivers_.List()) { if (transceiver->stopped()) { continue; } @@ -1036,7 +1036,7 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription( } if (IsUnifiedPlan()) { - for (const auto& transceiver : pc_->transceivers_) { + for (const auto& transceiver : pc_->transceivers_.List()) { if (transceiver->stopped()) { continue; } @@ -1315,7 +1315,7 @@ RTCError SdpOfferAnswerHandler::ApplyRemoteDescription( std::vector> remove_list; std::vector> added_streams; std::vector> removed_streams; - for (const auto& transceiver : pc_->transceivers_) { + for (const auto& transceiver : pc_->transceivers_.List()) { const ContentInfo* content = pc_->FindMediaSectionForTransceiver( transceiver, remote_description()); if (!content) { @@ -1334,8 +1334,8 @@ RTCError SdpOfferAnswerHandler::ApplyRemoteDescription( // The remote description has signaled the stream IDs. stream_ids = media_desc->streams()[0].stream_ids(); } - pc_->transceiver_stable_states_by_transceivers_[transceiver] - .SetRemoteStreamIdsIfUnset(transceiver->receiver()->stream_ids()); + pc_->transceivers_.StableState(transceiver) + ->SetRemoteStreamIdsIfUnset(transceiver->receiver()->stream_ids()); RTC_LOG(LS_INFO) << "Processing the MSIDs for MID=" << content->name << " (" << GetStreamIdsString(stream_ids) << ")."; @@ -2142,7 +2142,7 @@ RTCError SdpOfferAnswerHandler::UpdateSessionState( RTC_DCHECK_RUN_ON(pc_->signaling_thread()); RTC_DCHECK(type == SdpType::kAnswer); ChangeSignalingState(PeerConnectionInterface::kStable); - pc_->transceiver_stable_states_by_transceivers_.clear(); + pc_->transceivers_.DiscardStableStates(); pc_->have_pending_rtp_data_channel_ = false; } @@ -2206,7 +2206,7 @@ RTCError SdpOfferAnswerHandler::Rollback(SdpType desc_type) { std::vector> removed_receivers; for (auto&& transceivers_stable_state_pair : - pc_->transceiver_stable_states_by_transceivers_) { + pc_->transceivers_.StableStates()) { auto transceiver = transceivers_stable_state_pair.first; auto state = transceivers_stable_state_pair.second; @@ -2237,13 +2237,7 @@ RTCError SdpOfferAnswerHandler::Rollback(SdpType desc_type) { if (transceiver->internal()->reused_for_addtrack()) { transceiver->internal()->set_created_by_addtrack(true); } else { - int remaining_transceiver_count = 0; - for (auto&& t : pc_->transceivers_) { - if (t != transceiver) { - pc_->transceivers_[remaining_transceiver_count++] = t; - } - } - pc_->transceivers_.resize(remaining_transceiver_count); + pc_->transceivers_.Remove(transceiver); } } transceiver->internal()->sender_internal()->set_transport(nullptr); @@ -2258,7 +2252,7 @@ RTCError SdpOfferAnswerHandler::Rollback(SdpType desc_type) { pc_->DestroyDataChannelTransport(); pc_->have_pending_rtp_data_channel_ = false; } - pc_->transceiver_stable_states_by_transceivers_.clear(); + pc_->transceivers_.DiscardStableStates(); } pending_local_description_.reset(); pending_remote_description_.reset(); @@ -2412,7 +2406,7 @@ bool SdpOfferAnswerHandler::CheckIfNegotiationIsNeeded() { // 5. For each transceiver in connection's set of transceivers, perform the // following checks: - for (const auto& transceiver : pc_->transceivers_) { + for (const auto& transceiver : pc_->transceivers_.List()) { const ContentInfo* current_local_msection = FindTransceiverMSection(transceiver.get(), description); @@ -2791,8 +2785,7 @@ SdpOfferAnswerHandler::AssociateTransceiver( transceiver->internal()->set_direction( RtpTransceiverDirection::kRecvOnly); if (type == SdpType::kOffer) { - pc_->transceiver_stable_states_by_transceivers_[transceiver] - .set_newly_created(); + pc_->transceivers_.StableState(transceiver)->set_newly_created(); } } // Check if the offer indicated simulcast but the answer rejected it. @@ -2831,9 +2824,9 @@ SdpOfferAnswerHandler::AssociateTransceiver( bool state_changes = transceiver->internal()->mid() != content.name || transceiver->internal()->mline_index() != mline_index; if (state_changes) { - pc_->transceiver_stable_states_by_transceivers_[transceiver] - .SetMSectionIfUnset(transceiver->internal()->mid(), - transceiver->internal()->mline_index()); + pc_->transceivers_.StableState(transceiver) + ->SetMSectionIfUnset(transceiver->internal()->mid(), + transceiver->internal()->mline_index()); } } // Associate the found or created RtpTransceiver with the m= section by diff --git a/pc/transceiver_list.cc b/pc/transceiver_list.cc new file mode 100644 index 0000000000..5fe148a222 --- /dev/null +++ b/pc/transceiver_list.cc @@ -0,0 +1,67 @@ +/* + * Copyright 2020 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "pc/transceiver_list.h" + +namespace webrtc { + +void TransceiverStableState::set_newly_created() { + RTC_DCHECK(!has_m_section_); + newly_created_ = true; +} + +void TransceiverStableState::SetMSectionIfUnset( + absl::optional mid, + absl::optional mline_index) { + if (!has_m_section_) { + mid_ = mid; + mline_index_ = mline_index; + has_m_section_ = true; + } +} + +void TransceiverStableState::SetRemoteStreamIdsIfUnset( + const std::vector& ids) { + if (!remote_stream_ids_.has_value()) { + remote_stream_ids_ = ids; + } +} + +RtpTransceiverProxyRefPtr TransceiverList::FindBySender( + rtc::scoped_refptr sender) const { + for (auto transceiver : transceivers_) { + if (transceiver->sender() == sender) { + return transceiver; + } + } + return nullptr; +} + +RtpTransceiverProxyRefPtr TransceiverList::FindByMid( + const std::string& mid) const { + for (auto transceiver : transceivers_) { + if (transceiver->mid() == mid) { + return transceiver; + } + } + return nullptr; +} + +RtpTransceiverProxyRefPtr TransceiverList::FindByMLineIndex( + size_t mline_index) const { + for (auto transceiver : transceivers_) { + if (transceiver->internal()->mline_index() == mline_index) { + return transceiver; + } + } + return nullptr; +} + +} // namespace webrtc diff --git a/pc/transceiver_list.h b/pc/transceiver_list.h new file mode 100644 index 0000000000..cd77d67f44 --- /dev/null +++ b/pc/transceiver_list.h @@ -0,0 +1,100 @@ +/* + * Copyright 2020 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#ifndef PC_TRANSCEIVER_LIST_H_ +#define PC_TRANSCEIVER_LIST_H_ + +#include +#include +#include +#include + +#include "pc/rtp_transceiver.h" + +namespace webrtc { + +typedef rtc::scoped_refptr> + RtpTransceiverProxyRefPtr; + +// Captures partial state to be used for rollback. Applicable only in +// Unified Plan. +class TransceiverStableState { + public: + TransceiverStableState() {} + void set_newly_created(); + void SetMSectionIfUnset(absl::optional mid, + absl::optional mline_index); + void SetRemoteStreamIdsIfUnset(const std::vector& ids); + absl::optional mid() const { return mid_; } + absl::optional mline_index() const { return mline_index_; } + absl::optional> remote_stream_ids() const { + return remote_stream_ids_; + } + bool has_m_section() const { return has_m_section_; } + bool newly_created() const { return newly_created_; } + + private: + absl::optional mid_; + absl::optional mline_index_; + absl::optional> remote_stream_ids_; + // Indicates that mid value from stable state has been captured and + // that rollback has to restore the transceiver. Also protects against + // subsequent overwrites. + bool has_m_section_ = false; + // Indicates that the transceiver was created as part of applying a + // description to track potential need for removing transceiver during + // rollback. + bool newly_created_ = false; +}; + +class TransceiverList { + public: + std::vector List() const { return transceivers_; } + + void Add(RtpTransceiverProxyRefPtr transceiver) { + transceivers_.push_back(transceiver); + } + void Remove(RtpTransceiverProxyRefPtr transceiver) { + transceivers_.erase( + std::remove(transceivers_.begin(), transceivers_.end(), transceiver), + transceivers_.end()); + } + RtpTransceiverProxyRefPtr FindBySender( + rtc::scoped_refptr sender) const; + RtpTransceiverProxyRefPtr FindByMid(const std::string& mid) const; + RtpTransceiverProxyRefPtr FindByMLineIndex(size_t mline_index) const; + + // Find or create the stable state for a transceiver. + TransceiverStableState* StableState(RtpTransceiverProxyRefPtr transceiver) { + return &(transceiver_stable_states_by_transceivers_[transceiver]); + } + + void DiscardStableStates() { + transceiver_stable_states_by_transceivers_.clear(); + } + + std::map& StableStates() { + return transceiver_stable_states_by_transceivers_; + } + + private: + std::vector transceivers_; + // Holds changes made to transceivers during applying descriptors for + // potential rollback. Gets cleared once signaling state goes to stable. + std::map + transceiver_stable_states_by_transceivers_; + // Holds remote stream ids for transceivers from stable state. + std::map> + remote_stream_ids_by_transceivers_; +}; + +} // namespace webrtc + +#endif // PC_TRANSCEIVER_LIST_H_