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

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

Issue 2991693002: Adding support for Unified Plan offer/answer negotiation. (Closed)
Patch Set: Fix the chromium win-clang bulid by replacing int with Optional<size_t>. 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
« no previous file with comments | « webrtc/pc/peerconnection.h ('k') | webrtc/pc/peerconnectioninterface_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
307 // Generate a RTCP CNAME when a PeerConnection is created. 320 // Generate a RTCP CNAME when a PeerConnection is created.
308 std::string GenerateRtcpCname() { 321 std::string GenerateRtcpCname() {
309 std::string cname; 322 std::string cname;
310 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) { 323 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) {
311 LOG(LS_ERROR) << "Failed to generate CNAME."; 324 LOG(LS_ERROR) << "Failed to generate CNAME.";
312 RTC_NOTREACHED(); 325 RTC_NOTREACHED();
313 } 326 }
314 return cname; 327 return cname;
315 } 328 }
316 329
317 bool ExtractMediaSessionOptions( 330 bool ValidateOfferAnswerOptions(
331 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options) {
332 return IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) &&
333 IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video);
334 }
335
336 // From |rtc_options|, fill parts of |session_options| shared by all generated
337 // m= sections (in other words, nothing that involves a map/array).
338 void ExtractSharedMediaSessionOptions(
318 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 339 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
319 bool is_offer,
320 cricket::MediaSessionOptions* session_options) { 340 cricket::MediaSessionOptions* session_options) {
321 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; 341 session_options->vad_enabled = rtc_options.voice_activity_detection;
322 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) || 342 session_options->bundle_enabled = rtc_options.use_rtp_mux;
323 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) { 343 }
324 return false; 344
345 bool ConvertConstraintsToOfferAnswerOptions(
346 const MediaConstraintsInterface* constraints,
347 PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) {
348 if (!constraints) {
349 return true;
325 } 350 }
326 351
327 // If constraints don't prevent us, we always accept video.
328 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
329 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0);
330 } else {
331 session_options->recv_audio = true;
332 }
333 // For offers, we only offer video if we have it or it's forced by options.
334 // For answers, we will always accept video (if offered).
335 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
336 session_options->recv_video = (rtc_options.offer_to_receive_video > 0);
337 } else if (is_offer) {
338 session_options->recv_video = false;
339 } else {
340 session_options->recv_video = true;
341 }
342
343 session_options->vad_enabled = rtc_options.voice_activity_detection;
344 session_options->bundle_enabled = rtc_options.use_rtp_mux;
345 for (auto& kv : session_options->transport_options) {
346 kv.second.ice_restart = rtc_options.ice_restart;
347 }
348
349 return true;
350 }
351
352 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints,
353 cricket::MediaSessionOptions* session_options) {
354 bool value = false; 352 bool value = false;
355 size_t mandatory_constraints_satisfied = 0; 353 size_t mandatory_constraints_satisfied = 0;
356 354
357 // kOfferToReceiveAudio defaults to true according to spec. 355 if (FindConstraint(constraints,
358 if (!FindConstraint(constraints, 356 MediaConstraintsInterface::kOfferToReceiveAudio, &value,
359 MediaConstraintsInterface::kOfferToReceiveAudio, &value, 357 &mandatory_constraints_satisfied)) {
360 &mandatory_constraints_satisfied) || 358 offer_answer_options->offer_to_receive_audio =
361 value) { 359 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
362 session_options->recv_audio = true; 360 kOfferToReceiveMediaTrue
363 } 361 : 0;
364
365 // kOfferToReceiveVideo defaults to false according to spec. But
366 // if it is an answer and video is offered, we should still accept video
367 // per default.
368 value = false;
369 if (!FindConstraint(constraints,
370 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
371 &mandatory_constraints_satisfied) ||
372 value) {
373 session_options->recv_video = true;
374 } 362 }
375 363
376 if (FindConstraint(constraints, 364 if (FindConstraint(constraints,
365 MediaConstraintsInterface::kOfferToReceiveVideo, &value,
366 &mandatory_constraints_satisfied)) {
367 offer_answer_options->offer_to_receive_video =
368 value ? PeerConnectionInterface::RTCOfferAnswerOptions::
369 kOfferToReceiveMediaTrue
370 : 0;
371 }
372 if (FindConstraint(constraints,
377 MediaConstraintsInterface::kVoiceActivityDetection, &value, 373 MediaConstraintsInterface::kVoiceActivityDetection, &value,
378 &mandatory_constraints_satisfied)) { 374 &mandatory_constraints_satisfied)) {
379 session_options->vad_enabled = value; 375 offer_answer_options->voice_activity_detection = value;
376 }
377 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
378 &mandatory_constraints_satisfied)) {
379 offer_answer_options->use_rtp_mux = value;
380 }
381 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
382 &value, &mandatory_constraints_satisfied)) {
383 offer_answer_options->ice_restart = value;
380 } 384 }
381 385
382 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value,
383 &mandatory_constraints_satisfied)) {
384 session_options->bundle_enabled = value;
385 } else {
386 // kUseRtpMux defaults to true according to spec.
387 session_options->bundle_enabled = true;
388 }
389
390 bool ice_restart = false;
391 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart,
392 &value, &mandatory_constraints_satisfied)) {
393 // kIceRestart defaults to false according to spec.
394 ice_restart = true;
395 }
396 for (auto& kv : session_options->transport_options) {
397 kv.second.ice_restart = ice_restart;
398 }
399
400 if (!constraints) {
401 return true;
402 }
403 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); 386 return mandatory_constraints_satisfied == constraints->GetMandatory().size();
404 } 387 }
405 388
406 PeerConnection::PeerConnection(PeerConnectionFactory* factory, 389 PeerConnection::PeerConnection(PeerConnectionFactory* factory,
407 std::unique_ptr<RtcEventLog> event_log, 390 std::unique_ptr<RtcEventLog> event_log,
408 std::unique_ptr<Call> call) 391 std::unique_ptr<Call> call)
409 : factory_(factory), 392 : factory_(factory),
410 observer_(NULL), 393 observer_(NULL),
411 uma_observer_(NULL), 394 uma_observer_(NULL),
412 event_log_(std::move(event_log)), 395 event_log_(std::move(event_log)),
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
835 return DataChannelProxy::Create(signaling_thread(), channel.get()); 818 return DataChannelProxy::Create(signaling_thread(), channel.get());
836 } 819 }
837 820
838 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 821 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
839 const MediaConstraintsInterface* constraints) { 822 const MediaConstraintsInterface* constraints) {
840 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 823 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
841 if (!observer) { 824 if (!observer) {
842 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 825 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
843 return; 826 return;
844 } 827 }
845 RTCOfferAnswerOptions options; 828 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
829 // Always create an offer even if |ConvertConstraintsToOfferAnswerOptions|
830 // returns false for now. Because |ConvertConstraintsToOfferAnswerOptions|
831 // compares the mandatory fields parsed with the mandatory fields added in the
832 // |constraints| and some downstream applications might create offers with
833 // mandatory fields which would not be parsed in the helper method. For
834 // example, in Chromium/remoting, |kEnableDtlsSrtp| is added to the
835 // |constraints| as a mandatory field but it is not parsed.
836 ConvertConstraintsToOfferAnswerOptions(constraints, &offer_answer_options);
846 837
847 bool value; 838 CreateOffer(observer, offer_answer_options);
848 size_t mandatory_constraints = 0;
849
850 if (FindConstraint(constraints,
851 MediaConstraintsInterface::kOfferToReceiveAudio,
852 &value,
853 &mandatory_constraints)) {
854 options.offer_to_receive_audio =
855 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
856 }
857
858 if (FindConstraint(constraints,
859 MediaConstraintsInterface::kOfferToReceiveVideo,
860 &value,
861 &mandatory_constraints)) {
862 options.offer_to_receive_video =
863 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
864 }
865
866 if (FindConstraint(constraints,
867 MediaConstraintsInterface::kVoiceActivityDetection,
868 &value,
869 &mandatory_constraints)) {
870 options.voice_activity_detection = value;
871 }
872
873 if (FindConstraint(constraints,
874 MediaConstraintsInterface::kIceRestart,
875 &value,
876 &mandatory_constraints)) {
877 options.ice_restart = value;
878 }
879
880 if (FindConstraint(constraints,
881 MediaConstraintsInterface::kUseRtpMux,
882 &value,
883 &mandatory_constraints)) {
884 options.use_rtp_mux = value;
885 }
886
887 CreateOffer(observer, options);
888 } 839 }
889 840
890 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 841 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
891 const RTCOfferAnswerOptions& options) { 842 const RTCOfferAnswerOptions& options) {
892 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 843 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
893 if (!observer) { 844 if (!observer) {
894 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 845 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
895 return; 846 return;
896 } 847 }
897 848
898 cricket::MediaSessionOptions session_options; 849 if (!ValidateOfferAnswerOptions(options)) {
899 if (!GetOptionsForOffer(options, &session_options)) {
900 std::string error = "CreateOffer called with invalid options."; 850 std::string error = "CreateOffer called with invalid options.";
901 LOG(LS_ERROR) << error; 851 LOG(LS_ERROR) << error;
902 PostCreateSessionDescriptionFailure(observer, error); 852 PostCreateSessionDescriptionFailure(observer, error);
903 return; 853 return;
904 } 854 }
905 855
856 cricket::MediaSessionOptions session_options;
857 GetOptionsForOffer(options, &session_options);
906 session_->CreateOffer(observer, options, session_options); 858 session_->CreateOffer(observer, options, session_options);
907 } 859 }
908 860
909 void PeerConnection::CreateAnswer( 861 void PeerConnection::CreateAnswer(
910 CreateSessionDescriptionObserver* observer, 862 CreateSessionDescriptionObserver* observer,
911 const MediaConstraintsInterface* constraints) { 863 const MediaConstraintsInterface* constraints) {
912 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 864 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
913 if (!observer) { 865 if (!observer) {
914 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 866 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
915 return; 867 return;
916 } 868 }
917 869
918 cricket::MediaSessionOptions session_options; 870 if (!session_->remote_description() ||
919 if (!GetOptionsForAnswer(constraints, &session_options)) { 871 session_->remote_description()->type() !=
872 SessionDescriptionInterface::kOffer) {
873 std::string error = "CreateAnswer called without remote offer.";
874 LOG(LS_ERROR) << error;
875 PostCreateSessionDescriptionFailure(observer, error);
876 return;
877 }
878
879 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
880 if (!ConvertConstraintsToOfferAnswerOptions(constraints,
881 &offer_answer_options)) {
920 std::string error = "CreateAnswer called with invalid constraints."; 882 std::string error = "CreateAnswer called with invalid constraints.";
921 LOG(LS_ERROR) << error; 883 LOG(LS_ERROR) << error;
922 PostCreateSessionDescriptionFailure(observer, error); 884 PostCreateSessionDescriptionFailure(observer, error);
923 return; 885 return;
924 } 886 }
925 887
888 cricket::MediaSessionOptions session_options;
889 GetOptionsForAnswer(offer_answer_options, &session_options);
926 session_->CreateAnswer(observer, session_options); 890 session_->CreateAnswer(observer, session_options);
927 } 891 }
928 892
929 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, 893 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
930 const RTCOfferAnswerOptions& options) { 894 const RTCOfferAnswerOptions& options) {
931 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 895 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
932 if (!observer) { 896 if (!observer) {
933 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 897 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
934 return; 898 return;
935 } 899 }
936 900
937 cricket::MediaSessionOptions session_options; 901 cricket::MediaSessionOptions session_options;
938 if (!GetOptionsForAnswer(options, &session_options)) { 902 GetOptionsForAnswer(options, &session_options);
939 std::string error = "CreateAnswer called with invalid options.";
940 LOG(LS_ERROR) << error;
941 PostCreateSessionDescriptionFailure(observer, error);
942 return;
943 }
944 903
945 session_->CreateAnswer(observer, session_options); 904 session_->CreateAnswer(observer, session_options);
946 } 905 }
947 906
948 void PeerConnection::SetLocalDescription( 907 void PeerConnection::SetLocalDescription(
949 SetSessionDescriptionObserver* observer, 908 SetSessionDescriptionObserver* observer,
950 SessionDescriptionInterface* desc) { 909 SessionDescriptionInterface* desc) {
951 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); 910 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
952 if (IsClosed()) { 911 if (IsClosed()) {
953 return; 912 return;
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 1650
1692 void PeerConnection::PostCreateSessionDescriptionFailure( 1651 void PeerConnection::PostCreateSessionDescriptionFailure(
1693 CreateSessionDescriptionObserver* observer, 1652 CreateSessionDescriptionObserver* observer,
1694 const std::string& error) { 1653 const std::string& error) {
1695 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); 1654 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
1696 msg->error = error; 1655 msg->error = error;
1697 signaling_thread()->Post(RTC_FROM_HERE, this, 1656 signaling_thread()->Post(RTC_FROM_HERE, this,
1698 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); 1657 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
1699 } 1658 }
1700 1659
1701 bool PeerConnection::GetOptionsForOffer( 1660 void PeerConnection::GetOptionsForOffer(
1702 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 1661 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
1703 cricket::MediaSessionOptions* session_options) { 1662 cricket::MediaSessionOptions* session_options) {
1704 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of 1663 ExtractSharedMediaSessionOptions(rtc_options, session_options);
1705 // ContentInfos. 1664
1665 // Figure out transceiver directional preferences.
1666 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
1667 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
1668
1669 // By default, generate sendrecv/recvonly m= sections.
1670 bool recv_audio = true;
1671 bool recv_video = true;
1672
1673 // By default, only offer a new m= section if we have media to send with it.
1674 bool offer_new_audio_description = send_audio;
1675 bool offer_new_video_description = send_video;
1676 bool offer_new_data_description = HasDataChannels();
1677
1678 // The "offer_to_receive_X" options allow those defaults to be overridden.
1679 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
1680 recv_audio = (rtc_options.offer_to_receive_audio > 0);
1681 offer_new_audio_description =
1682 offer_new_audio_description || (rtc_options.offer_to_receive_audio > 0);
1683 }
1684 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
1685 recv_video = (rtc_options.offer_to_receive_video > 0);
1686 offer_new_video_description =
1687 offer_new_video_description || (rtc_options.offer_to_receive_video > 0);
1688 }
1689
1690 rtc::Optional<size_t> audio_index;
1691 rtc::Optional<size_t> video_index;
1692 rtc::Optional<size_t> data_index;
1693 // If a current description exists, generate m= sections in the same order,
1694 // using the first audio/video/data section that appears and rejecting
1695 // extraneous ones.
1706 if (session_->local_description()) { 1696 if (session_->local_description()) {
1707 for (const cricket::ContentInfo& content : 1697 GenerateMediaDescriptionOptions(
1708 session_->local_description()->description()->contents()) { 1698 session_->local_description(),
1709 session_options->transport_options[content.name] = 1699 cricket::RtpTransceiverDirection(send_audio, recv_audio),
1710 cricket::TransportOptions(); 1700 cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index,
1711 } 1701 &video_index, &data_index, session_options);
1712 } 1702 }
1713 session_options->enable_ice_renomination = 1703
1714 configuration_.enable_ice_renomination; 1704 // Add audio/video/data m= sections to the end if needed.
1715 1705 if (!audio_index && offer_new_audio_description) {
1716 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) { 1706 session_options->media_description_options.push_back(
1717 return false; 1707 cricket::MediaDescriptionOptions(
1718 } 1708 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
1719 1709 cricket::RtpTransceiverDirection(send_audio, recv_audio), false));
1720 AddSendStreams(session_options, senders_, rtp_data_channels_); 1710 audio_index = rtc::Optional<size_t>(
1721 // Offer to receive audio/video if the constraint is not set and there are 1711 session_options->media_description_options.size() - 1);
1722 // send streams, or we're currently receiving. 1712 }
1723 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { 1713 if (!video_index && offer_new_video_description) {
1724 session_options->recv_audio = 1714 session_options->media_description_options.push_back(
1725 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || 1715 cricket::MediaDescriptionOptions(
1726 !remote_audio_tracks_.empty(); 1716 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
1727 } 1717 cricket::RtpTransceiverDirection(send_video, recv_video), false));
1728 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { 1718 video_index = rtc::Optional<size_t>(
1729 session_options->recv_video = 1719 session_options->media_description_options.size() - 1);
1730 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || 1720 }
1731 !remote_video_tracks_.empty(); 1721 if (!data_index && offer_new_data_description) {
1732 } 1722 session_options->media_description_options.push_back(
1723 cricket::MediaDescriptionOptions(
1724 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
1725 cricket::RtpTransceiverDirection(true, true), false));
1726 data_index = rtc::Optional<size_t>(
1727 session_options->media_description_options.size() - 1);
1728 }
1729
1730 cricket::MediaDescriptionOptions* audio_media_description_options =
1731 !audio_index ? nullptr
1732 : &session_options->media_description_options[*audio_index];
1733 cricket::MediaDescriptionOptions* video_media_description_options =
1734 !video_index ? nullptr
1735 : &session_options->media_description_options[*video_index];
1736 cricket::MediaDescriptionOptions* data_media_description_options =
1737 !data_index ? nullptr
1738 : &session_options->media_description_options[*data_index];
1739
1740 // Apply ICE restart flag and renomination flag.
1741 for (auto& options : session_options->media_description_options) {
1742 options.transport_options.ice_restart = rtc_options.ice_restart;
1743 options.transport_options.enable_ice_renomination =
1744 configuration_.enable_ice_renomination;
1745 }
1746
1747 AddRtpSenderOptions(senders_, audio_media_description_options,
1748 video_media_description_options);
1749 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
1733 1750
1734 // Intentionally unset the data channel type for RTP data channel with the 1751 // Intentionally unset the data channel type for RTP data channel with the
1735 // second condition. Otherwise the RTP data channels would be successfully 1752 // second condition. Otherwise the RTP data channels would be successfully
1736 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail 1753 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail
1737 // when building with chromium. We want to leave RTP data channels broken, so 1754 // when building with chromium. We want to leave RTP data channels broken, so
1738 // people won't try to use them. 1755 // people won't try to use them.
1739 if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) { 1756 if (!rtp_data_channels_.empty() ||
1757 session_->data_channel_type() != cricket::DCT_RTP) {
1740 session_options->data_channel_type = session_->data_channel_type(); 1758 session_options->data_channel_type = session_->data_channel_type();
1741 } 1759 }
1742 1760
1743 session_options->bundle_enabled =
1744 session_options->bundle_enabled &&
1745 (session_options->has_audio() || session_options->has_video() ||
1746 session_options->has_data());
1747
1748 session_options->rtcp_cname = rtcp_cname_; 1761 session_options->rtcp_cname = rtcp_cname_;
1749 session_options->crypto_options = factory_->options().crypto_options; 1762 session_options->crypto_options = factory_->options().crypto_options;
1750 return true; 1763 }
1751 } 1764
1752 1765 void PeerConnection::GetOptionsForAnswer(
1753 void PeerConnection::InitializeOptionsForAnswer( 1766 const RTCOfferAnswerOptions& rtc_options,
1754 cricket::MediaSessionOptions* session_options) { 1767 cricket::MediaSessionOptions* session_options) {
1755 session_options->recv_audio = false; 1768 ExtractSharedMediaSessionOptions(rtc_options, session_options);
1756 session_options->recv_video = false; 1769
1757 session_options->enable_ice_renomination = 1770 // Figure out transceiver directional preferences.
1758 configuration_.enable_ice_renomination; 1771 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
1759 } 1772 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
1760 1773
1761 void PeerConnection::FinishOptionsForAnswer( 1774 // By default, generate sendrecv/recvonly m= sections. The direction is also
1762 cricket::MediaSessionOptions* session_options) { 1775 // restricted by the direction in the offer.
1763 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of 1776 bool recv_audio = true;
1764 // ContentInfos. 1777 bool recv_video = true;
1765 if (session_->remote_description()) { 1778
1766 // Initialize the transport_options map. 1779 // The "offer_to_receive_X" options allow those defaults to be overridden.
1767 for (const cricket::ContentInfo& content : 1780 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
1768 session_->remote_description()->description()->contents()) { 1781 recv_audio = (rtc_options.offer_to_receive_audio > 0);
1769 session_options->transport_options[content.name] = 1782 }
1770 cricket::TransportOptions(); 1783 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
1771 } 1784 recv_video = (rtc_options.offer_to_receive_video > 0);
1772 } 1785 }
1773 AddSendStreams(session_options, senders_, rtp_data_channels_); 1786
1774 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams 1787 rtc::Optional<size_t> audio_index;
1775 // are not signaled in the SDP so does not go through that path and must be 1788 rtc::Optional<size_t> video_index;
1776 // handled here. 1789 rtc::Optional<size_t> data_index;
1790 // There should be a pending remote description that's an offer...
1791 RTC_DCHECK(session_->remote_description());
1792 RTC_DCHECK(session_->remote_description()->type() ==
1793 SessionDescriptionInterface::kOffer);
1794 // Generate m= sections that match those in the offer.
1795 // Note that mediasession.cc will handle intersection our preferred direction
1796 // with the offered direction.
1797 GenerateMediaDescriptionOptions(
1798 session_->remote_description(),
1799 cricket::RtpTransceiverDirection(send_audio, recv_audio),
1800 cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index,
1801 &video_index, &data_index, session_options);
1802
1803 cricket::MediaDescriptionOptions* audio_media_description_options =
1804 !audio_index ? nullptr
1805 : &session_options->media_description_options[*audio_index];
1806 cricket::MediaDescriptionOptions* video_media_description_options =
1807 !video_index ? nullptr
1808 : &session_options->media_description_options[*video_index];
1809 cricket::MediaDescriptionOptions* data_media_description_options =
1810 !data_index ? nullptr
1811 : &session_options->media_description_options[*data_index];
1812
1813 // Apply ICE renomination flag.
1814 for (auto& options : session_options->media_description_options) {
1815 options.transport_options.enable_ice_renomination =
1816 configuration_.enable_ice_renomination;
1817 }
1818
1819 AddRtpSenderOptions(senders_, audio_media_description_options,
1820 video_media_description_options);
1821 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
1822
1777 // Intentionally unset the data channel type for RTP data channel. Otherwise 1823 // Intentionally unset the data channel type for RTP data channel. Otherwise
1778 // the RTP data channels would be successfully negotiated by default and the 1824 // the RTP data channels would be successfully negotiated by default and the
1779 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. 1825 // unit tests in WebRtcDataBrowserTest will fail when building with chromium.
1780 // We want to leave RTP data channels broken, so people won't try to use them. 1826 // We want to leave RTP data channels broken, so people won't try to use them.
1781 if (session_->data_channel_type() != cricket::DCT_RTP) { 1827 if (!rtp_data_channels_.empty() ||
1828 session_->data_channel_type() != cricket::DCT_RTP) {
1782 session_options->data_channel_type = session_->data_channel_type(); 1829 session_options->data_channel_type = session_->data_channel_type();
1783 } 1830 }
1784 session_options->bundle_enabled = 1831
1785 session_options->bundle_enabled && 1832 session_options->rtcp_cname = rtcp_cname_;
1786 (session_options->has_audio() || session_options->has_video() ||
1787 session_options->has_data());
1788
1789 session_options->crypto_options = factory_->options().crypto_options; 1833 session_options->crypto_options = factory_->options().crypto_options;
1790 } 1834 }
1791 1835
1792 bool PeerConnection::GetOptionsForAnswer( 1836 void PeerConnection::GenerateMediaDescriptionOptions(
1793 const MediaConstraintsInterface* constraints, 1837 const SessionDescriptionInterface* session_desc,
1838 cricket::RtpTransceiverDirection audio_direction,
1839 cricket::RtpTransceiverDirection video_direction,
1840 rtc::Optional<size_t>* audio_index,
1841 rtc::Optional<size_t>* video_index,
1842 rtc::Optional<size_t>* data_index,
1794 cricket::MediaSessionOptions* session_options) { 1843 cricket::MediaSessionOptions* session_options) {
1795 InitializeOptionsForAnswer(session_options); 1844 for (const cricket::ContentInfo& content :
1796 if (!ParseConstraintsForAnswer(constraints, session_options)) { 1845 session_desc->description()->contents()) {
1797 return false; 1846 if (IsAudioContent(&content)) {
1798 } 1847 // If we already have an audio m= section, reject this extra one.
1799 session_options->rtcp_cname = rtcp_cname_; 1848 if (*audio_index) {
1800 1849 session_options->media_description_options.push_back(
1801 FinishOptionsForAnswer(session_options); 1850 cricket::MediaDescriptionOptions(
1802 return true; 1851 cricket::MEDIA_TYPE_AUDIO, content.name,
1803 } 1852 cricket::RtpTransceiverDirection(false, false), true));
1804 1853 } else {
1805 bool PeerConnection::GetOptionsForAnswer( 1854 session_options->media_description_options.push_back(
1806 const RTCOfferAnswerOptions& options, 1855 cricket::MediaDescriptionOptions(
1807 cricket::MediaSessionOptions* session_options) { 1856 cricket::MEDIA_TYPE_AUDIO, content.name, audio_direction,
1808 InitializeOptionsForAnswer(session_options); 1857 !audio_direction.send && !audio_direction.recv));
1809 if (!ExtractMediaSessionOptions(options, false, session_options)) { 1858 *audio_index = rtc::Optional<size_t>(
1810 return false; 1859 session_options->media_description_options.size() - 1);
1811 } 1860 }
1812 session_options->rtcp_cname = rtcp_cname_; 1861 } else if (IsVideoContent(&content)) {
1813 1862 // If we already have an video m= section, reject this extra one.
1814 FinishOptionsForAnswer(session_options); 1863 if (*video_index) {
1815 return true; 1864 session_options->media_description_options.push_back(
1865 cricket::MediaDescriptionOptions(
1866 cricket::MEDIA_TYPE_VIDEO, content.name,
1867 cricket::RtpTransceiverDirection(false, false), true));
1868 } else {
1869 session_options->media_description_options.push_back(
1870 cricket::MediaDescriptionOptions(
1871 cricket::MEDIA_TYPE_VIDEO, content.name, video_direction,
1872 !video_direction.send && !video_direction.recv));
1873 *video_index = rtc::Optional<size_t>(
1874 session_options->media_description_options.size() - 1);
1875 }
1876 } else {
1877 RTC_DCHECK(IsDataContent(&content));
1878 // If we already have an data m= section, reject this extra one.
1879 if (*data_index) {
1880 session_options->media_description_options.push_back(
1881 cricket::MediaDescriptionOptions(
1882 cricket::MEDIA_TYPE_DATA, content.name,
1883 cricket::RtpTransceiverDirection(false, false), true));
1884 } else {
1885 session_options->media_description_options.push_back(
1886 cricket::MediaDescriptionOptions(
1887 cricket::MEDIA_TYPE_DATA, content.name,
1888 // Direction for data sections is meaningless, but legacy
1889 // endpoints might expect sendrecv.
1890 cricket::RtpTransceiverDirection(true, true), false));
1891 *data_index = rtc::Optional<size_t>(
1892 session_options->media_description_options.size() - 1);
1893 }
1894 }
1895 }
1816 } 1896 }
1817 1897
1818 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { 1898 void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
1819 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); 1899 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type);
1820 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, 1900 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false,
1821 media_type, nullptr); 1901 media_type, nullptr);
1822 } 1902 }
1823 1903
1824 void PeerConnection::UpdateRemoteStreamsList( 1904 void PeerConnection::UpdateRemoteStreamsList(
1825 const cricket::StreamParamsVec& streams, 1905 const cricket::StreamParamsVec& streams,
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 if (!channel.get()) { 2358 if (!channel.get()) {
2279 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; 2359 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
2280 return; 2360 return;
2281 } 2361 }
2282 2362
2283 rtc::scoped_refptr<DataChannelInterface> proxy_channel = 2363 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
2284 DataChannelProxy::Create(signaling_thread(), channel); 2364 DataChannelProxy::Create(signaling_thread(), channel);
2285 observer_->OnDataChannel(std::move(proxy_channel)); 2365 observer_->OnDataChannel(std::move(proxy_channel));
2286 } 2366 }
2287 2367
2368 bool PeerConnection::HasRtpSender(cricket::MediaType type) const {
2369 return std::find_if(
2370 senders_.begin(), senders_.end(),
2371 [type](const rtc::scoped_refptr<
2372 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2373 return sender->media_type() == type;
2374 }) != senders_.end();
2375 }
2376
2288 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { 2377 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) {
2289 auto it = std::find_if( 2378 auto it = std::find_if(
2290 senders_.begin(), senders_.end(), 2379 senders_.begin(), senders_.end(),
2291 [id](const rtc::scoped_refptr< 2380 [id](const rtc::scoped_refptr<
2292 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { 2381 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2293 return sender->id() == id; 2382 return sender->id() == id;
2294 }); 2383 });
2295 return it != senders_.end() ? (*it)->internal() : nullptr; 2384 return it != senders_.end() ? (*it)->internal() : nullptr;
2296 } 2385 }
2297 2386
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2434 return event_log_->StartLogging(file, max_size_bytes); 2523 return event_log_->StartLogging(file, max_size_bytes);
2435 } 2524 }
2436 2525
2437 void PeerConnection::StopRtcEventLog_w() { 2526 void PeerConnection::StopRtcEventLog_w() {
2438 if (event_log_) { 2527 if (event_log_) {
2439 event_log_->StopLogging(); 2528 event_log_->StopLogging();
2440 } 2529 }
2441 } 2530 }
2442 2531
2443 } // namespace webrtc 2532 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/pc/peerconnection.h ('k') | webrtc/pc/peerconnectioninterface_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698