Factor out the transceiver list into a separate object.

This component is heavily referenced by both PeerConnection and
SdpOfferAnswerHandler; it's likely that it will end up in
SdpOfferAnswerHandler.

Encapsulation makes it easier to move around.

Bug: webrtc:11995
Change-Id: I5329d9a90159d203510bf3698962cd246eea7324
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/185880
Commit-Queue: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#32229}
This commit is contained in:
Harald Alvestrand 2020-09-29 11:54:05 +00:00 committed by Commit Bot
parent b6bc09b099
commit 38b768c588
6 changed files with 227 additions and 147 deletions

View File

@ -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",

View File

@ -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<std::string> mid,
absl::optional<size_t> mline_index) {
if (!has_m_section_) {
mid_ = mid;
mline_index_ = mline_index;
has_m_section_ = true;
}
}
void PeerConnection::TransceiverStableState::SetRemoteStreamIdsIfUnset(
const std::vector<std::string>& 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<RtpTransceiver>::Create(
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)));
transceivers_.push_back(
RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_VIDEO)));
transceivers_.Add(RtpTransceiverProxyWithInternal<RtpTransceiver>::Create(
signaling_thread(), new RtpTransceiver(cricket::MEDIA_TYPE_AUDIO)));
transceivers_.Add(RtpTransceiverProxyWithInternal<RtpTransceiver>::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<RtpTransceiverProxyWithInternal<RtpTransceiver>>
PeerConnection::FindFirstTransceiverForAddedTrack(
rtc::scoped_refptr<MediaStreamTrackInterface> 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<RtpTransceiverProxyWithInternal<RtpTransceiver>>
PeerConnection::FindTransceiverBySender(
rtc::scoped_refptr<RtpSenderInterface> sender) {
for (auto transceiver : transceivers_) {
if (transceiver->sender() == sender) {
return transceiver;
}
}
return nullptr;
return transceivers_.FindBySender(sender);
}
RTCErrorOr<rtc::scoped_refptr<RtpTransceiverInterface>>
@ -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<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
PeerConnection::GetSendersInternal() const {
std::vector<rtc::scoped_refptr<RtpSenderProxyWithInternal<RtpSenderInternal>>>
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<RtpReceiverProxyWithInternal<RtpReceiverInternal>>>
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<rtc::scoped_refptr<RtpTransceiverInterface>> 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<RtpSenderInternal> 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<RtpReceiverInternal> 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<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
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<RtpTransceiverProxyWithInternal<RtpTransceiver>>
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<RtpTransceiverProxyWithInternal<RtpTransceiver>>
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<RtpTransceiverProxyWithInternal<RtpTransceiver>>
@ -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<cricket::VideoMediaChannel*> 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<RtpTransceiverProxyWithInternal<RtpTransceiver>>
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<RtpSenderProxyWithInternal<RtpSenderInternal>>
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<RtpSenderProxyWithInternal<RtpSenderInternal>>
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<RtpReceiverProxyWithInternal<RtpReceiverInternal>>
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<std::pair<RtpTransceiverDirection, cricket::ChannelInterface*>>
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<std::string, std::string> PeerConnection::GetTransportNamesByMid()
const {
RTC_DCHECK_RUN_ON(signaling_thread());
std::map<std::string, std::string> 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<std::string, std::set<cricket::MediaType>>
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();

View File

@ -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<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
GetTransceiversInternal() const override {
RTC_DCHECK_RUN_ON(signaling_thread());
return transceivers_;
return transceivers_.List();
}
sigslot::signal1<RtpDataChannel*>& 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<std::string> mid,
absl::optional<size_t> mline_index);
void SetRemoteStreamIdsIfUnset(const std::vector<std::string>& ids);
absl::optional<std::string> mid() const { return mid_; }
absl::optional<size_t> mline_index() const { return mline_index_; }
absl::optional<std::vector<std::string>> 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<std::string> mid_;
absl::optional<size_t> mline_index_;
absl::optional<std::vector<std::string>> 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<RTCStatsCollector> 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<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>,
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<rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>,
std::vector<std::string>>
remote_stream_ids_by_transceivers_;
std::vector<
rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>>
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.

View File

@ -946,7 +946,7 @@ RTCError SdpOfferAnswerHandler::ApplyLocalDescription(
}
std::vector<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> 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<rtc::scoped_refptr<RtpTransceiverInterface>> remove_list;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> added_streams;
std::vector<rtc::scoped_refptr<MediaStreamInterface>> 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<rtc::scoped_refptr<RtpReceiverInterface>> 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

67
pc/transceiver_list.cc Normal file
View File

@ -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<std::string> mid,
absl::optional<size_t> mline_index) {
if (!has_m_section_) {
mid_ = mid;
mline_index_ = mline_index;
has_m_section_ = true;
}
}
void TransceiverStableState::SetRemoteStreamIdsIfUnset(
const std::vector<std::string>& ids) {
if (!remote_stream_ids_.has_value()) {
remote_stream_ids_ = ids;
}
}
RtpTransceiverProxyRefPtr TransceiverList::FindBySender(
rtc::scoped_refptr<RtpSenderInterface> 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

100
pc/transceiver_list.h Normal file
View File

@ -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 <algorithm>
#include <map>
#include <string>
#include <vector>
#include "pc/rtp_transceiver.h"
namespace webrtc {
typedef rtc::scoped_refptr<RtpTransceiverProxyWithInternal<RtpTransceiver>>
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<std::string> mid,
absl::optional<size_t> mline_index);
void SetRemoteStreamIdsIfUnset(const std::vector<std::string>& ids);
absl::optional<std::string> mid() const { return mid_; }
absl::optional<size_t> mline_index() const { return mline_index_; }
absl::optional<std::vector<std::string>> 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<std::string> mid_;
absl::optional<size_t> mline_index_;
absl::optional<std::vector<std::string>> 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<RtpTransceiverProxyRefPtr> 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<RtpSenderInterface> 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<RtpTransceiverProxyRefPtr, TransceiverStableState>& StableStates() {
return transceiver_stable_states_by_transceivers_;
}
private:
std::vector<RtpTransceiverProxyRefPtr> transceivers_;
// Holds changes made to transceivers during applying descriptors for
// potential rollback. Gets cleared once signaling state goes to stable.
std::map<RtpTransceiverProxyRefPtr, TransceiverStableState>
transceiver_stable_states_by_transceivers_;
// Holds remote stream ids for transceivers from stable state.
std::map<RtpTransceiverProxyRefPtr, std::vector<std::string>>
remote_stream_ids_by_transceivers_;
};
} // namespace webrtc
#endif // PC_TRANSCEIVER_LIST_H_