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

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

Issue 2991693002: Adding support for Unified Plan offer/answer negotiation. (Closed)
Patch Set: address review comments 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 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;
846 829 if (!ConvertConstraintsToOfferAnswerOptions(constraints,
847 bool value; 830 &offer_answer_options)) {
848 size_t mandatory_constraints = 0; 831 std::string error = "CreateOffer called with invalid constraints.";
849 832 LOG(LS_ERROR) << error;
850 if (FindConstraint(constraints, 833 PostCreateSessionDescriptionFailure(observer, error);
851 MediaConstraintsInterface::kOfferToReceiveAudio, 834 return;
852 &value,
853 &mandatory_constraints)) {
854 options.offer_to_receive_audio =
855 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0;
856 } 835 }
857 836
858 if (FindConstraint(constraints, 837 CreateOffer(observer, offer_answer_options);
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 } 838 }
889 839
890 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, 840 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer,
891 const RTCOfferAnswerOptions& options) { 841 const RTCOfferAnswerOptions& options) {
892 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); 842 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer");
893 if (!observer) { 843 if (!observer) {
894 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; 844 LOG(LS_ERROR) << "CreateOffer - observer is NULL.";
895 return; 845 return;
896 } 846 }
897 847
898 cricket::MediaSessionOptions session_options; 848 if (!ValidateOfferAnswerOptions(options)) {
899 if (!GetOptionsForOffer(options, &session_options)) {
900 std::string error = "CreateOffer called with invalid options."; 849 std::string error = "CreateOffer called with invalid options.";
901 LOG(LS_ERROR) << error; 850 LOG(LS_ERROR) << error;
902 PostCreateSessionDescriptionFailure(observer, error); 851 PostCreateSessionDescriptionFailure(observer, error);
903 return; 852 return;
904 } 853 }
905 854
855 cricket::MediaSessionOptions session_options;
856 GetOptionsForOffer(options, &session_options);
906 session_->CreateOffer(observer, options, session_options); 857 session_->CreateOffer(observer, options, session_options);
907 } 858 }
908 859
909 void PeerConnection::CreateAnswer( 860 void PeerConnection::CreateAnswer(
910 CreateSessionDescriptionObserver* observer, 861 CreateSessionDescriptionObserver* observer,
911 const MediaConstraintsInterface* constraints) { 862 const MediaConstraintsInterface* constraints) {
912 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 863 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
913 if (!observer) { 864 if (!observer) {
914 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 865 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
915 return; 866 return;
916 } 867 }
917 868
918 cricket::MediaSessionOptions session_options; 869 if (!session_->remote_description() ||
919 if (!GetOptionsForAnswer(constraints, &session_options)) { 870 session_->remote_description()->type() !=
871 SessionDescriptionInterface::kOffer) {
872 std::string error = "CreateAnswer called without remote offer.";
873 LOG(LS_ERROR) << error;
874 PostCreateSessionDescriptionFailure(observer, error);
875 return;
876 }
877
878 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options;
879 if (!ConvertConstraintsToOfferAnswerOptions(constraints,
880 &offer_answer_options)) {
920 std::string error = "CreateAnswer called with invalid constraints."; 881 std::string error = "CreateAnswer called with invalid constraints.";
921 LOG(LS_ERROR) << error; 882 LOG(LS_ERROR) << error;
922 PostCreateSessionDescriptionFailure(observer, error); 883 PostCreateSessionDescriptionFailure(observer, error);
923 return; 884 return;
924 } 885 }
925 886
887 cricket::MediaSessionOptions session_options;
888 GetOptionsForAnswer(offer_answer_options, &session_options);
926 session_->CreateAnswer(observer, session_options); 889 session_->CreateAnswer(observer, session_options);
927 } 890 }
928 891
929 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, 892 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer,
930 const RTCOfferAnswerOptions& options) { 893 const RTCOfferAnswerOptions& options) {
931 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); 894 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer");
932 if (!observer) { 895 if (!observer) {
933 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; 896 LOG(LS_ERROR) << "CreateAnswer - observer is NULL.";
934 return; 897 return;
935 } 898 }
936 899
937 cricket::MediaSessionOptions session_options; 900 cricket::MediaSessionOptions session_options;
938 if (!GetOptionsForAnswer(options, &session_options)) { 901 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 902
945 session_->CreateAnswer(observer, session_options); 903 session_->CreateAnswer(observer, session_options);
946 } 904 }
947 905
948 void PeerConnection::SetLocalDescription( 906 void PeerConnection::SetLocalDescription(
949 SetSessionDescriptionObserver* observer, 907 SetSessionDescriptionObserver* observer,
950 SessionDescriptionInterface* desc) { 908 SessionDescriptionInterface* desc) {
951 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); 909 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription");
952 if (IsClosed()) { 910 if (IsClosed()) {
953 return; 911 return;
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after
1691 1649
1692 void PeerConnection::PostCreateSessionDescriptionFailure( 1650 void PeerConnection::PostCreateSessionDescriptionFailure(
1693 CreateSessionDescriptionObserver* observer, 1651 CreateSessionDescriptionObserver* observer,
1694 const std::string& error) { 1652 const std::string& error) {
1695 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); 1653 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer);
1696 msg->error = error; 1654 msg->error = error;
1697 signaling_thread()->Post(RTC_FROM_HERE, this, 1655 signaling_thread()->Post(RTC_FROM_HERE, this,
1698 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); 1656 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg);
1699 } 1657 }
1700 1658
1701 bool PeerConnection::GetOptionsForOffer( 1659 void PeerConnection::GetOptionsForOffer(
1702 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, 1660 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options,
1703 cricket::MediaSessionOptions* session_options) { 1661 cricket::MediaSessionOptions* session_options) {
1704 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of 1662 ExtractSharedMediaSessionOptions(rtc_options, session_options);
1705 // ContentInfos. 1663
1706 if (session_->local_description()) { 1664 // Figure out transceiver directional preferences.
1707 for (const cricket::ContentInfo& content : 1665 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
1708 session_->local_description()->description()->contents()) { 1666 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
1709 session_options->transport_options[content.name] = 1667
1710 cricket::TransportOptions(); 1668 // By default, generate sendrecv/recvonly m= sections.
1711 } 1669 bool recv_audio = true;
1670 bool recv_video = true;
1671
1672 // By default, only offer a new m= section if we have media to send with it.
1673 bool offer_new_audio_description = send_audio;
1674 bool offer_new_video_description = send_video;
1675 bool offer_new_data_description = HasDataChannels();
1676
1677 // The "offer_to_receive_X" options allow those defaults to be overridden.
1678 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
1679 recv_audio = (rtc_options.offer_to_receive_audio > 0);
1680 offer_new_audio_description = (rtc_options.offer_to_receive_audio > 0);
1712 } 1681 }
1713 session_options->enable_ice_renomination = 1682 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
1714 configuration_.enable_ice_renomination; 1683 recv_video = (rtc_options.offer_to_receive_video > 0);
1715 1684 offer_new_video_description = (rtc_options.offer_to_receive_video > 0);
1716 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) {
1717 return false;
1718 } 1685 }
1719 1686
1720 AddSendStreams(session_options, senders_, rtp_data_channels_); 1687 int audio_index = -1;
1721 // Offer to receive audio/video if the constraint is not set and there are 1688 int video_index = -1;
1722 // send streams, or we're currently receiving. 1689 int data_index = -1;
1723 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { 1690 // If a current description exists, generate m= sections in the same order,
1724 session_options->recv_audio = 1691 // using the first audio/video/data section that appears and rejecting
1725 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || 1692 // extraneous ones.
1726 !remote_audio_tracks_.empty(); 1693 if (session_->local_description()) {
1694 GenerateMediaDescrptionOptions(
Taylor Brandstetter 2017/08/03 00:24:48 nit: "Description" is missing an "i".
Zhi Huang 2017/08/04 18:38:25 Done.
1695 session_->local_description(),
1696 cricket::RtpTransceiverDirection(send_audio, recv_audio),
1697 cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index,
1698 &video_index, &data_index, session_options);
1727 } 1699 }
1728 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { 1700
1729 session_options->recv_video = 1701 // Add audio/video/data m= sections to the end if needed.
1730 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || 1702 if (audio_index == -1 && offer_new_audio_description) {
1731 !remote_video_tracks_.empty(); 1703 session_options->media_description_options.push_back(
1704 cricket::MediaDescriptionOptions(
1705 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO,
1706 cricket::RtpTransceiverDirection(send_audio, recv_audio), false));
1707 audio_index = session_options->media_description_options.size() - 1;
1732 } 1708 }
1709 if (video_index == -1 && offer_new_video_description) {
1710 session_options->media_description_options.push_back(
1711 cricket::MediaDescriptionOptions(
1712 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO,
1713 cricket::RtpTransceiverDirection(send_video, recv_video), false));
1714 video_index = session_options->media_description_options.size() - 1;
1715 }
1716 if (data_index == -1 && offer_new_data_description) {
1717 session_options->media_description_options.push_back(
1718 cricket::MediaDescriptionOptions(
1719 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA,
1720 cricket::RtpTransceiverDirection(true, true), false));
1721 data_index = session_options->media_description_options.size() - 1;
1722 }
1723
1724 cricket::MediaDescriptionOptions* audio_media_description_options =
1725 audio_index == -1
1726 ? nullptr
1727 : &session_options->media_description_options[audio_index];
1728 cricket::MediaDescriptionOptions* video_media_description_options =
1729 video_index == -1
1730 ? nullptr
1731 : &session_options->media_description_options[video_index];
1732 cricket::MediaDescriptionOptions* data_media_description_options =
1733 data_index == -1
1734 ? nullptr
1735 : &session_options->media_description_options[data_index];
1736
1737 // Apply ICE restart flag and renomination flag.
1738 for (auto& options : session_options->media_description_options) {
1739 options.transport_options.ice_restart = rtc_options.ice_restart;
1740 options.transport_options.enable_ice_renomination =
1741 configuration_.enable_ice_renomination;
1742 }
1743
1744 AddRtpSenderOptions(senders_, audio_media_description_options,
1745 video_media_description_options);
1746 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
1733 1747
1734 // Intentionally unset the data channel type for RTP data channel with the 1748 // Intentionally unset the data channel type for RTP data channel with the
1735 // second condition. Otherwise the RTP data channels would be successfully 1749 // second condition. Otherwise the RTP data channels would be successfully
1736 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail 1750 // 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 1751 // when building with chromium. We want to leave RTP data channels broken, so
1738 // people won't try to use them. 1752 // people won't try to use them.
1739 if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) { 1753 if (session_->data_channel_type() != cricket::DCT_RTP) {
1740 session_options->data_channel_type = session_->data_channel_type(); 1754 session_options->data_channel_type = session_->data_channel_type();
1741 } 1755 }
1742 1756
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_; 1757 session_options->rtcp_cname = rtcp_cname_;
1749 session_options->crypto_options = factory_->options().crypto_options; 1758 session_options->crypto_options = factory_->options().crypto_options;
1750 return true;
1751 } 1759 }
1752 1760
1753 void PeerConnection::InitializeOptionsForAnswer( 1761 void PeerConnection::GetOptionsForAnswer(
1762 const RTCOfferAnswerOptions& rtc_options,
1754 cricket::MediaSessionOptions* session_options) { 1763 cricket::MediaSessionOptions* session_options) {
1755 session_options->recv_audio = false; 1764 ExtractSharedMediaSessionOptions(rtc_options, session_options);
1756 session_options->recv_video = false;
1757 session_options->enable_ice_renomination =
1758 configuration_.enable_ice_renomination;
1759 }
1760 1765
1761 void PeerConnection::FinishOptionsForAnswer( 1766 // Figure out transceiver directional preferences.
1762 cricket::MediaSessionOptions* session_options) { 1767 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO);
1763 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of 1768 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO);
1764 // ContentInfos. 1769
1765 if (session_->remote_description()) { 1770 // By default, generate sendrecv/recvonly m= sections. The direction is also
1766 // Initialize the transport_options map. 1771 // restricted by the direction in the offer.
1767 for (const cricket::ContentInfo& content : 1772 bool recv_audio = true;
1768 session_->remote_description()->description()->contents()) { 1773 bool recv_video = true;
1769 session_options->transport_options[content.name] = 1774
1770 cricket::TransportOptions(); 1775 // The "offer_to_receive_X" options allow those defaults to be overridden.
1771 } 1776 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) {
1777 recv_audio = (rtc_options.offer_to_receive_audio > 0);
1772 } 1778 }
1773 AddSendStreams(session_options, senders_, rtp_data_channels_); 1779 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) {
1774 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams 1780 recv_video = (rtc_options.offer_to_receive_video > 0);
1775 // are not signaled in the SDP so does not go through that path and must be 1781 }
1776 // handled here. 1782
1783 int audio_index = -1;
1784 int video_index = -1;
1785 int data_index = -1;
1786 // There should be a pending remote description that's an offer...
1787 RTC_DCHECK(session_->remote_description());
1788 RTC_DCHECK(session_->remote_description()->type() ==
1789 SessionDescriptionInterface::kOffer);
1790 // Generate m= sections that match those in the offer.
1791 // Note that mediasession.cc will handle intersection our preferred direction
1792 // with the offered direction.
1793 GenerateMediaDescrptionOptions(
1794 session_->remote_description(),
1795 cricket::RtpTransceiverDirection(send_audio, recv_audio),
1796 cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index,
1797 &video_index, &data_index, session_options);
1798
1799 cricket::MediaDescriptionOptions* audio_media_description_options =
1800 audio_index == -1
1801 ? nullptr
1802 : &session_options->media_description_options[audio_index];
1803 cricket::MediaDescriptionOptions* video_media_description_options =
1804 video_index == -1
1805 ? nullptr
1806 : &session_options->media_description_options[video_index];
1807 cricket::MediaDescriptionOptions* data_media_description_options =
1808 data_index == -1
1809 ? nullptr
1810 : &session_options->media_description_options[data_index];
1811
1812 // Apply ICE renomination flag.
1813 for (auto& options : session_options->media_description_options) {
1814 options.transport_options.enable_ice_renomination =
1815 configuration_.enable_ice_renomination;
1816 }
1817
1818 AddRtpSenderOptions(senders_, audio_media_description_options,
1819 video_media_description_options);
1820 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options);
1821
1777 // Intentionally unset the data channel type for RTP data channel. Otherwise 1822 // Intentionally unset the data channel type for RTP data channel. Otherwise
1778 // the RTP data channels would be successfully negotiated by default and the 1823 // the RTP data channels would be successfully negotiated by default and the
1779 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. 1824 // 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. 1825 // 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) { 1826 if (session_->data_channel_type() != cricket::DCT_RTP) {
1782 session_options->data_channel_type = session_->data_channel_type(); 1827 session_options->data_channel_type = session_->data_channel_type();
1783 } 1828 }
1784 session_options->bundle_enabled = 1829 session_options->rtcp_cname = rtcp_cname_;
1785 session_options->bundle_enabled &&
1786 (session_options->has_audio() || session_options->has_video() ||
1787 session_options->has_data());
1788
1789 session_options->crypto_options = factory_->options().crypto_options; 1830 session_options->crypto_options = factory_->options().crypto_options;
1790 } 1831 }
1791 1832
1792 bool PeerConnection::GetOptionsForAnswer( 1833 void PeerConnection::GenerateMediaDescrptionOptions(
1793 const MediaConstraintsInterface* constraints, 1834 const SessionDescriptionInterface* session_desc,
1835 cricket::RtpTransceiverDirection audio_direction,
1836 cricket::RtpTransceiverDirection video_direction,
1837 int* audio_index,
1838 int* video_index,
1839 int* data_index,
1794 cricket::MediaSessionOptions* session_options) { 1840 cricket::MediaSessionOptions* session_options) {
1795 InitializeOptionsForAnswer(session_options); 1841 for (const cricket::ContentInfo& content :
1796 if (!ParseConstraintsForAnswer(constraints, session_options)) { 1842 session_desc->description()->contents()) {
1797 return false; 1843 if (IsAudioContent(&content)) {
1844 // If we already have an audio m= section, reject this extra one.
1845 if (*audio_index != -1) {
1846 session_options->media_description_options.push_back(
1847 cricket::MediaDescriptionOptions(
1848 cricket::MEDIA_TYPE_AUDIO, content.name,
1849 cricket::RtpTransceiverDirection(false, false), true));
1850 } else {
1851 session_options->media_description_options.push_back(
1852 cricket::MediaDescriptionOptions(
1853 cricket::MEDIA_TYPE_AUDIO, content.name, audio_direction,
1854 !audio_direction.send && !audio_direction.recv));
1855 *audio_index = session_options->media_description_options.size() - 1;
1856 }
1857 } else if (IsVideoContent(&content)) {
1858 // If we already have an video m= section, reject this extra one.
1859 if (*video_index != -1) {
1860 session_options->media_description_options.push_back(
1861 cricket::MediaDescriptionOptions(
1862 cricket::MEDIA_TYPE_VIDEO, content.name,
1863 cricket::RtpTransceiverDirection(false, false), true));
1864 } else {
1865 session_options->media_description_options.push_back(
1866 cricket::MediaDescriptionOptions(
1867 cricket::MEDIA_TYPE_VIDEO, content.name, video_direction,
1868 !video_direction.send && !video_direction.recv));
1869 *video_index = session_options->media_description_options.size() - 1;
1870 }
1871 } else {
1872 RTC_DCHECK(IsDataContent(&content));
1873 // If we already have an data m= section, reject this extra one.
1874 if (*data_index != -1) {
1875 session_options->media_description_options.push_back(
1876 cricket::MediaDescriptionOptions(
1877 cricket::MEDIA_TYPE_DATA, content.name,
1878 cricket::RtpTransceiverDirection(false, false), true));
1879 } else {
1880 session_options->media_description_options.push_back(
1881 cricket::MediaDescriptionOptions(
1882 cricket::MEDIA_TYPE_DATA, content.name,
1883 // Direction for data sections is meaningless, but legacy
1884 // endpoints might expect sendrecv.
1885 cricket::RtpTransceiverDirection(true, true), false));
1886 *data_index = session_options->media_description_options.size() - 1;
1887 }
1888 }
1798 } 1889 }
1799 session_options->rtcp_cname = rtcp_cname_;
1800
1801 FinishOptionsForAnswer(session_options);
1802 return true;
1803 }
1804
1805 bool PeerConnection::GetOptionsForAnswer(
1806 const RTCOfferAnswerOptions& options,
1807 cricket::MediaSessionOptions* session_options) {
1808 InitializeOptionsForAnswer(session_options);
1809 if (!ExtractMediaSessionOptions(options, false, session_options)) {
1810 return false;
1811 }
1812 session_options->rtcp_cname = rtcp_cname_;
1813
1814 FinishOptionsForAnswer(session_options);
1815 return true;
1816 } 1890 }
1817 1891
1818 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { 1892 void PeerConnection::RemoveTracks(cricket::MediaType media_type) {
1819 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); 1893 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type);
1820 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, 1894 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false,
1821 media_type, nullptr); 1895 media_type, nullptr);
1822 } 1896 }
1823 1897
1824 void PeerConnection::UpdateRemoteStreamsList( 1898 void PeerConnection::UpdateRemoteStreamsList(
1825 const cricket::StreamParamsVec& streams, 1899 const cricket::StreamParamsVec& streams,
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
2278 if (!channel.get()) { 2352 if (!channel.get()) {
2279 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; 2353 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message.";
2280 return; 2354 return;
2281 } 2355 }
2282 2356
2283 rtc::scoped_refptr<DataChannelInterface> proxy_channel = 2357 rtc::scoped_refptr<DataChannelInterface> proxy_channel =
2284 DataChannelProxy::Create(signaling_thread(), channel); 2358 DataChannelProxy::Create(signaling_thread(), channel);
2285 observer_->OnDataChannel(std::move(proxy_channel)); 2359 observer_->OnDataChannel(std::move(proxy_channel));
2286 } 2360 }
2287 2361
2362 bool PeerConnection::HasRtpSender(cricket::MediaType type) const {
2363 return std::find_if(
2364 senders_.begin(), senders_.end(),
2365 [type](const rtc::scoped_refptr<
2366 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2367 return sender->media_type() == type;
2368 }) != senders_.end();
2369 }
2370
2288 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { 2371 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) {
2289 auto it = std::find_if( 2372 auto it = std::find_if(
2290 senders_.begin(), senders_.end(), 2373 senders_.begin(), senders_.end(),
2291 [id](const rtc::scoped_refptr< 2374 [id](const rtc::scoped_refptr<
2292 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { 2375 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) {
2293 return sender->id() == id; 2376 return sender->id() == id;
2294 }); 2377 });
2295 return it != senders_.end() ? (*it)->internal() : nullptr; 2378 return it != senders_.end() ? (*it)->internal() : nullptr;
2296 } 2379 }
2297 2380
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
2434 return event_log_->StartLogging(file, max_size_bytes); 2517 return event_log_->StartLogging(file, max_size_bytes);
2435 } 2518 }
2436 2519
2437 void PeerConnection::StopRtcEventLog_w() { 2520 void PeerConnection::StopRtcEventLog_w() {
2438 if (event_log_) { 2521 if (event_log_) {
2439 event_log_->StopLogging(); 2522 event_log_->StopLogging();
2440 } 2523 }
2441 } 2524 }
2442 2525
2443 } // namespace webrtc 2526 } // namespace webrtc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698