Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(74)

Unified Diff: talk/app/webrtc/peerconnection.cc

Issue 1413713003: Adding the ability to create an RtpSender without a track. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Adding some unit tests for new methods on the sender. Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: talk/app/webrtc/peerconnection.cc
diff --git a/talk/app/webrtc/peerconnection.cc b/talk/app/webrtc/peerconnection.cc
index 3ddb3560de6ac7dff5c89f70442ec2ff94c0d2b3..8ddffd9bc76a8bd214291f0769f03292e11fa879 100644
--- a/talk/app/webrtc/peerconnection.cc
+++ b/talk/app/webrtc/peerconnection.cc
@@ -59,6 +59,7 @@ using webrtc::DataChannel;
using webrtc::MediaConstraintsInterface;
using webrtc::MediaStreamInterface;
using webrtc::PeerConnectionInterface;
+using webrtc::RtpSenderInterface;
using webrtc::StreamCollection;
using webrtc::StunConfigurations;
using webrtc::TurnConfigurations;
@@ -365,25 +366,24 @@ bool IsValidOfferToReceiveMedia(int value) {
}
// Add the stream and RTP data channel info to |session_options|.
-void SetStreams(cricket::MediaSessionOptions* session_options,
- rtc::scoped_refptr<StreamCollection> streams,
- const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
- rtp_data_channels) {
+void AddSendStreams(
+ cricket::MediaSessionOptions* session_options,
+ const std::vector<rtc::scoped_refptr<RtpSenderInterface>>& senders,
+ const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
+ rtp_data_channels) {
session_options->streams.clear();
- if (streams != nullptr) {
- for (size_t i = 0; i < streams->count(); ++i) {
- MediaStreamInterface* stream = streams->at(i);
- // For each audio track in the stream, add it to the MediaSessionOptions.
- for (const auto& track : stream->GetAudioTracks()) {
- session_options->AddSendStream(cricket::MEDIA_TYPE_AUDIO, track->id(),
- stream->label());
- }
- // For each video track in the stream, add it to the MediaSessionOptions.
- for (const auto& track : stream->GetVideoTracks()) {
- session_options->AddSendStream(cricket::MEDIA_TYPE_VIDEO, track->id(),
- stream->label());
- }
+ for (const auto& sender : senders) {
+ // Add each sender to the MediaSessionOptions.
+ cricket::MediaType type;
+ if (sender->kind() == "audio") {
pthatcher1 2015/10/20 17:42:49 We should use a named constant for "audio" and "vi
Taylor Brandstetter 2015/10/21 00:22:08 Done.
+ type = cricket::MEDIA_TYPE_AUDIO;
+ } else if (sender->kind() == "video") {
+ type = cricket::MEDIA_TYPE_VIDEO;
+ } else {
+ RTC_DCHECK(false && "Invalid 'kind' for RtpSender.");
+ continue;
}
+ session_options->AddSendStream(type, sender->id(), sender->stream_id());
}
// Check for data channels.
@@ -683,8 +683,6 @@ PeerConnection::remote_streams() {
return remote_streams_;
}
-// TODO(deadbeef): Create RtpSenders immediately here, even if local
-// description hasn't yet been set.
bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
if (IsClosed()) {
return false;
@@ -695,23 +693,46 @@ bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
local_streams_->AddStream(local_stream);
- // Find tracks that have already been configured in SDP. This can occur if a
- // local session description that contains the MSID of these tracks is set
- // before AddLocalStream is called. It can also occur if the local session
- // description is not changed and RemoveLocalStream is called and later
- // AddLocalStream is called again with the same stream.
+ // Note: 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.
pthatcher1 2015/10/20 17:42:49 I'm a little lost as to how this comment matches t
Taylor Brandstetter 2015/10/21 00:22:08 "Already configured in SDP" isn't the same as "alr
for (const auto& track : local_stream->GetAudioTracks()) {
- const TrackInfo* track_info =
- FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id());
- if (track_info) {
- CreateAudioSender(local_stream, track.get(), track_info->ssrc);
+ auto sender = FindSenderForTrack(track.get());
+ if (sender == senders_.end()) {
+ // Normal case; we've never seen this track before.
+ AudioRtpSender* new_sender = new AudioRtpSender(
+ track.get(), local_stream->label(), session_.get(), stats_.get());
+ senders_.push_back(new_sender);
+ const TrackInfo* track_info = FindTrackInfo(
+ local_audio_tracks_, local_stream->label(), track->id());
+ if (track_info) {
+ new_sender->SetSsrc(track_info->ssrc);
+ }
+ } else {
+ // 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)->set_stream_id(local_stream->label());
pthatcher1 2015/10/20 17:42:49 Should this method be set_stream_label?
Taylor Brandstetter 2015/10/21 00:22:08 Since in the W3C spec it's called an "id", I figur
}
}
for (const auto& track : local_stream->GetVideoTracks()) {
- const TrackInfo* track_info =
- FindTrackInfo(local_video_tracks_, local_stream->label(), track->id());
- if (track_info) {
- CreateVideoSender(local_stream, track.get(), track_info->ssrc);
+ auto sender = FindSenderForTrack(track.get());
+ if (sender == senders_.end()) {
+ // Normal case; we've never seen this track before.
+ VideoRtpSender* new_sender = new VideoRtpSender(
+ track.get(), local_stream->label(), session_.get());
+ senders_.push_back(new_sender);
+ const TrackInfo* track_info = FindTrackInfo(
+ local_video_tracks_, local_stream->label(), track->id());
+ if (track_info) {
+ new_sender->SetSsrc(track_info->ssrc);
+ }
+ } else {
+ // 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)->set_stream_id(local_stream->label());
}
}
@@ -721,21 +742,27 @@ bool PeerConnection::AddStream(MediaStreamInterface* local_stream) {
}
// TODO(deadbeef): Don't destroy RtpSenders here; they should be kept around
-// indefinitely.
+// indefinitely, when we have unified plan SDP.
void PeerConnection::RemoveStream(MediaStreamInterface* local_stream) {
for (const auto& track : local_stream->GetAudioTracks()) {
- const TrackInfo* track_info =
- FindTrackInfo(local_audio_tracks_, local_stream->label(), track->id());
- if (track_info) {
- DestroyAudioSender(local_stream, track.get(), track_info->ssrc);
+ auto sender = FindSenderForTrack(track.get());
+ if (sender == senders_.end()) {
+ LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
+ << " doesn't exist.";
+ continue;
}
+ (*sender)->Stop();
+ senders_.erase(sender);
}
for (const auto& track : local_stream->GetVideoTracks()) {
- const TrackInfo* track_info =
- FindTrackInfo(local_video_tracks_, local_stream->label(), track->id());
- if (track_info) {
- DestroyVideoSender(local_stream, track.get());
+ auto sender = FindSenderForTrack(track.get());
+ if (sender == senders_.end()) {
+ LOG(LS_WARNING) << "RtpSender for track with id " << track->id()
+ << " doesn't exist.";
+ continue;
}
+ (*sender)->Stop();
+ senders_.erase(sender);
}
local_streams_->RemoveStream(local_stream);
@@ -766,6 +793,20 @@ rtc::scoped_refptr<DtmfSenderInterface> PeerConnection::CreateDtmfSender(
return DtmfSenderProxy::Create(signaling_thread(), sender.get());
}
+rtc::scoped_refptr<RtpSenderInterface> PeerConnection::CreateSender(
+ const std::string& kind) {
+ RtpSenderInterface* new_sender;
+ if (kind == "audio") {
pthatcher1 2015/10/20 17:42:49 Same here with named constants.
Taylor Brandstetter 2015/10/21 00:22:08 Done.
+ new_sender = new AudioRtpSender(session_.get(), stats_.get());
+ } else if (kind == "video") {
+ new_sender = new VideoRtpSender(session_.get());
+ } else {
+ return rtc::scoped_refptr<RtpSenderInterface>();
+ }
+ senders_.push_back(new_sender);
+ return RtpSenderProxy::Create(signaling_thread(), new_sender);
+}
+
std::vector<rtc::scoped_refptr<RtpSenderInterface>> PeerConnection::GetSenders()
const {
std::vector<rtc::scoped_refptr<RtpSenderInterface>> senders;
@@ -1282,49 +1323,6 @@ void PeerConnection::DestroyVideoReceiver(MediaStreamInterface* stream,
}
}
-void PeerConnection::CreateAudioSender(MediaStreamInterface* stream,
- AudioTrackInterface* audio_track,
- uint32_t ssrc) {
- senders_.push_back(new AudioRtpSender(audio_track, ssrc, session_.get()));
- stats_->AddLocalAudioTrack(audio_track, ssrc);
-}
-
-void PeerConnection::CreateVideoSender(MediaStreamInterface* stream,
- VideoTrackInterface* video_track,
- uint32_t ssrc) {
- senders_.push_back(new VideoRtpSender(video_track, ssrc, session_.get()));
-}
-
-// TODO(deadbeef): Keep RtpSenders around even if track goes away in local
-// description.
-void PeerConnection::DestroyAudioSender(MediaStreamInterface* stream,
- AudioTrackInterface* audio_track,
- uint32_t ssrc) {
- auto it = FindSenderForTrack(audio_track);
- if (it == senders_.end()) {
- LOG(LS_WARNING) << "RtpSender for track with id " << audio_track->id()
- << " doesn't exist.";
- return;
- } else {
- (*it)->Stop();
- senders_.erase(it);
- }
- stats_->RemoveLocalAudioTrack(audio_track, ssrc);
-}
-
-void PeerConnection::DestroyVideoSender(MediaStreamInterface* stream,
- VideoTrackInterface* video_track) {
- auto it = FindSenderForTrack(video_track);
- if (it == senders_.end()) {
- LOG(LS_WARNING) << "RtpSender for track with id " << video_track->id()
- << " doesn't exist.";
- return;
- } else {
- (*it)->Stop();
- senders_.erase(it);
- }
-}
-
void PeerConnection::OnIceConnectionChange(
PeerConnectionInterface::IceConnectionState new_state) {
RTC_DCHECK(signaling_thread()->IsCurrent());
@@ -1396,7 +1394,7 @@ void PeerConnection::PostCreateSessionDescriptionFailure(
bool PeerConnection::GetOptionsForOffer(
const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
cricket::MediaSessionOptions* session_options) {
- SetStreams(session_options, local_streams_, rtp_data_channels_);
+ AddSendStreams(session_options, senders_, rtp_data_channels_);
if (!ConvertRtcOptionsForOffer(rtc_options, session_options)) {
return false;
@@ -1411,7 +1409,7 @@ bool PeerConnection::GetOptionsForOffer(
bool PeerConnection::GetOptionsForAnswer(
const MediaConstraintsInterface* constraints,
cricket::MediaSessionOptions* session_options) {
- SetStreams(session_options, local_streams_, rtp_data_channels_);
+ AddSendStreams(session_options, senders_, rtp_data_channels_);
session_options->recv_audio = false;
session_options->recv_video = false;
@@ -1435,8 +1433,7 @@ void PeerConnection::UpdateRemoteStreamsList(
TrackInfos* current_tracks = GetRemoteTracks(media_type);
// Find removed tracks. I.e., tracks where the track id or ssrc don't match
- // the
- // new StreamParam.
+ // the new StreamParam.
auto track_it = current_tracks->begin();
while (track_it != current_tracks->end()) {
const TrackInfo& info = *track_it;
@@ -1638,62 +1635,52 @@ void PeerConnection::OnLocalTrackSeen(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type) {
pthatcher1 2015/10/20 17:42:49 Should we call this OnSenderAddedToSessionDescript
Taylor Brandstetter 2015/10/21 00:22:08 Well, then it would be inconsistent with OnRemoteT
- MediaStreamInterface* stream = local_streams_->find(stream_label);
- if (!stream) {
- LOG(LS_WARNING) << "An unknown local MediaStream with label "
- << stream_label << " has been configured.";
+ RtpSenderInterface* sender = FindSenderById(track_id);
pthatcher1 2015/10/20 17:42:49 Should we match the media_type/kind when finding s
Taylor Brandstetter 2015/10/21 00:22:08 Then we wouldn't be able to tell "unknown sender"
+ if (!sender) {
+ LOG(LS_WARNING) << "An unknown RtpSender with id " << track_id
+ << " has been configured in the local description.";
return;
}
- if (media_type == cricket::MEDIA_TYPE_AUDIO) {
- AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id);
- if (!audio_track) {
- LOG(LS_WARNING) << "An unknown local AudioTrack with id , " << track_id
- << " has been configured.";
- return;
- }
- CreateAudioSender(stream, audio_track, ssrc);
- } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
- VideoTrackInterface* video_track = stream->FindVideoTrack(track_id);
- if (!video_track) {
- LOG(LS_WARNING) << "An unknown local VideoTrack with id , " << track_id
- << " has been configured.";
- return;
- }
- CreateVideoSender(stream, video_track, ssrc);
- } else {
- RTC_DCHECK(false && "Invalid media type");
+ if (!((media_type == cricket::MEDIA_TYPE_AUDIO &&
+ sender->kind() == "audio") ||
+ (media_type == cricket::MEDIA_TYPE_VIDEO &&
+ sender->kind() == "video"))) {
+ LOG(LS_WARNING) << "An RtpSender has been configured in the local"
+ << " description with an unexpected media type.";
+ RTC_DCHECK(false && "Invalid media type.");
pthatcher1 2015/10/20 17:42:49 This is an error from the application or the javas
Taylor Brandstetter 2015/10/21 00:22:08 DCHECKS only do anything in a debug builds (hence
pthatcher1 2015/10/22 07:34:13 But do we still want to allow bad JS to crash the
Taylor Brandstetter 2015/10/22 19:26:42 Oh, that's a good point. Ok, it's removed.
+ return;
}
+
+ sender->set_stream_id(stream_label);
+ sender->SetSsrc(ssrc);
}
void PeerConnection::OnLocalTrackRemoved(const std::string& stream_label,
const std::string& track_id,
uint32_t ssrc,
cricket::MediaType media_type) {
pthatcher1 2015/10/20 17:42:49 Should we call this OnSenderRemovedFromSessionDesc
- MediaStreamInterface* stream = local_streams_->find(stream_label);
- if (!stream) {
- // This is the normal case. I.e., RemoveLocalStream has been called and the
+ RtpSenderInterface* sender = FindSenderById(track_id);
+ if (!sender) {
+ // This is the normal case. I.e., RemoveStream has been called and the
// SessionDescriptions has been renegotiated.
return;
}
- // A track has been removed from the SessionDescription but the MediaStream
- // is still associated with PeerConnection. This only occurs if the SDP
- // doesn't match with the calls to AddLocalStream and RemoveLocalStream.
- if (media_type == cricket::MEDIA_TYPE_AUDIO) {
- AudioTrackInterface* audio_track = stream->FindAudioTrack(track_id);
- if (!audio_track) {
- return;
- }
- DestroyAudioSender(stream, audio_track, ssrc);
- } else if (media_type == cricket::MEDIA_TYPE_VIDEO) {
- VideoTrackInterface* video_track = stream->FindVideoTrack(track_id);
- if (!video_track) {
- return;
- }
- DestroyVideoSender(stream, video_track);
- } else {
+
+ // A sender has been removed from the SessionDescription but it's still
+ // associated with the PeerConnection. This only occurs if the SDP doesn't
+ // match with the calls to CreateSender, AddStream and RemoveStream.
+ if (!((media_type == cricket::MEDIA_TYPE_AUDIO &&
+ sender->kind() == "audio") ||
pthatcher1 2015/10/20 17:42:49 Can we change the sender->kind() to be a cricket::
Taylor Brandstetter 2015/10/21 00:22:08 Done.
+ (media_type == cricket::MEDIA_TYPE_VIDEO &&
+ sender->kind() == "video"))) {
+ LOG(LS_WARNING) << "An RtpSender has been configured in the local"
+ << " description with an unexpected media type.";
RTC_DCHECK(false && "Invalid media type.");
+ return;
}
+
+ sender->SetSsrc(0);
}
void PeerConnection::UpdateLocalRtpDataChannels(
@@ -1911,6 +1898,15 @@ void PeerConnection::OnDataChannelOpenMessage(
DataChannelProxy::Create(signaling_thread(), channel));
}
+RtpSenderInterface* PeerConnection::FindSenderById(const std::string& id) {
+ auto it =
+ std::find_if(senders_.begin(), senders_.end(),
+ [id](const rtc::scoped_refptr<RtpSenderInterface>& sender) {
+ return sender->id() == id;
+ });
+ return it != senders_.end() ? it->get() : nullptr;
+}
+
std::vector<rtc::scoped_refptr<RtpSenderInterface>>::iterator
PeerConnection::FindSenderForTrack(MediaStreamTrackInterface* track) {
return std::find_if(

Powered by Google App Engine
This is Rietveld 408576698