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

Side by Side Diff: webrtc/pc/peerconnection.cc

Issue 2991693002: Adding support for Unified Plan offer/answer negotiation. (Closed)
Patch Set: Clean up. Created 3 years, 4 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 unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 ? desc->streams() 126 ? desc->streams()
127 : std::vector<cricket::StreamParams>(); 127 : std::vector<cricket::StreamParams>();
128 } 128 }
129 129
130 bool IsValidOfferToReceiveMedia(int value) { 130 bool IsValidOfferToReceiveMedia(int value) {
131 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; 131 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options;
132 return (value >= Options::kUndefined) && 132 return (value >= Options::kUndefined) &&
133 (value <= Options::kMaxOfferToReceiveMedia); 133 (value <= Options::kMaxOfferToReceiveMedia);
134 } 134 }
135 135
136 // Add the stream and RTP data channel info to |session_options|. 136 // Add options to |[audio/video]_media_description_options| from |senders|.
137 void AddSendStreams( 137 void AddRtpSenderOptions(
138 cricket::MediaSessionOptions* session_options,
139 const std::vector<rtc::scoped_refptr< 138 const std::vector<rtc::scoped_refptr<
140 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders, 139 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders,
140 cricket::MediaDescriptionOptions* audio_media_description_options,
141 cricket::MediaDescriptionOptions* video_media_description_options) {
142 for (const auto& sender : senders) {
143 if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) {
144 if (audio_media_description_options) {
145 audio_media_description_options->AddAudioSender(
146 sender->id(), sender->internal()->stream_id());
147 }
148 } else {
149 RTC_DCHECK(sender->media_type() == cricket::MEDIA_TYPE_VIDEO);
150 if (video_media_description_options) {
151 video_media_description_options->AddVideoSender(
152 sender->id(), sender->internal()->stream_id(), 1);
153 }
154 }
155 }
156 }
157
158 // Add options to |session_options| from |rtp_data_channels|.
159 void AddRtpDataChannelOptions(
141 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& 160 const std::map<std::string, rtc::scoped_refptr<DataChannel>>&
142 rtp_data_channels) { 161 rtp_data_channels,
143 session_options->streams.clear(); 162 cricket::MediaDescriptionOptions* data_media_description_options) {
144 for (const auto& sender : senders) { 163 if (!data_media_description_options) {
145 session_options->AddSendStream(sender->media_type(), sender->id(), 164 return;
146 sender->internal()->stream_id());
147 } 165 }
148
149 // Check for data channels. 166 // Check for data channels.
150 for (const auto& kv : rtp_data_channels) { 167 for (const auto& kv : rtp_data_channels) {
151 const DataChannel* channel = kv.second; 168 const DataChannel* channel = kv.second;
152 if (channel->state() == DataChannel::kConnecting || 169 if (channel->state() == DataChannel::kConnecting ||
153 channel->state() == DataChannel::kOpen) { 170 channel->state() == DataChannel::kOpen) {
154 // |streamid| and |sync_label| are both set to the DataChannel label 171 // Legacy RTP data channels are signaled with the track/stream ID set to
155 // here so they can be signaled the same way as MediaStreams and Tracks. 172 // the data channel's label.
156 // For MediaStreams, the sync_label is the MediaStream label and the 173 data_media_description_options->AddRtpDataChannel(channel->label(),
157 // track label is the same as |streamid|. 174 channel->label());
158 const std::string& streamid = channel->label();
159 const std::string& sync_label = channel->label();
160 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid,
161 sync_label);
162 } 175 }
163 } 176 }
164 } 177 }
165 178
166 uint32_t ConvertIceTransportTypeToCandidateFilter( 179 uint32_t ConvertIceTransportTypeToCandidateFilter(
167 PeerConnectionInterface::IceTransportsType type) { 180 PeerConnectionInterface::IceTransportsType type) {
168 switch (type) { 181 switch (type) {
169 case PeerConnectionInterface::kNone: 182 case PeerConnectionInterface::kNone:
170 return cricket::CF_NONE; 183 return cricket::CF_NONE;
171 case PeerConnectionInterface::kRelay: 184 case PeerConnectionInterface::kRelay:
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 // Generate a RTCP CNAME when a PeerConnection is created. 308 // Generate a RTCP CNAME when a PeerConnection is created.
296 std::string GenerateRtcpCname() { 309 std::string GenerateRtcpCname() {
297 std::string cname; 310 std::string cname;
298 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) { 311 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) {
299 LOG(LS_ERROR) << "Failed to generate CNAME."; 312 LOG(LS_ERROR) << "Failed to generate CNAME.";
300 RTC_NOTREACHED(); 313 RTC_NOTREACHED();
301 } 314 }
302 return cname; 315 return cname;
303 } 316 }
304 317
305 bool ExtractMediaSessionOptions( 318 bool ValidateOfferAnswerOptions(
319 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options) {
320 return IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) &&
321 IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video);
322 }
323
324 // From |rtc_options| and |is_offer|, fill |recv_audio| and |recv_video|.
325 // TODO: delete, it's simpler without a function
Taylor Brandstetter 2017/07/28 19:00:25 Can this TODO be addressed in this CL? Also, as we
Zhi Huang 2017/08/02 04:38:36 Done.
326 void ExtractAudioVideoRecvPreferences(
306 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 327 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
307 bool is_offer, 328 bool is_offer,
308 cricket::MediaSessionOptions* session_options) { 329 bool* recv_audio,
330 bool* recv_video) {
309 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; 331 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions;
310 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) || 332
311 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) { 333 // If constraints don't prevent us, we always accept audio.
312 return false; 334 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
335 *recv_audio = (rtc_options.offer_to_receive_audio > 0);
336 } else {
337 *recv_audio = true;
313 } 338 }
314 339
315 // If constraints don't prevent us, we always accept video.
316 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
317 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0);
318 } else {
319 session_options->recv_audio = true;
320 }
321 // For offers, we only offer video if we have it or it's forced by options. 340 // For offers, we only offer video if we have it or it's forced by options.
322 // For answers, we will always accept video (if offered). 341 // For answers, we will always accept video (if offered).
323 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { 342 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
324 session_options->recv_video = (rtc_options.offer_to_receive_video > 0); 343 *recv_video = (rtc_options.offer_to_receive_video > 0);
325 } else if (is_offer) { 344 } else if (is_offer) {
326 session_options->recv_video = false; 345 *recv_video = false;
327 } else { 346 } else {
328 session_options->recv_video = true; 347 *recv_video = true;
348 }
349 }
350
351 // From |rtc_options|, fill parts of |session_options| shared by all generated
352 // m= sections (in other words, nothign that involves a map/array).
Taylor Brandstetter 2017/07/28 19:00:25 nothign -> nothing
Zhi Huang 2017/08/02 04:38:36 Done.
353 void ExtractSharedMediaSessionOptions(
354 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
355 cricket::MediaSessionOptions* session_options) {
356 session_options->vad_enabled = rtc_options.voice_activity_detection;
357 session_options->bundle_enabled = rtc_options.use_rtp_mux;
358 }
359
360 bool ConvertConstraintsToOfferAnswerOptions(
361 const MediaConstraintsInterface* constraints,
362 PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
363 if (!constraints) {
364 return true;
329 } 365 }
330 366
331 session_options->vad_enabled = rtc_options.voice_activity_detection;
332 session_options->bundle_enabled = rtc_options.use_rtp_mux;
333 for (auto& kv : session_options->transport_options) {
334 kv.second.ice_restart = rtc_options.ice_restart;
335 }
336
337 return true;
338 }
339
340 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
341 cricket::MediaSessionOptions* session_options) {
342 bool value = false; 367 bool value = false;
343 size_t mandatory_constraints_satisfied = 0; 368 size_t mandatory_constraints_satisfied = 0;
344 369
345 // kOfferToReceiveAudio defaults to true according to spec. 370 if (FindConstraint(constraints,
346 if (!FindConstraint(constraints, 371 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
347 MediaConstraintsInterface::kOfferToReceiveAudio, &value, 372 &mandatory_constraints_satisfied)) {
348 &mandatory_constraints_satisfied) || 373 offer_answer_options->offer_to_receive_audio =
349 value) { 374 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
350 session_options->recv_audio = true; 375 kOfferToReceiveMediaTrue
351 } 376 : 0;
352
353 // kOfferToReceiveVideo defaults to false according to spec. But
354 // if it is an answer and video is offered, we should still accept video
355 // per default.
356 value = false;
357 if (!FindConstraint(constraints,
358 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
359 &mandatory_constraints_satisfied) ||
360 value) {
361 session_options->recv_video = true;
362 } 377 }
363 378
364 if (FindConstraint(constraints, 379 if (FindConstraint(constraints,
380 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
381 &mandatory_constraints_satisfied)) {
382 offer_answer_options->offer_to_receive_video =
383 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
384 kOfferToReceiveMediaTrue
385 : 0;
386 }
387 if (FindConstraint(constraints,
365 MediaConstraintsInterface::kVoiceActivityDetection, &value, 388 MediaConstraintsInterface::kVoiceActivityDetection, &value,
366 &mandatory_constraints_satisfied)) { 389 &mandatory_constraints_satisfied)) {
367 session_options->vad_enabled = value; 390 offer_answer_options->voice_activity_detection = value;
391 }
392 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
393 &mandatory_constraints_satisfied)) {
394 offer_answer_options->use_rtp_mux = value;
395 }
396 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
397 &value, &mandatory_constraints_satisfied)) {
398 offer_answer_options->ice_restart = value;
368 } 399 }
369 400
370 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
371 &mandatory_constraints_satisfied)) {
372 session_options->bundle_enabled = value;
373 } else {
374 // kUseRtpMux defaults to true according to spec.
375 session_options->bundle_enabled = true;
376 }
377
378 bool ice_restart = false;
379 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
380 &value, &mandatory_constraints_satisfied)) {
381 // kIceRestart defaults to false according to spec.
382 ice_restart = true;
383 }
384 for (auto& kv : session_options->transport_options) {
385 kv.second.ice_restart = ice_restart;
386 }
387
388 if (!constraints) {
389 return true;
390 }
391 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); 401 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
392 } 402 }
393 403
394 PeerConnection::PeerConnection(PeerConnectionFactory* factory, 404 PeerConnection::PeerConnection(PeerConnectionFactory* factory,
395 std::unique_ptr<RtcEventLog> event_log, 405 std::unique_ptr<RtcEventLog> event_log,
396 std::unique_ptr<Call> call) 406 std::unique_ptr<Call> call)
397 : factory_(factory), 407 : factory_(factory),
398 observer_(NULL), 408 observer_(NULL),
399 uma_observer_(NULL), 409 uma_observer_(NULL),
400 event_log_(std::move(event_log)), 410 event_log_(std::move(event_log)),
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 return DataChannelProxy::Create(signaling_thread(), channel.get()); 814 return DataChannelProxy::Create(signaling_thread(), channel.get());
805 } 815 }
806 816
807 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 817 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
808 const MediaConstraintsInterface* constraints) { 818 const MediaConstraintsInterface* constraints) {
809 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 819 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
810 if (!observer) { 820 if (!observer) {
811 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 821 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
812 return; 822 return;
813 } 823 }
814 RTCOfferAnswerOptions options; 824 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
815 825 if (!ConvertConstraintsToOfferAnswerOptions(constraints,
816 bool value; 826 &offer_answer_options)) {
817 size_t mandatory_constraints = 0; 827 std::string error = "CreateOffer called with invalid constraints.";
818 828 LOG(LS_ERROR) << error;
819 if (FindConstraint(constraints, 829 PostCreateSessionDescriptionFailure(observer, error);
820 MediaConstraintsInterface::kOfferToReceiveAudio, 830 return;
821 &value,
822 &mandatory_constraints)) {
823 options.offer_to_receive_audio =
824 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
825 } 831 }
826 832
827 if (FindConstraint(constraints, 833 CreateOffer(observer, offer_answer_options);
828 MediaConstraintsInterface::kOfferToReceiveVideo,
829 &value,
830 &mandatory_constraints)) {
831 options.offer_to_receive_video =
832 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
833 }
834
835 if (FindConstraint(constraints,
836 MediaConstraintsInterface::kVoiceActivityDetection,
837 &value,
838 &mandatory_constraints)) {
839 options.voice_activity_detection = value;
840 }
841
842 if (FindConstraint(constraints,
843 MediaConstraintsInterface::kIceRestart,
844 &value,
845 &mandatory_constraints)) {
846 options.ice_restart = value;
847 }
848
849 if (FindConstraint(constraints,
850 MediaConstraintsInterface::kUseRtpMux,
851 &value,
852 &mandatory_constraints)) {
853 options.use_rtp_mux = value;
854 }
855
856 CreateOffer(observer, options);
857 } 834 }
858 835
859 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 836 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
860 const RTCOfferAnswerOptions& options) { 837 const RTCOfferAnswerOptions& options) {
861 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 838 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
862 if (!observer) { 839 if (!observer) {
863 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 840 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
864 return; 841 return;
865 } 842 }
866 843
867 cricket::MediaSessionOptions session_options; 844 if (!ValidateOfferAnswerOptions(options)) {
868 if (!GetOptionsForOffer(options, &session_options)) {
869 std::string error = "CreateOffer called with invalid options."; 845 std::string error = "CreateOffer called with invalid options.";
870 LOG(LS_ERROR) << error; 846 LOG(LS_ERROR) << error;
871 PostCreateSessionDescriptionFailure(observer, error); 847 PostCreateSessionDescriptionFailure(observer, error);
872 return; 848 return;
873 } 849 }
874 850
851 cricket::MediaSessionOptions session_options;
852 GetOptionsForOffer(options, &session_options);
875 session_->CreateOffer(observer, options, session_options); 853 session_->CreateOffer(observer, options, session_options);
876 } 854 }
877 855
878 void PeerConnection::CreateAnswer( 856 void PeerConnection::CreateAnswer(
879 CreateSessionDescriptionObserver* observer, 857 CreateSessionDescriptionObserver* observer,
880 const MediaConstraintsInterface* constraints) { 858 const MediaConstraintsInterface* constraints) {
881 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 859 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
882 if (!observer) { 860 if (!observer) {
883 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 861 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
884 return; 862 return;
885 } 863 }
886 864
887 cricket::MediaSessionOptions session_options; 865 if (!session_->remote_description() ||
888 if (!GetOptionsForAnswer(constraints, &session_options)) { 866 session_->remote_description()->type() !=
867 SessionDescriptionInterface::kOffer) {
868 std::string error = "CreateAnswer called without remote offer.";
869 LOG(LS_ERROR) << error;
870 PostCreateSessionDescriptionFailure(observer, error);
871 return;
872 }
873
874 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
875 if (!ConvertConstraintsToOfferAnswerOptions(constraints,
876 &offer_answer_options)) {
889 std::string error = "CreateAnswer called with invalid constraints."; 877 std::string error = "CreateAnswer called with invalid constraints.";
890 LOG(LS_ERROR) << error; 878 LOG(LS_ERROR) << error;
891 PostCreateSessionDescriptionFailure(observer, error); 879 PostCreateSessionDescriptionFailure(observer, error);
892 return; 880 return;
893 } 881 }
894 882
883 cricket::MediaSessionOptions session_options;
884 GetOptionsForAnswer(offer_answer_options, &session_options);
895 session_->CreateAnswer(observer, session_options); 885 session_->CreateAnswer(observer, session_options);
896 } 886 }
897 887
898 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, 888 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
899 const RTCOfferAnswerOptions& options) { 889 const RTCOfferAnswerOptions& options) {
900 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 890 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
901 if (!observer) { 891 if (!observer) {
902 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 892 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
903 return; 893 return;
904 } 894 }
905 895
906 cricket::MediaSessionOptions session_options; 896 cricket::MediaSessionOptions session_options;
907 if (!GetOptionsForAnswer(options, &session_options)) { 897 GetOptionsForAnswer(options, &session_options);
908 std::string error = "CreateAnswer called with invalid options.";
909 LOG(LS_ERROR) << error;
910 PostCreateSessionDescriptionFailure(observer, error);
911 return;
912 }
913 898
914 session_->CreateAnswer(observer, session_options); 899 session_->CreateAnswer(observer, session_options);
915 } 900 }
916 901
917 void PeerConnection::SetLocalDescription( 902 void PeerConnection::SetLocalDescription(
918 SetSessionDescriptionObserver* observer, 903 SetSessionDescriptionObserver* observer,
919 SessionDescriptionInterface* desc) { 904 SessionDescriptionInterface* desc) {
920 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); 905 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
921 if (IsClosed()) { 906 if (IsClosed()) {
922 return; 907 return;
(...skipping 703 matching lines...) Expand 10 before | Expand all | Expand 10 after
1626 1611
1627 void PeerConnection::PostCreateSessionDescriptionFailure( 1612 void PeerConnection::PostCreateSessionDescriptionFailure(
1628 CreateSessionDescriptionObserver* observer, 1613 CreateSessionDescriptionObserver* observer,
1629 const std::string& error) { 1614 const std::string& error) {
1630 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); 1615 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
1631 msg->error = error; 1616 msg->error = error;
1632 signaling_thread()->Post(RTC_FROM_HERE, this, 1617 signaling_thread()->Post(RTC_FROM_HERE, this,
1633 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); 1618 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
1634 } 1619 }
1635 1620
1636 bool PeerConnection::GetOptionsForOffer( 1621 void PeerConnection::GetOptionsForOffer(
1637 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 1622 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
1638 cricket::MediaSessionOptions* session_options) { 1623 cricket::MediaSessionOptions* session_options) {
1639 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of 1624 ExtractSharedMediaSessionOptions(rtc_options, session_options);
1640 // ContentInfos. 1625
1626 // Figure out transceiver directional preferences.
1627 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
1628 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
Taylor Brandstetter 2017/07/28 19:00:25 nit: Some whitespace in between different logical
Zhi Huang 2017/08/02 04:38:36 Done.
1629 // By default, generate sendrecv/recvonly m= sections.
1630 bool recv_audio = true;
1631 bool recv_video = true;
1632 // By default, only offer a new m= section if we have media to send with it.
1633 bool offer_new_audio_description = send_audio;
1634 bool offer_new_video_description = send_video;
1635 bool offer_new_data_description = HasDataChannels();
1636 // The "offer_to_receive_X" options allow those defaults to be overridden.
1637 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
1638 recv_audio = (rtc_options.offer_to_receive_audio > 0);
1639 offer_new_audio_description = (rtc_options.offer_to_receive_audio > 0);
1640 }
1641 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
1642 recv_video = (rtc_options.offer_to_receive_video > 0);
1643 offer_new_video_description = (rtc_options.offer_to_receive_video > 0);
1644 }
1645
1646 int audio_index = -1;
1647 int video_index = -1;
1648 int data_index = -1;
1649 // If a current description exists, generate m= sections in the same order,
1650 // using the first audio/video/data section that appears and rejecting
1651 // extraneous ones.
1641 if (session_->local_description()) { 1652 if (session_->local_description()) {
1642 for (const cricket::ContentInfo& content : 1653 for (const cricket::ContentInfo& content :
1643 session_->local_description()->description()->contents()) { 1654 session_->local_description()->description()->contents()) {
1644 session_options->transport_options[content.name] = 1655 if (IsAudioContent(&content)) {
1645 cricket::TransportOptions(); 1656 // If we already have an audio m= section, reject this extra one.
1657 if (audio_index != -1) {
1658 session_options->media_description_options.push_back(
1659 cricket::MediaDescriptionOptions(
1660 cricket::MEDIA_TYPE_AUDIO, content.name,
1661 cricket::RtpTransceiverDirection(false, false), true));
1662 } else {
1663 session_options->media_description_options.push_back(
1664 cricket::MediaDescriptionOptions(
1665 cricket::MEDIA_TYPE_AUDIO, content.name,
1666 cricket::RtpTransceiverDirection(send_audio, recv_audio),
1667 !recv_audio && !send_audio));
1668 audio_index = session_options->media_description_options.size() - 1;
1669 }
1670 } else if (IsVideoContent(&content)) {
1671 // If we already have an video m= section, reject this extra one.
1672 if (video_index != -1) {
1673 session_options->media_description_options.push_back(
1674 cricket::MediaDescriptionOptions(
1675 cricket::MEDIA_TYPE_VIDEO, content.name,
1676 cricket::RtpTransceiverDirection(false, false), true));
1677 } else {
1678 session_options->media_description_options.push_back(
1679 cricket::MediaDescriptionOptions(
1680 cricket::MEDIA_TYPE_VIDEO, content.name,
1681 cricket::RtpTransceiverDirection(send_video, recv_video),
1682 !recv_video && !send_video));
1683 video_index = session_options->media_description_options.size() - 1;
1684 }
1685 } else {
1686 RTC_DCHECK(IsDataContent(&content));
1687 // If we already have an data m= section, reject this extra one.
1688 if (data_index != -1) {
1689 session_options->media_description_options.push_back(
1690 cricket::MediaDescriptionOptions(
1691 cricket::MEDIA_TYPE_DATA, content.name,
1692 cricket::RtpTransceiverDirection(false, false), true));
1693 } else {
1694 session_options->media_description_options.push_back(
1695 cricket::MediaDescriptionOptions(
1696 cricket::MEDIA_TYPE_DATA, content.name,
1697 // Direction for data sections is meaningless, but legacy
1698 // endpoints might expect sendrecv.
1699 cricket::RtpTransceiverDirection(true, true), false));
1700 data_index = session_options->media_description_options.size() - 1;
1701 }
1702 }
1646 } 1703 }
1647 } 1704 }
1648 session_options->enable_ice_renomination = 1705
1649 configuration_.enable_ice_renomination; 1706 // Add audio/video/data m= sections to the end if needed.
1650 1707 if (audio_index == -1 && offer_new_audio_description) {
1651 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) { 1708 session_options->media_description_options.push_back(
1652 return false; 1709 cricket::MediaDescriptionOptions(
1653 } 1710 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
1654 1711 cricket::RtpTransceiverDirection(send_audio, recv_audio), false));
1655 AddSendStreams(session_options, senders_, rtp_data_channels_); 1712 audio_index = session_options->media_description_options.size() - 1;
1656 // Offer to receive audio/video if the constraint is not set and there are 1713 }
1657 // send streams, or we're currently receiving. 1714 if (video_index == -1 && offer_new_video_description) {
1658 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { 1715 session_options->media_description_options.push_back(
1659 session_options->recv_audio = 1716 cricket::MediaDescriptionOptions(
1660 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || 1717 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
1661 !remote_audio_tracks_.empty(); 1718 cricket::RtpTransceiverDirection(send_video, recv_video), false));
1662 } 1719 video_index = session_options->media_description_options.size() - 1;
1663 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { 1720 }
1664 session_options->recv_video = 1721 if (data_index == -1 && offer_new_data_description) {
1665 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || 1722 session_options->media_description_options.push_back(
1666 !remote_video_tracks_.empty(); 1723 cricket::MediaDescriptionOptions(
1667 } 1724 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
1725 cricket::RtpTransceiverDirection(true, true), false));
1726 data_index = session_options->media_description_options.size() - 1;
1727 }
1728
1729 cricket::MediaDescriptionOptions* audio_media_description_options =
1730 audio_index == -1
1731 ? nullptr
1732 : &session_options->media_description_options[audio_index];
1733 cricket::MediaDescriptionOptions* video_media_description_options =
1734 video_index == -1
1735 ? nullptr
1736 : &session_options->media_description_options[video_index];
1737 cricket::MediaDescriptionOptions* data_media_description_options =
1738 data_index == -1
1739 ? nullptr
1740 : &session_options->media_description_options[data_index];
1741
1742 // Apply ICE restart flag and renomination flag.
1743 for (auto& options : session_options->media_description_options) {
1744 options.transport_options.ice_restart = rtc_options.ice_restart;
1745 options.transport_options.enable_ice_renomination =
1746 configuration_.enable_ice_renomination;
1747 }
1748
1749 AddRtpSenderOptions(senders_, audio_media_description_options,
1750 video_media_description_options);
1751 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
1668 1752
1669 // Intentionally unset the data channel type for RTP data channel with the 1753 // Intentionally unset the data channel type for RTP data channel with the
1670 // second condition. Otherwise the RTP data channels would be successfully 1754 // second condition. Otherwise the RTP data channels would be successfully
1671 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail 1755 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail
1672 // when building with chromium. We want to leave RTP data channels broken, so 1756 // when building with chromium. We want to leave RTP data channels broken, so
1673 // people won't try to use them. 1757 // people won't try to use them.
1674 if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) { 1758 if (session_->data_channel_type() != cricket::DCT_RTP) {
1675 session_options->data_channel_type = session_->data_channel_type(); 1759 session_options->data_channel_type = session_->data_channel_type();
1676 } 1760 }
1677 1761
1678 session_options->bundle_enabled =
1679 session_options->bundle_enabled &&
1680 (session_options->has_audio() || session_options->has_video() ||
1681 session_options->has_data());
1682
1683 session_options->rtcp_cname = rtcp_cname_; 1762 session_options->rtcp_cname = rtcp_cname_;
1684 session_options->crypto_options = factory_->options().crypto_options; 1763 session_options->crypto_options = factory_->options().crypto_options;
1685 return true;
1686 } 1764 }
1687 1765
1688 void PeerConnection::InitializeOptionsForAnswer( 1766 void PeerConnection::GetOptionsForAnswer(
1767 const RTCOfferAnswerOptions& rtc_options,
1689 cricket::MediaSessionOptions* session_options) { 1768 cricket::MediaSessionOptions* session_options) {
1690 session_options->recv_audio = false; 1769 ExtractSharedMediaSessionOptions(rtc_options, session_options);
1691 session_options->recv_video = false; 1770
1692 session_options->enable_ice_renomination = 1771 // Figure out transceiver directional preferences.
1693 configuration_.enable_ice_renomination; 1772 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
1694 } 1773 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
1695 1774 // By default, generate sendrecv/recvonly m= sections.
Taylor Brandstetter 2017/07/28 19:00:25 I'd clarify that the generated direction will also
Zhi Huang 2017/08/02 04:38:36 Done.
1696 void PeerConnection::FinishOptionsForAnswer( 1775 bool recv_audio = true;
1697 cricket::MediaSessionOptions* session_options) { 1776 bool recv_video = true;
1698 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of 1777 // The "offer_to_receive_X" options allow those defaults to be overridden.
1699 // ContentInfos. 1778 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
1700 if (session_->remote_description()) { 1779 recv_audio = (rtc_options.offer_to_receive_audio > 0);
1701 // Initialize the transport_options map. 1780 }
1702 for (const cricket::ContentInfo& content : 1781 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
1703 session_->remote_description()->description()->contents()) { 1782 recv_video = (rtc_options.offer_to_receive_video > 0);
1704 session_options->transport_options[content.name] = 1783 }
1705 cricket::TransportOptions(); 1784
1785 int audio_index = -1;
1786 int video_index = -1;
1787 int data_index = -1;
1788 // There should be a pending remote description that's an offer...
1789 RTC_DCHECK(session_->remote_description());
1790 RTC_DCHECK(session_->remote_description()->type() ==
1791 SessionDescriptionInterface::kOffer);
1792 // Generate m= sections that match those in the offer.
1793 // Note that mediasession.cc will handle intersection our preferred direction
1794 // with the offered direction.
1795 for (const cricket::ContentInfo& content :
1796 session_->remote_description()->description()->contents()) {
1797 if (IsAudioContent(&content)) {
1798 // If we already have an audio m= section, reject this extra one.
1799 if (audio_index != -1) {
1800 session_options->media_description_options.push_back(
1801 cricket::MediaDescriptionOptions(
1802 cricket::MEDIA_TYPE_AUDIO, content.name,
1803 cricket::RtpTransceiverDirection(false, false), true));
1804 } else {
1805 session_options->media_description_options.push_back(
1806 cricket::MediaDescriptionOptions(
1807 cricket::MEDIA_TYPE_AUDIO, content.name,
1808 cricket::RtpTransceiverDirection(send_audio, recv_audio),
1809 !send_audio && !recv_audio));
1810 audio_index = session_options->media_description_options.size() - 1;
1811 }
1812 } else if (IsVideoContent(&content)) {
1813 // If we already have an video m= section, reject this extra one.
1814 if (video_index != -1) {
1815 session_options->media_description_options.push_back(
1816 cricket::MediaDescriptionOptions(
1817 cricket::MEDIA_TYPE_VIDEO, content.name,
1818 cricket::RtpTransceiverDirection(false, false), true));
1819 } else {
1820 session_options->media_description_options.push_back(
1821 cricket::MediaDescriptionOptions(
1822 cricket::MEDIA_TYPE_VIDEO, content.name,
1823 cricket::RtpTransceiverDirection(send_video, recv_video),
1824 !send_video && !recv_video));
1825 video_index = session_options->media_description_options.size() - 1;
1826 }
1827 } else {
1828 RTC_DCHECK(IsDataContent(&content));
1829 // If we already have an data m= section, reject this extra one.
1830 if (data_index != -1) {
1831 session_options->media_description_options.push_back(
1832 cricket::MediaDescriptionOptions(
1833 cricket::MEDIA_TYPE_DATA, content.name,
1834 cricket::RtpTransceiverDirection(false, false), true));
1835 } else {
1836 session_options->media_description_options.push_back(
1837 cricket::MediaDescriptionOptions(
1838 cricket::MEDIA_TYPE_DATA, content.name,
1839 // Direction for data sections is meaningless, but legacy
1840 // endpoints might expect sendrecv.
1841 cricket::RtpTransceiverDirection(true, true), false));
1842 data_index = session_options->media_description_options.size() - 1;
1843 }
1706 } 1844 }
1707 } 1845 }
1708 AddSendStreams(session_options, senders_, rtp_data_channels_); 1846
1709 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams 1847 cricket::MediaDescriptionOptions* audio_media_description_options =
1710 // are not signaled in the SDP so does not go through that path and must be 1848 audio_index == -1
1711 // handled here. 1849 ? nullptr
1850 : &session_options->media_description_options[audio_index];
1851 cricket::MediaDescriptionOptions* video_media_description_options =
1852 video_index == -1
1853 ? nullptr
1854 : &session_options->media_description_options[video_index];
1855 cricket::MediaDescriptionOptions* data_media_description_options =
1856 data_index == -1
1857 ? nullptr
1858 : &session_options->media_description_options[data_index];
Taylor Brandstetter 2017/07/28 19:00:25 nit: Something could probably be done to reduce du
Zhi Huang 2017/08/02 04:38:36 I think maybe the code in the for-loop can be opti
1859
1860 // Apply ICE renomination flag.
1861 for (auto& options : session_options->media_description_options) {
1862 options.transport_options.enable_ice_renomination =
1863 configuration_.enable_ice_renomination;
1864 }
1865
1866 AddRtpSenderOptions(senders_, audio_media_description_options,
1867 video_media_description_options);
1868 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
1869
1712 // Intentionally unset the data channel type for RTP data channel. Otherwise 1870 // Intentionally unset the data channel type for RTP data channel. Otherwise
1713 // the RTP data channels would be successfully negotiated by default and the 1871 // the RTP data channels would be successfully negotiated by default and the
1714 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. 1872 // unit tests in WebRtcDataBrowserTest will fail when building with chromium.
1715 // We want to leave RTP data channels broken, so people won't try to use them. 1873 // We want to leave RTP data channels broken, so people won't try to use them.
1716 if (session_->data_channel_type() != cricket::DCT_RTP) { 1874 if (session_->data_channel_type() != cricket::DCT_RTP) {
1717 session_options->data_channel_type = session_->data_channel_type(); 1875 session_options->data_channel_type = session_->data_channel_type();
1718 } 1876 }
1719 session_options->bundle_enabled = 1877 session_options->rtcp_cname = rtcp_cname_;
1720 session_options->bundle_enabled &&
1721 (session_options->has_audio() || session_options->has_video() ||
1722 session_options->has_data());
1723
1724 session_options->crypto_options = factory_->options().crypto_options; 1878 session_options->crypto_options = factory_->options().crypto_options;
1725 } 1879 }
1726 1880
1727 bool PeerConnection::GetOptionsForAnswer(
1728 const MediaConstraintsInterface* constraints,
1729 cricket::MediaSessionOptions* session_options) {
1730 InitializeOptionsForAnswer(session_options);
1731 if (!ParseConstraintsForAnswer(constraints, session_options)) {
1732 return false;
1733 }
1734 session_options->rtcp_cname = rtcp_cname_;
1735
1736 FinishOptionsForAnswer(session_options);
1737 return true;
1738 }
1739
1740 bool PeerConnection::GetOptionsForAnswer(
1741 const RTCOfferAnswerOptions& options,
1742 cricket::MediaSessionOptions* session_options) {
1743 InitializeOptionsForAnswer(session_options);
1744 if (!ExtractMediaSessionOptions(options, false, session_options)) {
1745 return false;
1746 }
1747 session_options->rtcp_cname = rtcp_cname_;
1748
1749 FinishOptionsForAnswer(session_options);
1750 return true;
1751 }
1752
1753 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { 1881 void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
1754 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); 1882 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type);
1755 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, 1883 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false,
1756 media_type, nullptr); 1884 media_type, nullptr);
1757 } 1885 }
1758 1886
1759 void PeerConnection::UpdateRemoteStreamsList( 1887 void PeerConnection::UpdateRemoteStreamsList(
1760 const cricket::StreamParamsVec& streams, 1888 const cricket::StreamParamsVec& streams,
1761 bool default_track_needed, 1889 bool default_track_needed,
1762 cricket::MediaType media_type, 1890 cricket::MediaType media_type,
(...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after
2213 if (!channel.get()) { 2341 if (!channel.get()) {
2214 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; 2342 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
2215 return; 2343 return;
2216 } 2344 }
2217 2345
2218 rtc::scoped_refptr<DataChannelInterface> proxy_channel = 2346 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
2219 DataChannelProxy::Create(signaling_thread(), channel); 2347 DataChannelProxy::Create(signaling_thread(), channel);
2220 observer_->OnDataChannel(std::move(proxy_channel)); 2348 observer_->OnDataChannel(std::move(proxy_channel));
2221 } 2349 }
2222 2350
2351 bool PeerConnection::HasRtpSender(cricket::MediaType type) const {
2352 return std::find_if(
2353 senders_.begin(), senders_.end(),
2354 [type](const rtc::scoped_refptr<
2355 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2356 return sender->media_type() == type;
2357 }) != senders_.end();
2358 }
2359
2223 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { 2360 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) {
2224 auto it = std::find_if( 2361 auto it = std::find_if(
2225 senders_.begin(), senders_.end(), 2362 senders_.begin(), senders_.end(),
2226 [id](const rtc::scoped_refptr< 2363 [id](const rtc::scoped_refptr<
2227 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { 2364 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2228 return sender->id() == id; 2365 return sender->id() == id;
2229 }); 2366 });
2230 return it != senders_.end() ? (*it)->internal() : nullptr; 2367 return it != senders_.end() ? (*it)->internal() : nullptr;
2231 } 2368 }
2232 2369
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
2368 return event_log_->StartLogging(file, max_size_bytes); 2505 return event_log_->StartLogging(file, max_size_bytes);
2369 } 2506 }
2370 2507
2371 void PeerConnection::StopRtcEventLog_w() { 2508 void PeerConnection::StopRtcEventLog_w() {
2372 if (event_log_) { 2509 if (event_log_) {
2373 event_log_->StopLogging(); 2510 event_log_->StopLogging();
2374 } 2511 }
2375 } 2512 }
2376 2513
2377 } // namespace webrtc 2514 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698