From 4171afb1865adb374e7529f41292347cd4deb0ab Mon Sep 17 00:00:00 2001 From: Steve Anton Date: Mon, 20 Nov 2017 10:20:22 -0800 Subject: [PATCH] Use RtpTransceivers in PeerConnection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Moves ownership of the RtpSenders/RtpReceivers/BaseChannels to RtpTransceiver objects. For now, there can only be one RtpTransceiver for audio and one for video. Future work to implement Unified Plan will relax this restriction. Bug: webrtc:7600 Change-Id: I9dfe324de61e2b363948858da72624396e27fc1a Reviewed-on: https://webrtc-review.googlesource.com/21461 Commit-Queue: Steve Anton Reviewed-by: Peter Thatcher Reviewed-by: Henrik Boström Cr-Commit-Position: refs/heads/master@{#20802} --- pc/peerconnection.cc | 659 ++++++++++++++++++---------------- pc/peerconnection.h | 180 +++++----- pc/test/mock_peerconnection.h | 4 +- 3 files changed, 438 insertions(+), 405 deletions(-) diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc index e8857a39df..d617c715d0 100644 --- a/pc/peerconnection.cc +++ b/pc/peerconnection.cc @@ -91,8 +91,8 @@ const char kEnableBundleFailed[] = "Failed to enable BUNDLE."; namespace { static const char kDefaultStreamLabel[] = "default"; -static const char kDefaultAudioTrackLabel[] = "defaulta0"; -static const char kDefaultVideoTrackLabel[] = "defaultv0"; +static const char kDefaultAudioSenderId[] = "defaulta0"; +static const char kDefaultVideoSenderId[] = "defaultv0"; // The length of RTCP CNAMEs. static const int kRtcpCnameLength = 16; @@ -227,34 +227,6 @@ uint32_t ConvertIceTransportTypeToCandidateFilter( return cricket::CF_NONE; } -// Helper method to set a voice/video channel on all applicable senders -// and receivers when one is created/destroyed by PeerConnection. -// -// Used by On(Voice|Video)Channel(Created|Destroyed) -template -void SetChannelOnSendersAndReceivers(CHANNEL* channel, - const SENDERS& senders, - const RECEIVERS& receivers, - cricket::MediaType media_type) { - for (auto& sender : senders) { - if (sender->media_type() == media_type) { - static_cast(sender->internal())->SetChannel(channel); - } - } - for (auto& receiver : receivers) { - if (receiver->media_type() == media_type) { - if (!channel) { - receiver->internal()->Stop(); - } - static_cast(receiver->internal())->SetChannel(channel); - } - } -} - // Helper to set an error and return from a method. bool SafeSetError(webrtc::RTCErrorType type, webrtc::RTCError* error) { if (error) { @@ -827,15 +799,14 @@ PeerConnection::PeerConnection(PeerConnectionFactory* factory, PeerConnection::~PeerConnection() { TRACE_EVENT0("webrtc", "PeerConnection::~PeerConnection"); - RTC_DCHECK(signaling_thread()->IsCurrent()); - // Need to detach RTP senders/receivers from PeerConnection, - // since it's about to be destroyed. - for (const auto& sender : senders_) { - sender->internal()->Stop(); - } - for (const auto& receiver : receivers_) { - receiver->internal()->Stop(); + RTC_DCHECK_RUN_ON(signaling_thread()); + + // Need to detach RTP transceivers from PeerConnection, since it's about to be + // destroyed. + for (auto transceiver : transceivers_) { + transceiver->Stop(); } + // Destroy stats_ because it depends on session_. stats_.reset(nullptr); if (stats_collector_) { @@ -845,11 +816,19 @@ PeerConnection::~PeerConnection() { // Destroy video channels first since they may have a pointer to a voice // channel. - for (auto* channel : video_channels_) { - DestroyVideoChannel(channel); + for (auto transceiver : transceivers_) { + if (transceiver->internal()->media_type() == cricket::MEDIA_TYPE_VIDEO && + transceiver->internal()->channel()) { + DestroyVideoChannel(static_cast( + transceiver->internal()->channel())); + } } - for (auto* channel : voice_channels_) { - DestroyVoiceChannel(channel); + for (auto transceiver : transceivers_) { + if (transceiver->internal()->media_type() == cricket::MEDIA_TYPE_AUDIO && + transceiver->internal()->channel()) { + DestroyVoiceChannel(static_cast( + transceiver->internal()->channel())); + } } if (rtp_data_channel_) { DestroyDataChannel(); @@ -1019,6 +998,16 @@ bool PeerConnection::Initialize( webrtc_session_desc_factory_->set_enable_encrypted_rtp_header_extensions( options.crypto_options.enable_encrypted_rtp_header_extensions); + // 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))); + } + return true; } @@ -1114,8 +1103,7 @@ rtc::scoped_refptr PeerConnection::AddTrack( << "Adding a track with two streams is not currently supported."; return nullptr; } - // TODO(deadbeef): Support adding a track to two different senders. - if (FindSenderForTrack(track) != senders_.end()) { + if (FindSenderForTrack(track)) { RTC_LOG(LS_ERROR) << "Sender for track " << track->id() << " already exists."; return nullptr; @@ -1128,26 +1116,30 @@ rtc::scoped_refptr PeerConnection::AddTrack( signaling_thread(), new AudioRtpSender(static_cast(track), voice_channel(), stats_.get())); + GetAudioTransceiver()->internal()->AddSender(new_sender); if (!streams.empty()) { new_sender->internal()->set_stream_id(streams[0]->label()); } - const TrackInfo* track_info = FindTrackInfo( - local_audio_tracks_, new_sender->internal()->stream_id(), track->id()); - if (track_info) { - new_sender->internal()->SetSsrc(track_info->ssrc); + const RtpSenderInfo* sender_info = + FindSenderInfo(local_audio_sender_infos_, + new_sender->internal()->stream_id(), track->id()); + if (sender_info) { + new_sender->internal()->SetSsrc(sender_info->first_ssrc); } } else if (track->kind() == MediaStreamTrackInterface::kVideoKind) { new_sender = RtpSenderProxyWithInternal::Create( signaling_thread(), new VideoRtpSender(static_cast(track), video_channel())); + GetVideoTransceiver()->internal()->AddSender(new_sender); if (!streams.empty()) { new_sender->internal()->set_stream_id(streams[0]->label()); } - const TrackInfo* track_info = FindTrackInfo( - local_video_tracks_, new_sender->internal()->stream_id(), track->id()); - if (track_info) { - new_sender->internal()->SetSsrc(track_info->ssrc); + const RtpSenderInfo* sender_info = + FindSenderInfo(local_video_sender_infos_, + new_sender->internal()->stream_id(), track->id()); + if (sender_info) { + new_sender->internal()->SetSsrc(sender_info->first_ssrc); } } else { RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " @@ -1155,7 +1147,6 @@ rtc::scoped_refptr PeerConnection::AddTrack( return rtc::scoped_refptr(); } - senders_.push_back(new_sender); observer_->OnRenegotiationNeeded(); return new_sender; } @@ -1166,14 +1157,18 @@ bool PeerConnection::RemoveTrack(RtpSenderInterface* sender) { return false; } - auto it = std::find(senders_.begin(), senders_.end(), sender); - if (it == senders_.end()) { + bool removed; + if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) { + removed = GetAudioTransceiver()->internal()->RemoveSender(sender); + } else { + RTC_DCHECK_EQ(cricket::MEDIA_TYPE_VIDEO, sender->media_type()); + removed = GetVideoTransceiver()->internal()->RemoveSender(sender); + } + if (!removed) { RTC_LOG(LS_ERROR) << "Couldn't find sender " << sender->id() << " to remove."; return false; } - (*it)->internal()->Stop(); - senders_.erase(it); observer_->OnRenegotiationNeeded(); return true; @@ -1189,13 +1184,13 @@ rtc::scoped_refptr PeerConnection::CreateDtmfSender( RTC_LOG(LS_ERROR) << "CreateDtmfSender - track is NULL."; return nullptr; } - auto it = FindSenderForTrack(track); - if (it == senders_.end()) { + auto track_sender = FindSenderForTrack(track); + if (!track_sender) { RTC_LOG(LS_ERROR) << "CreateDtmfSender called with a non-added track."; return nullptr; } - return (*it)->GetDtmfSender(); + return track_sender->GetDtmfSender(); } rtc::scoped_refptr PeerConnection::CreateSender( @@ -1205,42 +1200,72 @@ rtc::scoped_refptr PeerConnection::CreateSender( if (IsClosed()) { return nullptr; } + + // TODO(steveanton): Move construction of the RtpSenders to RtpTransceiver. rtc::scoped_refptr> new_sender; if (kind == MediaStreamTrackInterface::kAudioKind) { new_sender = RtpSenderProxyWithInternal::Create( signaling_thread(), new AudioRtpSender(voice_channel(), stats_.get())); + GetAudioTransceiver()->internal()->AddSender(new_sender); } else if (kind == MediaStreamTrackInterface::kVideoKind) { new_sender = RtpSenderProxyWithInternal::Create( signaling_thread(), new VideoRtpSender(video_channel())); + GetVideoTransceiver()->internal()->AddSender(new_sender); } else { RTC_LOG(LS_ERROR) << "CreateSender called with invalid kind: " << kind; - return new_sender; + return nullptr; } + if (!stream_id.empty()) { new_sender->internal()->set_stream_id(stream_id); } - senders_.push_back(new_sender); + return new_sender; } std::vector> PeerConnection::GetSenders() const { std::vector> ret; - for (const auto& sender : senders_) { - ret.push_back(sender.get()); + for (auto sender : GetSendersInternal()) { + ret.push_back(sender); } return ret; } +std::vector>> +PeerConnection::GetSendersInternal() const { + std::vector>> + all_senders; + for (auto transceiver : transceivers_) { + auto senders = transceiver->internal()->senders(); + all_senders.insert(all_senders.end(), senders.begin(), senders.end()); + } + return all_senders; +} + std::vector> PeerConnection::GetReceivers() const { std::vector> ret; - for (const auto& receiver : receivers_) { - ret.push_back(receiver.get()); + for (const auto& receiver : GetReceiversInternal()) { + ret.push_back(receiver); } return ret; } +std::vector< + rtc::scoped_refptr>> +PeerConnection::GetReceiversInternal() const { + std::vector< + rtc::scoped_refptr>> + all_receivers; + for (auto transceiver : transceivers_) { + auto receivers = transceiver->internal()->receivers(); + all_receivers.insert(all_receivers.end(), receivers.begin(), + receivers.end()); + } + return all_receivers; +} + bool PeerConnection::GetStats(StatsObserver* observer, MediaStreamTrackInterface* track, StatsOutputLevel level) { @@ -1455,12 +1480,12 @@ void PeerConnection::SetLocalDescription( GetFirstAudioContent(local_description()->description()); if (audio_content) { if (audio_content->rejected) { - RemoveTracks(cricket::MEDIA_TYPE_AUDIO); + RemoveSenders(cricket::MEDIA_TYPE_AUDIO); } else { const cricket::AudioContentDescription* audio_desc = static_cast( audio_content->description); - UpdateLocalTracks(audio_desc->streams(), audio_desc->type()); + UpdateLocalSenders(audio_desc->streams(), audio_desc->type()); } } @@ -1468,12 +1493,12 @@ void PeerConnection::SetLocalDescription( GetFirstVideoContent(local_description()->description()); if (video_content) { if (video_content->rejected) { - RemoveTracks(cricket::MEDIA_TYPE_VIDEO); + RemoveSenders(cricket::MEDIA_TYPE_VIDEO); } else { const cricket::VideoContentDescription* video_desc = static_cast( video_content->description); - UpdateLocalTracks(video_desc->streams(), video_desc->type()); + UpdateLocalSenders(video_desc->streams(), video_desc->type()); } } @@ -1583,19 +1608,19 @@ void PeerConnection::SetRemoteDescription( // rejected media section, there is some cleanup logic that expects the voice/ // video channel to still be set. But in this method the voice/video channel // would have been destroyed by the SetRemoteDescription caller above so the - // cleanup that relies on them fails to run. The RemoveTracks calls should be + // cleanup that relies on them fails to run. The RemoveSenders calls should be // moved to right before the DestroyChannel calls to fix this. // Find all audio rtp streams and create corresponding remote AudioTracks // and MediaStreams. if (audio_content) { if (audio_content->rejected) { - RemoveTracks(cricket::MEDIA_TYPE_AUDIO); + RemoveSenders(cricket::MEDIA_TYPE_AUDIO); } else { bool default_audio_track_needed = !remote_peer_supports_msid_ && MediaContentDirectionHasSend(audio_desc->direction()); - UpdateRemoteStreamsList(GetActiveStreams(audio_desc), + UpdateRemoteSendersList(GetActiveStreams(audio_desc), default_audio_track_needed, audio_desc->type(), new_streams); } @@ -1605,12 +1630,12 @@ void PeerConnection::SetRemoteDescription( // and MediaStreams. if (video_content) { if (video_content->rejected) { - RemoveTracks(cricket::MEDIA_TYPE_VIDEO); + RemoveSenders(cricket::MEDIA_TYPE_VIDEO); } else { bool default_video_track_needed = !remote_peer_supports_msid_ && MediaContentDirectionHasSend(video_desc->direction()); - UpdateRemoteStreamsList(GetActiveStreams(video_desc), + UpdateRemoteSendersList(GetActiveStreams(video_desc), default_video_track_needed, video_desc->type(), new_streams); } @@ -1987,8 +2012,8 @@ void PeerConnection::Close() { ChangeSignalingState(PeerConnectionInterface::kClosed); RemoveUnusedChannels(nullptr); - RTC_DCHECK(voice_channels_.empty()); - RTC_DCHECK(video_channels_.empty()); + RTC_DCHECK(!GetAudioTransceiver()->internal()->channel()); + RTC_DCHECK(!GetVideoTransceiver()->internal()->channel()); RTC_DCHECK(!rtp_data_channel_); RTC_DCHECK(!sctp_transport_); @@ -2045,31 +2070,33 @@ void PeerConnection::OnMessage(rtc::Message* msg) { } } -void PeerConnection::CreateAudioReceiver(MediaStreamInterface* stream, - const std::string& track_id, - uint32_t ssrc) { +void PeerConnection::CreateAudioReceiver( + MediaStreamInterface* stream, + const RtpSenderInfo& remote_sender_info) { rtc::scoped_refptr> receiver = RtpReceiverProxyWithInternal::Create( signaling_thread(), - new AudioRtpReceiver(track_id, ssrc, voice_channel())); + new AudioRtpReceiver(remote_sender_info.sender_id, + remote_sender_info.first_ssrc, voice_channel())); stream->AddTrack( static_cast(receiver->internal()->track().get())); - receivers_.push_back(receiver); + GetAudioTransceiver()->internal()->AddReceiver(receiver); std::vector> streams; streams.push_back(rtc::scoped_refptr(stream)); observer_->OnAddTrack(receiver, streams); } -void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream, - const std::string& track_id, - uint32_t ssrc) { +void PeerConnection::CreateVideoReceiver( + MediaStreamInterface* stream, + const RtpSenderInfo& remote_sender_info) { rtc::scoped_refptr> receiver = RtpReceiverProxyWithInternal::Create( - signaling_thread(), new VideoRtpReceiver(track_id, worker_thread(), - ssrc, video_channel())); + signaling_thread(), + new VideoRtpReceiver(remote_sender_info.sender_id, worker_thread(), + remote_sender_info.first_ssrc, video_channel())); stream->AddTrack( static_cast(receiver->internal()->track().get())); - receivers_.push_back(receiver); + GetVideoTransceiver()->internal()->AddReceiver(receiver); std::vector> streams; streams.push_back(rtc::scoped_refptr(stream)); observer_->OnAddTrack(receiver, streams); @@ -2078,16 +2105,18 @@ void PeerConnection::CreateVideoReceiver(MediaStreamInterface* stream, // TODO(deadbeef): Keep RtpReceivers around even if track goes away in remote // description. rtc::scoped_refptr PeerConnection::RemoveAndStopReceiver( - const std::string& track_id) { - auto it = FindReceiverForTrack(track_id); - if (it == receivers_.end()) { - RTC_LOG(LS_WARNING) << "RtpReceiver for track with id " << track_id - << " doesn't exist."; + const RtpSenderInfo& remote_sender_info) { + auto receiver = FindReceiverById(remote_sender_info.sender_id); + if (!receiver) { + RTC_LOG(LS_WARNING) << "RtpReceiver for track with id " + << remote_sender_info.sender_id << " doesn't exist."; return nullptr; } - (*it)->internal()->Stop(); - rtc::scoped_refptr receiver = *it; - receivers_.erase(it); + if (receiver->media_type() == cricket::MEDIA_TYPE_AUDIO) { + GetAudioTransceiver()->internal()->RemoveReceiver(receiver); + } else { + GetVideoTransceiver()->internal()->RemoveReceiver(receiver); + } return receiver; } @@ -2095,10 +2124,10 @@ void PeerConnection::AddAudioTrack(AudioTrackInterface* track, MediaStreamInterface* stream) { RTC_DCHECK(!IsClosed()); auto sender = FindSenderForTrack(track); - if (sender != senders_.end()) { + if (sender) { // We already have a sender for this track, so just change the stream_id // so that it's correct in the next call to CreateOffer. - (*sender)->internal()->set_stream_id(stream->label()); + sender->internal()->set_stream_id(stream->label()); return; } @@ -2108,17 +2137,17 @@ void PeerConnection::AddAudioTrack(AudioTrackInterface* track, signaling_thread(), new AudioRtpSender(track, {stream->label()}, voice_channel(), stats_.get())); - senders_.push_back(new_sender); + GetAudioTransceiver()->internal()->AddSender(new_sender); // If the sender has already been configured in SDP, we call SetSsrc, // which will connect the sender to the underlying transport. This can // occur if a local session description that contains the ID of the sender // is set before AddStream is called. It can also occur if the local // session description is not changed and RemoveStream is called, and // later AddStream is called again with the same stream. - const TrackInfo* track_info = - FindTrackInfo(local_audio_tracks_, stream->label(), track->id()); - if (track_info) { - new_sender->internal()->SetSsrc(track_info->ssrc); + const RtpSenderInfo* sender_info = + FindSenderInfo(local_audio_sender_infos_, stream->label(), track->id()); + if (sender_info) { + new_sender->internal()->SetSsrc(sender_info->first_ssrc); } } @@ -2128,23 +2157,22 @@ void PeerConnection::RemoveAudioTrack(AudioTrackInterface* track, MediaStreamInterface* stream) { RTC_DCHECK(!IsClosed()); auto sender = FindSenderForTrack(track); - if (sender == senders_.end()) { + if (!sender) { RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id() << " doesn't exist."; return; } - (*sender)->internal()->Stop(); - senders_.erase(sender); + GetAudioTransceiver()->internal()->RemoveSender(sender); } void PeerConnection::AddVideoTrack(VideoTrackInterface* track, MediaStreamInterface* stream) { RTC_DCHECK(!IsClosed()); auto sender = FindSenderForTrack(track); - if (sender != senders_.end()) { + if (sender) { // We already have a sender for this track, so just change the stream_id // so that it's correct in the next call to CreateOffer. - (*sender)->internal()->set_stream_id(stream->label()); + sender->internal()->set_stream_id(stream->label()); return; } @@ -2153,11 +2181,11 @@ void PeerConnection::AddVideoTrack(VideoTrackInterface* track, RtpSenderProxyWithInternal::Create( signaling_thread(), new VideoRtpSender(track, {stream->label()}, video_channel())); - senders_.push_back(new_sender); - const TrackInfo* track_info = - FindTrackInfo(local_video_tracks_, stream->label(), track->id()); - if (track_info) { - new_sender->internal()->SetSsrc(track_info->ssrc); + GetVideoTransceiver()->internal()->AddSender(new_sender); + const RtpSenderInfo* sender_info = + FindSenderInfo(local_video_sender_infos_, stream->label(), track->id()); + if (sender_info) { + new_sender->internal()->SetSsrc(sender_info->first_ssrc); } } @@ -2165,13 +2193,12 @@ void PeerConnection::RemoveVideoTrack(VideoTrackInterface* track, MediaStreamInterface* stream) { RTC_DCHECK(!IsClosed()); auto sender = FindSenderForTrack(track); - if (sender == senders_.end()) { + if (!sender) { RTC_LOG(LS_WARNING) << "RtpSender for track with id " << track->id() << " doesn't exist."; return; } - (*sender)->internal()->Stop(); - senders_.erase(sender); + GetVideoTransceiver()->internal()->RemoveSender(sender); } void PeerConnection::SetIceConnectionState(IceConnectionState new_state) { @@ -2386,7 +2413,7 @@ void PeerConnection::GetOptionsForOffer( configuration_.enable_ice_renomination; } - AddRtpSenderOptions(senders_, audio_media_description_options, + AddRtpSenderOptions(GetSendersInternal(), audio_media_description_options, video_media_description_options); AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options); @@ -2458,7 +2485,7 @@ void PeerConnection::GetOptionsForAnswer( configuration_.enable_ice_renomination; } - AddRtpSenderOptions(senders_, audio_media_description_options, + AddRtpSenderOptions(GetSendersInternal(), audio_media_description_options, video_media_description_options); AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options); @@ -2536,43 +2563,45 @@ void PeerConnection::GenerateMediaDescriptionOptions( } } -void PeerConnection::RemoveTracks(cricket::MediaType media_type) { - UpdateLocalTracks(std::vector(), media_type); - UpdateRemoteStreamsList(std::vector(), false, +void PeerConnection::RemoveSenders(cricket::MediaType media_type) { + UpdateLocalSenders(std::vector(), media_type); + UpdateRemoteSendersList(std::vector(), false, media_type, nullptr); } -void PeerConnection::UpdateRemoteStreamsList( +void PeerConnection::UpdateRemoteSendersList( const cricket::StreamParamsVec& streams, - bool default_track_needed, + bool default_sender_needed, cricket::MediaType media_type, StreamCollection* new_streams) { - TrackInfos* current_tracks = GetRemoteTracks(media_type); + std::vector* current_senders = + GetRemoteSenderInfos(media_type); - // Find removed tracks. I.e., tracks where the track id or ssrc don't match + // Find removed senders. I.e., senders where the sender id or ssrc don't match // the new StreamParam. - auto track_it = current_tracks->begin(); - while (track_it != current_tracks->end()) { - const TrackInfo& info = *track_it; + for (auto sender_it = current_senders->begin(); + sender_it != current_senders->end(); + /* incremented manually */) { + const RtpSenderInfo& info = *sender_it; const cricket::StreamParams* params = - cricket::GetStreamBySsrc(streams, info.ssrc); - bool track_exists = params && params->id == info.track_id; + cricket::GetStreamBySsrc(streams, info.first_ssrc); + bool sender_exists = params && params->id == info.sender_id; // If this is a default track, and we still need it, don't remove it. - if ((info.stream_label == kDefaultStreamLabel && default_track_needed) || - track_exists) { - ++track_it; + if ((info.stream_label == kDefaultStreamLabel && default_sender_needed) || + sender_exists) { + ++sender_it; } else { - OnRemoteTrackRemoved(info.stream_label, info.track_id, media_type); - track_it = current_tracks->erase(track_it); + OnRemoteSenderRemoved(info, media_type); + sender_it = current_senders->erase(sender_it); } } - // Find new and active tracks. + // Find new and active senders. for (const cricket::StreamParams& params : streams) { // The sync_label is the MediaStream label and the |stream.id| is the - // track id. + // sender id. const std::string& stream_label = params.sync_label; - const std::string& track_id = params.id; + const std::string& sender_id = params.id; uint32_t ssrc = params.first_ssrc(); rtc::scoped_refptr stream = @@ -2585,16 +2614,16 @@ void PeerConnection::UpdateRemoteStreamsList( new_streams->AddStream(stream); } - const TrackInfo* track_info = - FindTrackInfo(*current_tracks, stream_label, track_id); - if (!track_info) { - current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); - OnRemoteTrackSeen(stream_label, track_id, ssrc, media_type); + const RtpSenderInfo* sender_info = + FindSenderInfo(*current_senders, stream_label, sender_id); + if (!sender_info) { + current_senders->push_back(RtpSenderInfo(stream_label, sender_id, ssrc)); + OnRemoteSenderAdded(current_senders->back(), media_type); } } - // Add default track if necessary. - if (default_track_needed) { + // Add default sender if necessary. + if (default_sender_needed) { rtc::scoped_refptr default_stream = remote_streams_->find(kDefaultStreamLabel); if (!default_stream) { @@ -2604,55 +2633,54 @@ void PeerConnection::UpdateRemoteStreamsList( remote_streams_->AddStream(default_stream); new_streams->AddStream(default_stream); } - std::string default_track_id = (media_type == cricket::MEDIA_TYPE_AUDIO) - ? kDefaultAudioTrackLabel - : kDefaultVideoTrackLabel; - const TrackInfo* default_track_info = - FindTrackInfo(*current_tracks, kDefaultStreamLabel, default_track_id); - if (!default_track_info) { - current_tracks->push_back( - TrackInfo(kDefaultStreamLabel, default_track_id, 0)); - OnRemoteTrackSeen(kDefaultStreamLabel, default_track_id, 0, media_type); + std::string default_sender_id = (media_type == cricket::MEDIA_TYPE_AUDIO) + ? kDefaultAudioSenderId + : kDefaultVideoSenderId; + const RtpSenderInfo* default_sender_info = FindSenderInfo( + *current_senders, kDefaultStreamLabel, default_sender_id); + if (!default_sender_info) { + current_senders->push_back( + RtpSenderInfo(kDefaultStreamLabel, default_sender_id, 0)); + OnRemoteSenderAdded(current_senders->back(), media_type); } } } -void PeerConnection::OnRemoteTrackSeen(const std::string& stream_label, - const std::string& track_id, - uint32_t ssrc, - cricket::MediaType media_type) { - MediaStreamInterface* stream = remote_streams_->find(stream_label); +void PeerConnection::OnRemoteSenderAdded(const RtpSenderInfo& sender_info, + cricket::MediaType media_type) { + MediaStreamInterface* stream = + remote_streams_->find(sender_info.stream_label); if (media_type == cricket::MEDIA_TYPE_AUDIO) { - CreateAudioReceiver(stream, track_id, ssrc); + CreateAudioReceiver(stream, sender_info); } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { - CreateVideoReceiver(stream, track_id, ssrc); + CreateVideoReceiver(stream, sender_info); } else { RTC_NOTREACHED() << "Invalid media type"; } } -void PeerConnection::OnRemoteTrackRemoved(const std::string& stream_label, - const std::string& track_id, - cricket::MediaType media_type) { - MediaStreamInterface* stream = remote_streams_->find(stream_label); +void PeerConnection::OnRemoteSenderRemoved(const RtpSenderInfo& sender_info, + cricket::MediaType media_type) { + MediaStreamInterface* stream = + remote_streams_->find(sender_info.stream_label); rtc::scoped_refptr receiver; if (media_type == cricket::MEDIA_TYPE_AUDIO) { // When the MediaEngine audio channel is destroyed, the RemoteAudioSource // will be notified which will end the AudioRtpReceiver::track(). - receiver = RemoveAndStopReceiver(track_id); + receiver = RemoveAndStopReceiver(sender_info); rtc::scoped_refptr audio_track = - stream->FindAudioTrack(track_id); + stream->FindAudioTrack(sender_info.sender_id); if (audio_track) { stream->RemoveTrack(audio_track); } } else if (media_type == cricket::MEDIA_TYPE_VIDEO) { // Stopping or destroying a VideoRtpReceiver will end the // VideoRtpReceiver::track(). - receiver = RemoveAndStopReceiver(track_id); + receiver = RemoveAndStopReceiver(sender_info); rtc::scoped_refptr video_track = - stream->FindVideoTrack(track_id); + stream->FindVideoTrack(sender_info.sender_id); if (video_track) { // There's no guarantee the track is still available, e.g. the track may // have been removed from the stream by an application. @@ -2681,51 +2709,50 @@ void PeerConnection::UpdateEndedRemoteMediaStreams() { } } -void PeerConnection::UpdateLocalTracks( +void PeerConnection::UpdateLocalSenders( const std::vector& streams, cricket::MediaType media_type) { - TrackInfos* current_tracks = GetLocalTracks(media_type); + std::vector* current_senders = GetLocalSenderInfos(media_type); // Find removed tracks. I.e., tracks where the track id, stream label or ssrc // don't match the new StreamParam. - TrackInfos::iterator track_it = current_tracks->begin(); - while (track_it != current_tracks->end()) { - const TrackInfo& info = *track_it; + for (auto sender_it = current_senders->begin(); + sender_it != current_senders->end(); + /* incremented manually */) { + const RtpSenderInfo& info = *sender_it; const cricket::StreamParams* params = - cricket::GetStreamBySsrc(streams, info.ssrc); - if (!params || params->id != info.track_id || + cricket::GetStreamBySsrc(streams, info.first_ssrc); + if (!params || params->id != info.sender_id || params->sync_label != info.stream_label) { - OnLocalTrackRemoved(info.stream_label, info.track_id, info.ssrc, - media_type); - track_it = current_tracks->erase(track_it); + OnLocalSenderRemoved(info, media_type); + sender_it = current_senders->erase(sender_it); } else { - ++track_it; + ++sender_it; } } - // Find new and active tracks. + // Find new and active senders. for (const cricket::StreamParams& params : streams) { // The sync_label is the MediaStream label and the |stream.id| is the - // track id. + // sender id. const std::string& stream_label = params.sync_label; - const std::string& track_id = params.id; + const std::string& sender_id = params.id; uint32_t ssrc = params.first_ssrc(); - const TrackInfo* track_info = - FindTrackInfo(*current_tracks, stream_label, track_id); - if (!track_info) { - current_tracks->push_back(TrackInfo(stream_label, track_id, ssrc)); - OnLocalTrackSeen(stream_label, track_id, params.first_ssrc(), media_type); + const RtpSenderInfo* sender_info = + FindSenderInfo(*current_senders, stream_label, sender_id); + if (!sender_info) { + current_senders->push_back(RtpSenderInfo(stream_label, sender_id, ssrc)); + OnLocalSenderAdded(current_senders->back(), media_type); } } } -void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, - const std::string& track_id, - uint32_t ssrc, - cricket::MediaType media_type) { - RtpSenderInternal* sender = FindSenderById(track_id); +void PeerConnection::OnLocalSenderAdded(const RtpSenderInfo& sender_info, + cricket::MediaType media_type) { + auto sender = FindSenderById(sender_info.sender_id); if (!sender) { - RTC_LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id + RTC_LOG(LS_WARNING) << "An unknown RtpSender with id " + << sender_info.sender_id << " has been configured in the local description."; return; } @@ -2736,15 +2763,13 @@ void PeerConnection::OnLocalTrackSeen(const std::string& stream_label, return; } - sender->set_stream_id(stream_label); - sender->SetSsrc(ssrc); + sender->internal()->set_stream_id(sender_info.stream_label); + sender->internal()->SetSsrc(sender_info.first_ssrc); } -void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, - const std::string& track_id, - uint32_t ssrc, - cricket::MediaType media_type) { - RtpSenderInternal* sender = FindSenderById(track_id); +void PeerConnection::OnLocalSenderRemoved(const RtpSenderInfo& sender_info, + cricket::MediaType media_type) { + auto sender = FindSenderById(sender_info.sender_id); if (!sender) { // This is the normal case. I.e., RemoveStream has been called and the // SessionDescriptions has been renegotiated. @@ -2760,7 +2785,7 @@ void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label, return; } - sender->SetSsrc(0); + sender->internal()->SetSsrc(0); } void PeerConnection::UpdateLocalRtpDataChannels( @@ -2975,71 +3000,110 @@ void PeerConnection::OnDataChannelOpenMessage( observer_->OnDataChannel(std::move(proxy_channel)); } +rtc::scoped_refptr> +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_) { + if (transceiver->internal()->media_type() == cricket::MEDIA_TYPE_AUDIO) { + return transceiver; + } + } + RTC_NOTREACHED(); + return nullptr; +} + +rtc::scoped_refptr> +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_) { + if (transceiver->internal()->media_type() == cricket::MEDIA_TYPE_VIDEO) { + return transceiver; + } + } + RTC_NOTREACHED(); + return nullptr; +} + +// TODO(bugs.webrtc.org/7600): Remove this when multiple transceivers with +// individual transceiver directions are supported. bool PeerConnection::HasRtpSender(cricket::MediaType type) const { - return std::find_if( - senders_.begin(), senders_.end(), - [type](const rtc::scoped_refptr< - RtpSenderProxyWithInternal>& sender) { - return sender->media_type() == type; - }) != senders_.end(); + switch (type) { + case cricket::MEDIA_TYPE_AUDIO: + return !GetAudioTransceiver()->internal()->senders().empty(); + case cricket::MEDIA_TYPE_VIDEO: + return !GetVideoTransceiver()->internal()->senders().empty(); + case cricket::MEDIA_TYPE_DATA: + return false; + } + RTC_NOTREACHED(); + return false; } -RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { - auto it = std::find_if( - senders_.begin(), senders_.end(), - [id](const rtc::scoped_refptr< - RtpSenderProxyWithInternal>& sender) { - return sender->id() == id; - }); - return it != senders_.end() ? (*it)->internal() : nullptr; +rtc::scoped_refptr> +PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) const { + for (auto transceiver : transceivers_) { + for (auto sender : transceiver->internal()->senders()) { + if (sender->track() == track) { + return sender; + } + } + } + return nullptr; } -std::vector< - rtc::scoped_refptr>>::iterator -PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) { - return std::find_if( - senders_.begin(), senders_.end(), - [track](const rtc::scoped_refptr< - RtpSenderProxyWithInternal>& sender) { - return sender->track() == track; - }); +rtc::scoped_refptr> +PeerConnection::FindSenderById(const std::string& sender_id) const { + for (auto transceiver : transceivers_) { + for (auto sender : transceiver->internal()->senders()) { + if (sender->id() == sender_id) { + return sender; + } + } + } + return nullptr; } -std::vector>>::iterator -PeerConnection::FindReceiverForTrack(const std::string& track_id) { - return std::find_if( - receivers_.begin(), receivers_.end(), - [track_id](const rtc::scoped_refptr< - RtpReceiverProxyWithInternal>& receiver) { - return receiver->id() == track_id; - }); +rtc::scoped_refptr> +PeerConnection::FindReceiverById(const std::string& receiver_id) const { + for (auto transceiver : transceivers_) { + for (auto receiver : transceiver->internal()->receivers()) { + if (receiver->id() == receiver_id) { + return receiver; + } + } + } + return nullptr; } -PeerConnection::TrackInfos* PeerConnection::GetRemoteTracks( +std::vector* +PeerConnection::GetRemoteSenderInfos(cricket::MediaType media_type) { + RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || + media_type == cricket::MEDIA_TYPE_VIDEO); + return (media_type == cricket::MEDIA_TYPE_AUDIO) + ? &remote_audio_sender_infos_ + : &remote_video_sender_infos_; +} + +std::vector* PeerConnection::GetLocalSenderInfos( cricket::MediaType media_type) { RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || media_type == cricket::MEDIA_TYPE_VIDEO); - return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &remote_audio_tracks_ - : &remote_video_tracks_; + return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_sender_infos_ + : &local_video_sender_infos_; } -PeerConnection::TrackInfos* PeerConnection::GetLocalTracks( - cricket::MediaType media_type) { - RTC_DCHECK(media_type == cricket::MEDIA_TYPE_AUDIO || - media_type == cricket::MEDIA_TYPE_VIDEO); - return (media_type == cricket::MEDIA_TYPE_AUDIO) ? &local_audio_tracks_ - : &local_video_tracks_; -} - -const PeerConnection::TrackInfo* PeerConnection::FindTrackInfo( - const PeerConnection::TrackInfos& infos, +const PeerConnection::RtpSenderInfo* PeerConnection::FindSenderInfo( + const std::vector& infos, const std::string& stream_label, - const std::string track_id) const { - for (const TrackInfo& track_info : infos) { - if (track_info.stream_label == stream_label && - track_info.track_id == track_id) { - return &track_info; + const std::string sender_id) const { + for (const RtpSenderInfo& sender_info : infos) { + if (sender_info.stream_label == stream_label && + sender_info.sender_id == sender_id) { + return &sender_info; } } return nullptr; @@ -3357,10 +3421,12 @@ bool PeerConnection::SetRemoteDescription( // vectors. At that point, this will become a simple getter. std::vector PeerConnection::Channels() const { std::vector channels; - channels.insert(channels.end(), voice_channels_.begin(), - voice_channels_.end()); - channels.insert(channels.end(), video_channels_.begin(), - video_channels_.end()); + if (voice_channel()) { + channels.push_back(voice_channel()); + } + if (video_channel()) { + channels.push_back(video_channel()); + } if (rtp_data_channel_) { channels.push_back(rtp_data_channel_); } @@ -3942,20 +4008,17 @@ void PeerConnection::OnTransportControllerDtlsHandshakeError( // Enabling voice and video (and RTP data) channels. void PeerConnection::EnableChannels() { - for (cricket::VoiceChannel* voice_channel : voice_channels_) { - if (!voice_channel->enabled()) { - voice_channel->Enable(true); - } + if (voice_channel() && !voice_channel()->enabled()) { + voice_channel()->Enable(true); } - for (cricket::VideoChannel* video_channel : video_channels_) { - if (!video_channel->enabled()) { - video_channel->Enable(true); - } + if (video_channel() && !video_channel()->enabled()) { + video_channel()->Enable(true); } - if (rtp_data_channel_ && !rtp_data_channel_->enabled()) + if (rtp_data_channel_ && !rtp_data_channel_->enabled()) { rtp_data_channel_->Enable(true); + } } // Returns the media index for a local ice candidate given the content name. @@ -4053,12 +4116,12 @@ void PeerConnection::RemoveUnusedChannels(const SessionDescription* desc) { // voice channel. const cricket::ContentInfo* video_info = cricket::GetFirstVideoContent(desc); if ((!video_info || video_info->rejected) && video_channel()) { - RemoveAndDestroyVideoChannel(video_channel()); + DestroyVideoChannel(video_channel()); } const cricket::ContentInfo* voice_info = cricket::GetFirstAudioContent(desc); if ((!voice_info || voice_info->rejected) && voice_channel()) { - RemoveAndDestroyVoiceChannel(voice_channel()); + DestroyVoiceChannel(voice_channel()); } const cricket::ContentInfo* data_info = cricket::GetFirstDataContent(desc); @@ -4139,11 +4202,12 @@ bool PeerConnection::CreateChannels(const SessionDescription* desc) { return true; } +// TODO(steveanton): Perhaps this should be managed by the RtpTransceiver. bool PeerConnection::CreateVoiceChannel(const cricket::ContentInfo* content, const std::string* bundle_transport) { // TODO(steveanton): Check to see if it's safe to create multiple voice // channels. - RTC_DCHECK(voice_channels_.empty()); + RTC_DCHECK(!voice_channel()); std::string transport_name = bundle_transport ? *bundle_transport : content->name; @@ -4171,26 +4235,24 @@ bool PeerConnection::CreateVoiceChannel(const cricket::ContentInfo* content, } return false; } - - voice_channels_.push_back(voice_channel); - voice_channel->SignalRtcpMuxFullyActive.connect( this, &PeerConnection::DestroyRtcpTransport_n); voice_channel->SignalDtlsSrtpSetupFailure.connect( this, &PeerConnection::OnDtlsSrtpSetupFailure); - - SetChannelOnSendersAndReceivers( - voice_channel, senders_, receivers_, cricket::MEDIA_TYPE_AUDIO); voice_channel->SignalSentPacket.connect(this, &PeerConnection::OnSentPacket_w); + + GetAudioTransceiver()->internal()->SetChannel(voice_channel); + return true; } +// TODO(steveanton): Perhaps this should be managed by the RtpTransceiver. bool PeerConnection::CreateVideoChannel(const cricket::ContentInfo* content, const std::string* bundle_transport) { // TODO(steveanton): Check to see if it's safe to create multiple video // channels. - RTC_DCHECK(video_channels_.empty()); + RTC_DCHECK(!video_channel()); std::string transport_name = bundle_transport ? *bundle_transport : content->name; @@ -4219,18 +4281,15 @@ bool PeerConnection::CreateVideoChannel(const cricket::ContentInfo* content, } return false; } - - video_channels_.push_back(video_channel); - video_channel->SignalRtcpMuxFullyActive.connect( this, &PeerConnection::DestroyRtcpTransport_n); video_channel->SignalDtlsSrtpSetupFailure.connect( this, &PeerConnection::OnDtlsSrtpSetupFailure); - - SetChannelOnSendersAndReceivers( - video_channel, senders_, receivers_, cricket::MEDIA_TYPE_VIDEO); video_channel->SignalSentPacket.connect(this, &PeerConnection::OnSentPacket_w); + + GetVideoTransceiver()->internal()->SetChannel(video_channel); + return true; } @@ -4769,23 +4828,12 @@ void PeerConnection::DestroyRtcpTransport_n(const std::string& transport_name) { transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP); } -void PeerConnection::RemoveAndDestroyVideoChannel( - cricket::VideoChannel* video_channel) { - auto it = - std::find(video_channels_.begin(), video_channels_.end(), video_channel); - RTC_DCHECK(it != video_channels_.end()); - if (it == video_channels_.end()) { - return; - } - video_channels_.erase(it); - DestroyVideoChannel(video_channel); -} - +// TODO(steveanton): Perhaps this should be managed by the RtpTransceiver. void PeerConnection::DestroyVideoChannel(cricket::VideoChannel* video_channel) { - SetChannelOnSendersAndReceivers( - nullptr, senders_, receivers_, cricket::MEDIA_TYPE_VIDEO); + RTC_DCHECK(video_channel); RTC_DCHECK(video_channel->rtp_dtls_transport()); + RTC_DCHECK_EQ(GetVideoTransceiver()->internal()->channel(), video_channel); + GetVideoTransceiver()->internal()->SetChannel(nullptr); const std::string transport_name = video_channel->rtp_dtls_transport()->transport_name(); const bool need_to_delete_rtcp = @@ -4801,23 +4849,12 @@ void PeerConnection::DestroyVideoChannel(cricket::VideoChannel* video_channel) { } } -void PeerConnection::RemoveAndDestroyVoiceChannel( - cricket::VoiceChannel* voice_channel) { - auto it = - std::find(voice_channels_.begin(), voice_channels_.end(), voice_channel); - RTC_DCHECK(it != voice_channels_.end()); - if (it == voice_channels_.end()) { - return; - } - voice_channels_.erase(it); - DestroyVoiceChannel(voice_channel); -} - +// TODO(steveanton): Perhaps this should be managed by the RtpTransceiver. void PeerConnection::DestroyVoiceChannel(cricket::VoiceChannel* voice_channel) { - SetChannelOnSendersAndReceivers( - nullptr, senders_, receivers_, cricket::MEDIA_TYPE_AUDIO); + RTC_DCHECK(voice_channel); RTC_DCHECK(voice_channel->rtp_dtls_transport()); + RTC_DCHECK_EQ(GetAudioTransceiver()->internal()->channel(), voice_channel); + GetAudioTransceiver()->internal()->SetChannel(nullptr); const std::string transport_name = voice_channel->rtp_dtls_transport()->transport_name(); const bool need_to_delete_rtcp = diff --git a/pc/peerconnection.h b/pc/peerconnection.h index e0bf2b8ce5..ae6b537bda 100644 --- a/pc/peerconnection.h +++ b/pc/peerconnection.h @@ -22,8 +22,7 @@ #include "pc/iceserverparsing.h" #include "pc/peerconnectionfactory.h" #include "pc/rtcstatscollector.h" -#include "pc/rtpreceiver.h" -#include "pc/rtpsender.h" +#include "pc/rtptransceiver.h" #include "pc/statscollector.h" #include "pc/streamcollection.h" #include "pc/webrtcsessiondescriptionfactory.h" @@ -223,19 +222,13 @@ class PeerConnection : public PeerConnectionInterface, // Exposed for stats collecting. // TODO(steveanton): Switch callers to use the plural form and remove these. - virtual cricket::VoiceChannel* voice_channel() { - if (voice_channels_.empty()) { - return nullptr; - } else { - return voice_channels_[0]; - } + virtual cricket::VoiceChannel* voice_channel() const { + return static_cast( + GetAudioTransceiver()->internal()->channel()); } - virtual cricket::VideoChannel* video_channel() { - if (video_channels_.empty()) { - return nullptr; - } else { - return video_channels_[0]; - } + virtual cricket::VideoChannel* video_channel() const { + return static_cast( + GetVideoTransceiver()->internal()->channel()); } // Only valid when using deprecated RTP data channels. @@ -277,34 +270,45 @@ class PeerConnection : public PeerConnectionInterface, ~PeerConnection() override; private: - struct TrackInfo { - TrackInfo() : ssrc(0) {} - TrackInfo(const std::string& stream_label, - const std::string track_id, - uint32_t ssrc) - : stream_label(stream_label), track_id(track_id), ssrc(ssrc) {} - bool operator==(const TrackInfo& other) { + struct RtpSenderInfo { + RtpSenderInfo() : first_ssrc(0) {} + RtpSenderInfo(const std::string& stream_label, + const std::string sender_id, + uint32_t ssrc) + : stream_label(stream_label), sender_id(sender_id), first_ssrc(ssrc) {} + bool operator==(const RtpSenderInfo& other) { return this->stream_label == other.stream_label && - this->track_id == other.track_id && this->ssrc == other.ssrc; + this->sender_id == other.sender_id && + this->first_ssrc == other.first_ssrc; } std::string stream_label; - std::string track_id; - uint32_t ssrc; + std::string sender_id; + // An RtpSender can have many SSRCs. The first one is used as a sort of ID + // for communicating with the lower layers. + uint32_t first_ssrc; }; - typedef std::vector TrackInfos; // Implements MessageHandler. void OnMessage(rtc::Message* msg) override; + std::vector>> + GetSendersInternal() const; + std::vector< + rtc::scoped_refptr>> + GetReceiversInternal() const; + + rtc::scoped_refptr> + GetAudioTransceiver() const; + rtc::scoped_refptr> + GetVideoTransceiver() const; + void CreateAudioReceiver(MediaStreamInterface* stream, - const std::string& track_id, - uint32_t ssrc); + const RtpSenderInfo& remote_sender_info); void CreateVideoReceiver(MediaStreamInterface* stream, - const std::string& track_id, - uint32_t ssrc); + const RtpSenderInfo& remote_sender_info); rtc::scoped_refptr RemoveAndStopReceiver( - const std::string& track_id); + const RtpSenderInfo& remote_sender_info); // May be called either by AddStream/RemoveStream, or when a track is // added/removed from a stream previously added via AddStream. @@ -369,9 +373,9 @@ class PeerConnection : public PeerConnectionInterface, rtc::Optional* data_index, cricket::MediaSessionOptions* session_options); - // Remove all local and remote tracks of type |media_type|. + // Remove all local and remote senders of type |media_type|. // Called when a media type is rejected (m-line set to port 0). - void RemoveTracks(cricket::MediaType media_type); + void RemoveSenders(cricket::MediaType media_type); // Makes sure a MediaStreamTrack is created for each StreamParam in |streams|, // and existing MediaStreamTracks are removed if there is no corresponding @@ -379,26 +383,23 @@ class PeerConnection : public PeerConnectionInterface, // is created if it doesn't exist; if false, it's removed if it exists. // |media_type| is the type of the |streams| and can be either audio or video. // If a new MediaStream is created it is added to |new_streams|. - void UpdateRemoteStreamsList( + void UpdateRemoteSendersList( const std::vector& streams, bool default_track_needed, cricket::MediaType media_type, StreamCollection* new_streams); - // Triggered when a remote track has been seen for the first time in a remote + // Triggered when a remote sender has been seen for the first time in a remote // session description. It creates a remote MediaStreamTrackInterface // implementation and triggers CreateAudioReceiver or CreateVideoReceiver. - void OnRemoteTrackSeen(const std::string& stream_label, - const std::string& track_id, - uint32_t ssrc, - cricket::MediaType media_type); + void OnRemoteSenderAdded(const RtpSenderInfo& sender_info, + cricket::MediaType media_type); - // Triggered when a remote track has been removed from a remote session - // description. It removes the remote track with id |track_id| from a remote + // Triggered when a remote sender has been removed from a remote session + // description. It removes the remote sender with id |sender_id| from a remote // MediaStream and triggers DestroyAudioReceiver or DestroyVideoReceiver. - void OnRemoteTrackRemoved(const std::string& stream_label, - const std::string& track_id, - cricket::MediaType media_type); + void OnRemoteSenderRemoved(const RtpSenderInfo& sender_info, + cricket::MediaType media_type); // Finds remote MediaStreams without any tracks and removes them from // |remote_streams_| and notifies the observer that the MediaStreams no longer @@ -407,30 +408,26 @@ class PeerConnection : public PeerConnectionInterface, // Loops through the vector of |streams| and finds added and removed // StreamParams since last time this method was called. - // For each new or removed StreamParam, OnLocalTrackSeen or - // OnLocalTrackRemoved is invoked. - void UpdateLocalTracks(const std::vector& streams, - cricket::MediaType media_type); + // For each new or removed StreamParam, OnLocalSenderSeen or + // OnLocalSenderRemoved is invoked. + void UpdateLocalSenders(const std::vector& streams, + cricket::MediaType media_type); - // Triggered when a local track has been seen for the first time in a local + // Triggered when a local sender has been seen for the first time in a local // session description. // This method triggers CreateAudioSender or CreateVideoSender if the rtp // streams in the local SessionDescription can be mapped to a MediaStreamTrack // in a MediaStream in |local_streams_| - void OnLocalTrackSeen(const std::string& stream_label, - const std::string& track_id, - uint32_t ssrc, - cricket::MediaType media_type); + void OnLocalSenderAdded(const RtpSenderInfo& sender_info, + cricket::MediaType media_type); - // Triggered when a local track has been removed from a local session + // Triggered when a local sender has been removed from a local session // description. // This method triggers DestroyAudioSender or DestroyVideoSender if a stream // has been removed from the local SessionDescription and the stream can be // mapped to a MediaStreamTrack in a MediaStream in |local_streams_|. - void OnLocalTrackRemoved(const std::string& stream_label, - const std::string& track_id, - uint32_t ssrc, - cricket::MediaType media_type); + void OnLocalSenderRemoved(const RtpSenderInfo& sender_info, + cricket::MediaType media_type); void UpdateLocalRtpDataChannels(const cricket::StreamParamsVec& streams); void UpdateRemoteRtpDataChannels(const cricket::StreamParamsVec& streams); @@ -457,21 +454,36 @@ class PeerConnection : public PeerConnectionInterface, void OnDataChannelOpenMessage(const std::string& label, const InternalDataChannelInit& config); + // Returns true if the PeerConnection is configured to use Unified Plan + // semantics for creating offers/answers and setting local/remote + // descriptions. If this is true the RtpTransceiver API will also be available + // to the user. If this is false, Plan B semantics are assumed. + // TODO(steveanton): Flip the default to be Unified Plan once sufficient time + // has passed. + bool IsUnifiedPlan() const { return false; } + + // Is there an RtpSender of the given type? bool HasRtpSender(cricket::MediaType type) const; - RtpSenderInternal* FindSenderById(const std::string& id); - std::vector>>::iterator - FindSenderForTrack(MediaStreamTrackInterface* track); - std::vector>>::iterator - FindReceiverForTrack(const std::string& track_id); + // Return the RtpSender with the given track attached. + rtc::scoped_refptr> + FindSenderForTrack(MediaStreamTrackInterface* track) const; - TrackInfos* GetRemoteTracks(cricket::MediaType media_type); - TrackInfos* GetLocalTracks(cricket::MediaType media_type); - const TrackInfo* FindTrackInfo(const TrackInfos& infos, - const std::string& stream_label, - const std::string track_id) const; + // Return the RtpSender with the given id, or null if none exists. + rtc::scoped_refptr> + FindSenderById(const std::string& sender_id) const; + + // Return the RtpReceiver with the given id, or null if none exists. + rtc::scoped_refptr> + FindReceiverById(const std::string& receiver_id) const; + + std::vector* GetRemoteSenderInfos( + cricket::MediaType media_type); + std::vector* GetLocalSenderInfos( + cricket::MediaType media_type); + const RtpSenderInfo* FindSenderInfo(const std::vector& infos, + const std::string& stream_label, + const std::string sender_id) const; // Returns the specified SCTP DataChannel in sctp_data_channels_, // or nullptr if not found. @@ -518,13 +530,6 @@ class PeerConnection : public PeerConnectionInterface, Error error() const { return error_; } const std::string& error_desc() const { return error_desc_; } - virtual std::vector voice_channels() const { - return voice_channels_; - } - virtual std::vector video_channels() const { - return video_channels_; - } - cricket::BaseChannel* GetChannel(const std::string& content_name); // Get current SSL role used by SCTP's underlying transport. @@ -760,11 +765,11 @@ class PeerConnection : public PeerConnectionInterface, std::vector> stream_observers_; - // These lists store track info seen in local/remote descriptions. - TrackInfos remote_audio_tracks_; - TrackInfos remote_video_tracks_; - TrackInfos local_audio_tracks_; - TrackInfos local_video_tracks_; + // These lists store sender info seen in local/remote descriptions. + std::vector remote_audio_sender_infos_; + std::vector remote_video_sender_infos_; + std::vector local_audio_sender_infos_; + std::vector local_video_sender_infos_; SctpSidAllocator sid_allocator_; // label -> DataChannel @@ -778,11 +783,9 @@ class PeerConnection : public PeerConnectionInterface, std::unique_ptr stats_; // A pointer is passed to senders_ rtc::scoped_refptr stats_collector_; - std::vector>> - senders_; std::vector< - rtc::scoped_refptr>> - receivers_; + rtc::scoped_refptr>> + transceivers_; Error error_ = ERROR_NONE; std::string error_desc_; @@ -792,13 +795,6 @@ class PeerConnection : public PeerConnectionInterface, std::unique_ptr transport_controller_; std::unique_ptr sctp_factory_; - // TODO(steveanton): voice_channels_ and video_channels_ used to be a single - // VoiceChannel/VideoChannel respectively but are being changed to support - // multiple m= lines in unified plan. But until more work is done, these can - // only have 0 or 1 channel each. - // These channels are owned by ChannelManager. - std::vector voice_channels_; - std::vector video_channels_; // |rtp_data_channel_| is used if in RTP data channel mode, |sctp_transport_| // when using SCTP. cricket::RtpDataChannel* rtp_data_channel_ = nullptr; diff --git a/pc/test/mock_peerconnection.h b/pc/test/mock_peerconnection.h index 444ee2e618..cf115932cc 100644 --- a/pc/test/mock_peerconnection.h +++ b/pc/test/mock_peerconnection.h @@ -61,8 +61,8 @@ class MockPeerConnection std::vector>()); MOCK_CONST_METHOD0(sctp_data_channels, const std::vector>&()); - MOCK_METHOD0(voice_channel, cricket::VoiceChannel*()); - MOCK_METHOD0(video_channel, cricket::VideoChannel*()); + MOCK_CONST_METHOD0(voice_channel, cricket::VoiceChannel*()); + MOCK_CONST_METHOD0(video_channel, cricket::VideoChannel*()); // Libjingle uses "local" for a outgoing track, and "remote" for a incoming // track. MOCK_METHOD2(GetLocalTrackIdBySsrc, bool(uint32_t, std::string*));