OLD | NEW |
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 Loading... |
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 options to |[audio/video]_media_description_options| from |senders|. | 136 // Add the stream and RTP data channel info to |session_options|. |
137 void AddRtpSenderOptions( | 137 void AddSendStreams( |
| 138 cricket::MediaSessionOptions* session_options, |
138 const std::vector<rtc::scoped_refptr< | 139 const std::vector<rtc::scoped_refptr< |
139 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders, | 140 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders, |
140 cricket::MediaDescriptionOptions* audio_media_description_options, | 141 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& |
141 cricket::MediaDescriptionOptions* video_media_description_options) { | 142 rtp_data_channels) { |
| 143 session_options->streams.clear(); |
142 for (const auto& sender : senders) { | 144 for (const auto& sender : senders) { |
143 if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) { | 145 session_options->AddSendStream(sender->media_type(), sender->id(), |
144 if (audio_media_description_options) { | 146 sender->internal()->stream_id()); |
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 } | 147 } |
156 } | |
157 | 148 |
158 // Add options to |session_options| from |rtp_data_channels|. | |
159 void AddRtpDataChannelOptions( | |
160 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& | |
161 rtp_data_channels, | |
162 cricket::MediaDescriptionOptions* data_media_description_options) { | |
163 if (!data_media_description_options) { | |
164 return; | |
165 } | |
166 // Check for data channels. | 149 // Check for data channels. |
167 for (const auto& kv : rtp_data_channels) { | 150 for (const auto& kv : rtp_data_channels) { |
168 const DataChannel* channel = kv.second; | 151 const DataChannel* channel = kv.second; |
169 if (channel->state() == DataChannel::kConnecting || | 152 if (channel->state() == DataChannel::kConnecting || |
170 channel->state() == DataChannel::kOpen) { | 153 channel->state() == DataChannel::kOpen) { |
171 // Legacy RTP data channels are signaled with the track/stream ID set to | 154 // |streamid| and |sync_label| are both set to the DataChannel label |
172 // the data channel's label. | 155 // here so they can be signaled the same way as MediaStreams and Tracks. |
173 data_media_description_options->AddRtpDataChannel(channel->label(), | 156 // For MediaStreams, the sync_label is the MediaStream label and the |
174 channel->label()); | 157 // track label is the same as |streamid|. |
| 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); |
175 } | 162 } |
176 } | 163 } |
177 } | 164 } |
178 | 165 |
179 uint32_t ConvertIceTransportTypeToCandidateFilter( | 166 uint32_t ConvertIceTransportTypeToCandidateFilter( |
180 PeerConnectionInterface::IceTransportsType type) { | 167 PeerConnectionInterface::IceTransportsType type) { |
181 switch (type) { | 168 switch (type) { |
182 case PeerConnectionInterface::kNone: | 169 case PeerConnectionInterface::kNone: |
183 return cricket::CF_NONE; | 170 return cricket::CF_NONE; |
184 case PeerConnectionInterface::kRelay: | 171 case PeerConnectionInterface::kRelay: |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
320 // Generate a RTCP CNAME when a PeerConnection is created. | 307 // Generate a RTCP CNAME when a PeerConnection is created. |
321 std::string GenerateRtcpCname() { | 308 std::string GenerateRtcpCname() { |
322 std::string cname; | 309 std::string cname; |
323 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) { | 310 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) { |
324 LOG(LS_ERROR) << "Failed to generate CNAME."; | 311 LOG(LS_ERROR) << "Failed to generate CNAME."; |
325 RTC_NOTREACHED(); | 312 RTC_NOTREACHED(); |
326 } | 313 } |
327 return cname; | 314 return cname; |
328 } | 315 } |
329 | 316 |
330 bool ValidateOfferAnswerOptions( | 317 bool ExtractMediaSessionOptions( |
331 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options) { | 318 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
332 return IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) && | 319 bool is_offer, |
333 IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video); | 320 cricket::MediaSessionOptions* session_options) { |
| 321 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; |
| 322 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) || |
| 323 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) { |
| 324 return false; |
| 325 } |
| 326 |
| 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; |
334 } | 350 } |
335 | 351 |
336 // From |rtc_options|, fill parts of |session_options| shared by all generated | 352 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, |
337 // m= sections (in other words, nothing that involves a map/array). | 353 cricket::MediaSessionOptions* session_options) { |
338 void ExtractSharedMediaSessionOptions( | 354 bool value = false; |
339 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 355 size_t mandatory_constraints_satisfied = 0; |
340 cricket::MediaSessionOptions* session_options) { | |
341 session_options->vad_enabled = rtc_options.voice_activity_detection; | |
342 session_options->bundle_enabled = rtc_options.use_rtp_mux; | |
343 } | |
344 | 356 |
345 bool ConvertConstraintsToOfferAnswerOptions( | 357 // kOfferToReceiveAudio defaults to true according to spec. |
346 const MediaConstraintsInterface* constraints, | 358 if (!FindConstraint(constraints, |
347 PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) { | 359 MediaConstraintsInterface::kOfferToReceiveAudio, &value, |
| 360 &mandatory_constraints_satisfied) || |
| 361 value) { |
| 362 session_options->recv_audio = true; |
| 363 } |
| 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 } |
| 375 |
| 376 if (FindConstraint(constraints, |
| 377 MediaConstraintsInterface::kVoiceActivityDetection, &value, |
| 378 &mandatory_constraints_satisfied)) { |
| 379 session_options->vad_enabled = value; |
| 380 } |
| 381 |
| 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 |
348 if (!constraints) { | 400 if (!constraints) { |
349 return true; | 401 return true; |
350 } | 402 } |
351 | |
352 bool value = false; | |
353 size_t mandatory_constraints_satisfied = 0; | |
354 | |
355 if (FindConstraint(constraints, | |
356 MediaConstraintsInterface::kOfferToReceiveAudio, &value, | |
357 &mandatory_constraints_satisfied)) { | |
358 offer_answer_options->offer_to_receive_audio = | |
359 value ? PeerConnectionInterface::RTCOfferAnswerOptions:: | |
360 kOfferToReceiveMediaTrue | |
361 : 0; | |
362 } | |
363 | |
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, | |
373 MediaConstraintsInterface::kVoiceActivityDetection, &value, | |
374 &mandatory_constraints_satisfied)) { | |
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; | |
384 } | |
385 | |
386 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); | 403 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); |
387 } | 404 } |
388 | 405 |
389 PeerConnection::PeerConnection(PeerConnectionFactory* factory, | 406 PeerConnection::PeerConnection(PeerConnectionFactory* factory, |
390 std::unique_ptr<RtcEventLog> event_log, | 407 std::unique_ptr<RtcEventLog> event_log, |
391 std::unique_ptr<Call> call) | 408 std::unique_ptr<Call> call) |
392 : factory_(factory), | 409 : factory_(factory), |
393 observer_(NULL), | 410 observer_(NULL), |
394 uma_observer_(NULL), | 411 uma_observer_(NULL), |
395 event_log_(std::move(event_log)), | 412 event_log_(std::move(event_log)), |
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
818 return DataChannelProxy::Create(signaling_thread(), channel.get()); | 835 return DataChannelProxy::Create(signaling_thread(), channel.get()); |
819 } | 836 } |
820 | 837 |
821 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, | 838 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, |
822 const MediaConstraintsInterface* constraints) { | 839 const MediaConstraintsInterface* constraints) { |
823 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); | 840 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); |
824 if (!observer) { | 841 if (!observer) { |
825 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; | 842 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; |
826 return; | 843 return; |
827 } | 844 } |
828 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options; | 845 RTCOfferAnswerOptions 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); | |
837 | 846 |
838 CreateOffer(observer, offer_answer_options); | 847 bool value; |
| 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); |
839 } | 888 } |
840 | 889 |
841 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, | 890 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, |
842 const RTCOfferAnswerOptions& options) { | 891 const RTCOfferAnswerOptions& options) { |
843 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); | 892 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); |
844 if (!observer) { | 893 if (!observer) { |
845 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; | 894 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; |
846 return; | 895 return; |
847 } | 896 } |
848 | 897 |
849 if (!ValidateOfferAnswerOptions(options)) { | 898 cricket::MediaSessionOptions session_options; |
| 899 if (!GetOptionsForOffer(options, &session_options)) { |
850 std::string error = "CreateOffer called with invalid options."; | 900 std::string error = "CreateOffer called with invalid options."; |
851 LOG(LS_ERROR) << error; | 901 LOG(LS_ERROR) << error; |
852 PostCreateSessionDescriptionFailure(observer, error); | 902 PostCreateSessionDescriptionFailure(observer, error); |
853 return; | 903 return; |
854 } | 904 } |
855 | 905 |
856 cricket::MediaSessionOptions session_options; | |
857 GetOptionsForOffer(options, &session_options); | |
858 session_->CreateOffer(observer, options, session_options); | 906 session_->CreateOffer(observer, options, session_options); |
859 } | 907 } |
860 | 908 |
861 void PeerConnection::CreateAnswer( | 909 void PeerConnection::CreateAnswer( |
862 CreateSessionDescriptionObserver* observer, | 910 CreateSessionDescriptionObserver* observer, |
863 const MediaConstraintsInterface* constraints) { | 911 const MediaConstraintsInterface* constraints) { |
864 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); | 912 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); |
865 if (!observer) { | 913 if (!observer) { |
866 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; | 914 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; |
867 return; | 915 return; |
868 } | 916 } |
869 | 917 |
870 if (!session_->remote_description() || | 918 cricket::MediaSessionOptions session_options; |
871 session_->remote_description()->type() != | 919 if (!GetOptionsForAnswer(constraints, &session_options)) { |
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)) { | |
882 std::string error = "CreateAnswer called with invalid constraints."; | 920 std::string error = "CreateAnswer called with invalid constraints."; |
883 LOG(LS_ERROR) << error; | 921 LOG(LS_ERROR) << error; |
884 PostCreateSessionDescriptionFailure(observer, error); | 922 PostCreateSessionDescriptionFailure(observer, error); |
885 return; | 923 return; |
886 } | 924 } |
887 | 925 |
888 cricket::MediaSessionOptions session_options; | |
889 GetOptionsForAnswer(offer_answer_options, &session_options); | |
890 session_->CreateAnswer(observer, session_options); | 926 session_->CreateAnswer(observer, session_options); |
891 } | 927 } |
892 | 928 |
893 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, | 929 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, |
894 const RTCOfferAnswerOptions& options) { | 930 const RTCOfferAnswerOptions& options) { |
895 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); | 931 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); |
896 if (!observer) { | 932 if (!observer) { |
897 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; | 933 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; |
898 return; | 934 return; |
899 } | 935 } |
900 | 936 |
901 cricket::MediaSessionOptions session_options; | 937 cricket::MediaSessionOptions session_options; |
902 GetOptionsForAnswer(options, &session_options); | 938 if (!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 } |
903 | 944 |
904 session_->CreateAnswer(observer, session_options); | 945 session_->CreateAnswer(observer, session_options); |
905 } | 946 } |
906 | 947 |
907 void PeerConnection::SetLocalDescription( | 948 void PeerConnection::SetLocalDescription( |
908 SetSessionDescriptionObserver* observer, | 949 SetSessionDescriptionObserver* observer, |
909 SessionDescriptionInterface* desc) { | 950 SessionDescriptionInterface* desc) { |
910 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); | 951 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); |
911 if (IsClosed()) { | 952 if (IsClosed()) { |
912 return; | 953 return; |
(...skipping 737 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1650 | 1691 |
1651 void PeerConnection::PostCreateSessionDescriptionFailure( | 1692 void PeerConnection::PostCreateSessionDescriptionFailure( |
1652 CreateSessionDescriptionObserver* observer, | 1693 CreateSessionDescriptionObserver* observer, |
1653 const std::string& error) { | 1694 const std::string& error) { |
1654 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); | 1695 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); |
1655 msg->error = error; | 1696 msg->error = error; |
1656 signaling_thread()->Post(RTC_FROM_HERE, this, | 1697 signaling_thread()->Post(RTC_FROM_HERE, this, |
1657 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); | 1698 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); |
1658 } | 1699 } |
1659 | 1700 |
1660 void PeerConnection::GetOptionsForOffer( | 1701 bool PeerConnection::GetOptionsForOffer( |
1661 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 1702 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
1662 cricket::MediaSessionOptions* session_options) { | 1703 cricket::MediaSessionOptions* session_options) { |
1663 ExtractSharedMediaSessionOptions(rtc_options, session_options); | 1704 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of |
| 1705 // ContentInfos. |
| 1706 if (session_->local_description()) { |
| 1707 for (const cricket::ContentInfo& content : |
| 1708 session_->local_description()->description()->contents()) { |
| 1709 session_options->transport_options[content.name] = |
| 1710 cricket::TransportOptions(); |
| 1711 } |
| 1712 } |
| 1713 session_options->enable_ice_renomination = |
| 1714 configuration_.enable_ice_renomination; |
1664 | 1715 |
1665 // Figure out transceiver directional preferences. | 1716 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) { |
1666 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO); | 1717 return false; |
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 } | 1718 } |
1689 | 1719 |
1690 int audio_index = -1; | 1720 AddSendStreams(session_options, senders_, rtp_data_channels_); |
1691 int video_index = -1; | 1721 // Offer to receive audio/video if the constraint is not set and there are |
1692 int data_index = -1; | 1722 // send streams, or we're currently receiving. |
1693 // If a current description exists, generate m= sections in the same order, | 1723 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { |
1694 // using the first audio/video/data section that appears and rejecting | 1724 session_options->recv_audio = |
1695 // extraneous ones. | 1725 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || |
1696 if (session_->local_description()) { | 1726 !remote_audio_tracks_.empty(); |
1697 GenerateMediaDescriptionOptions( | |
1698 session_->local_description(), | |
1699 cricket::RtpTransceiverDirection(send_audio, recv_audio), | |
1700 cricket::RtpTransceiverDirection(send_video, recv_video), &audio_index, | |
1701 &video_index, &data_index, session_options); | |
1702 } | 1727 } |
1703 | 1728 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { |
1704 // Add audio/video/data m= sections to the end if needed. | 1729 session_options->recv_video = |
1705 if (audio_index == -1 && offer_new_audio_description) { | 1730 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || |
1706 session_options->media_description_options.push_back( | 1731 !remote_video_tracks_.empty(); |
1707 cricket::MediaDescriptionOptions( | |
1708 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, | |
1709 cricket::RtpTransceiverDirection(send_audio, recv_audio), false)); | |
1710 audio_index = session_options->media_description_options.size() - 1; | |
1711 } | 1732 } |
1712 if (video_index == -1 && offer_new_video_description) { | |
1713 session_options->media_description_options.push_back( | |
1714 cricket::MediaDescriptionOptions( | |
1715 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, | |
1716 cricket::RtpTransceiverDirection(send_video, recv_video), false)); | |
1717 video_index = session_options->media_description_options.size() - 1; | |
1718 } | |
1719 if (data_index == -1 && offer_new_data_description) { | |
1720 session_options->media_description_options.push_back( | |
1721 cricket::MediaDescriptionOptions( | |
1722 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA, | |
1723 cricket::RtpTransceiverDirection(true, true), false)); | |
1724 data_index = session_options->media_description_options.size() - 1; | |
1725 } | |
1726 | |
1727 cricket::MediaDescriptionOptions* audio_media_description_options = | |
1728 audio_index == -1 | |
1729 ? nullptr | |
1730 : &session_options->media_description_options[audio_index]; | |
1731 cricket::MediaDescriptionOptions* video_media_description_options = | |
1732 video_index == -1 | |
1733 ? nullptr | |
1734 : &session_options->media_description_options[video_index]; | |
1735 cricket::MediaDescriptionOptions* data_media_description_options = | |
1736 data_index == -1 | |
1737 ? 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); | |
1750 | 1733 |
1751 // Intentionally unset the data channel type for RTP data channel with the | 1734 // Intentionally unset the data channel type for RTP data channel with the |
1752 // second condition. Otherwise the RTP data channels would be successfully | 1735 // second condition. Otherwise the RTP data channels would be successfully |
1753 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail | 1736 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail |
1754 // when building with chromium. We want to leave RTP data channels broken, so | 1737 // when building with chromium. We want to leave RTP data channels broken, so |
1755 // people won't try to use them. | 1738 // people won't try to use them. |
1756 if (!rtp_data_channels_.empty() || | 1739 if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) { |
1757 session_->data_channel_type() != cricket::DCT_RTP) { | |
1758 session_options->data_channel_type = session_->data_channel_type(); | 1740 session_options->data_channel_type = session_->data_channel_type(); |
1759 } | 1741 } |
1760 | 1742 |
| 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 |
1761 session_options->rtcp_cname = rtcp_cname_; | 1748 session_options->rtcp_cname = rtcp_cname_; |
1762 session_options->crypto_options = factory_->options().crypto_options; | 1749 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, | |
1767 cricket::MediaSessionOptions* session_options) { | 1754 cricket::MediaSessionOptions* session_options) { |
1768 ExtractSharedMediaSessionOptions(rtc_options, session_options); | 1755 session_options->recv_audio = false; |
| 1756 session_options->recv_video = false; |
| 1757 session_options->enable_ice_renomination = |
| 1758 configuration_.enable_ice_renomination; |
| 1759 } |
1769 | 1760 |
1770 // Figure out transceiver directional preferences. | 1761 void PeerConnection::FinishOptionsForAnswer( |
1771 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO); | 1762 cricket::MediaSessionOptions* session_options) { |
1772 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO); | 1763 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of |
1773 | 1764 // ContentInfos. |
1774 // By default, generate sendrecv/recvonly m= sections. The direction is also | 1765 if (session_->remote_description()) { |
1775 // restricted by the direction in the offer. | 1766 // Initialize the transport_options map. |
1776 bool recv_audio = true; | 1767 for (const cricket::ContentInfo& content : |
1777 bool recv_video = true; | 1768 session_->remote_description()->description()->contents()) { |
1778 | 1769 session_options->transport_options[content.name] = |
1779 // The "offer_to_receive_X" options allow those defaults to be overridden. | 1770 cricket::TransportOptions(); |
1780 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) { | 1771 } |
1781 recv_audio = (rtc_options.offer_to_receive_audio > 0); | |
1782 } | 1772 } |
1783 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { | 1773 AddSendStreams(session_options, senders_, rtp_data_channels_); |
1784 recv_video = (rtc_options.offer_to_receive_video > 0); | 1774 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams |
1785 } | 1775 // are not signaled in the SDP so does not go through that path and must be |
1786 | 1776 // handled here. |
1787 int audio_index = -1; | |
1788 int video_index = -1; | |
1789 int data_index = -1; | |
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 == -1 | |
1805 ? nullptr | |
1806 : &session_options->media_description_options[audio_index]; | |
1807 cricket::MediaDescriptionOptions* video_media_description_options = | |
1808 video_index == -1 | |
1809 ? nullptr | |
1810 : &session_options->media_description_options[video_index]; | |
1811 cricket::MediaDescriptionOptions* data_media_description_options = | |
1812 data_index == -1 | |
1813 ? nullptr | |
1814 : &session_options->media_description_options[data_index]; | |
1815 | |
1816 // Apply ICE renomination flag. | |
1817 for (auto& options : session_options->media_description_options) { | |
1818 options.transport_options.enable_ice_renomination = | |
1819 configuration_.enable_ice_renomination; | |
1820 } | |
1821 | |
1822 AddRtpSenderOptions(senders_, audio_media_description_options, | |
1823 video_media_description_options); | |
1824 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options); | |
1825 | |
1826 // Intentionally unset the data channel type for RTP data channel. Otherwise | 1777 // Intentionally unset the data channel type for RTP data channel. Otherwise |
1827 // the RTP data channels would be successfully negotiated by default and the | 1778 // the RTP data channels would be successfully negotiated by default and the |
1828 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. | 1779 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. |
1829 // We want to leave RTP data channels broken, so people won't try to use them. | 1780 // We want to leave RTP data channels broken, so people won't try to use them. |
1830 if (!rtp_data_channels_.empty() || | 1781 if (session_->data_channel_type() != cricket::DCT_RTP) { |
1831 session_->data_channel_type() != cricket::DCT_RTP) { | |
1832 session_options->data_channel_type = session_->data_channel_type(); | 1782 session_options->data_channel_type = session_->data_channel_type(); |
1833 } | 1783 } |
| 1784 session_options->bundle_enabled = |
| 1785 session_options->bundle_enabled && |
| 1786 (session_options->has_audio() || session_options->has_video() || |
| 1787 session_options->has_data()); |
1834 | 1788 |
1835 session_options->rtcp_cname = rtcp_cname_; | |
1836 session_options->crypto_options = factory_->options().crypto_options; | 1789 session_options->crypto_options = factory_->options().crypto_options; |
1837 } | 1790 } |
1838 | 1791 |
1839 void PeerConnection::GenerateMediaDescriptionOptions( | 1792 bool PeerConnection::GetOptionsForAnswer( |
1840 const SessionDescriptionInterface* session_desc, | 1793 const MediaConstraintsInterface* constraints, |
1841 cricket::RtpTransceiverDirection audio_direction, | |
1842 cricket::RtpTransceiverDirection video_direction, | |
1843 int* audio_index, | |
1844 int* video_index, | |
1845 int* data_index, | |
1846 cricket::MediaSessionOptions* session_options) { | 1794 cricket::MediaSessionOptions* session_options) { |
1847 for (const cricket::ContentInfo& content : | 1795 InitializeOptionsForAnswer(session_options); |
1848 session_desc->description()->contents()) { | 1796 if (!ParseConstraintsForAnswer(constraints, session_options)) { |
1849 if (IsAudioContent(&content)) { | 1797 return false; |
1850 // If we already have an audio m= section, reject this extra one. | |
1851 if (*audio_index != -1) { | |
1852 session_options->media_description_options.push_back( | |
1853 cricket::MediaDescriptionOptions( | |
1854 cricket::MEDIA_TYPE_AUDIO, content.name, | |
1855 cricket::RtpTransceiverDirection(false, false), true)); | |
1856 } else { | |
1857 session_options->media_description_options.push_back( | |
1858 cricket::MediaDescriptionOptions( | |
1859 cricket::MEDIA_TYPE_AUDIO, content.name, audio_direction, | |
1860 !audio_direction.send && !audio_direction.recv)); | |
1861 *audio_index = session_options->media_description_options.size() - 1; | |
1862 } | |
1863 } else if (IsVideoContent(&content)) { | |
1864 // If we already have an video m= section, reject this extra one. | |
1865 if (*video_index != -1) { | |
1866 session_options->media_description_options.push_back( | |
1867 cricket::MediaDescriptionOptions( | |
1868 cricket::MEDIA_TYPE_VIDEO, content.name, | |
1869 cricket::RtpTransceiverDirection(false, false), true)); | |
1870 } else { | |
1871 session_options->media_description_options.push_back( | |
1872 cricket::MediaDescriptionOptions( | |
1873 cricket::MEDIA_TYPE_VIDEO, content.name, video_direction, | |
1874 !video_direction.send && !video_direction.recv)); | |
1875 *video_index = session_options->media_description_options.size() - 1; | |
1876 } | |
1877 } else { | |
1878 RTC_DCHECK(IsDataContent(&content)); | |
1879 // If we already have an data m= section, reject this extra one. | |
1880 if (*data_index != -1) { | |
1881 session_options->media_description_options.push_back( | |
1882 cricket::MediaDescriptionOptions( | |
1883 cricket::MEDIA_TYPE_DATA, content.name, | |
1884 cricket::RtpTransceiverDirection(false, false), true)); | |
1885 } else { | |
1886 session_options->media_description_options.push_back( | |
1887 cricket::MediaDescriptionOptions( | |
1888 cricket::MEDIA_TYPE_DATA, content.name, | |
1889 // Direction for data sections is meaningless, but legacy | |
1890 // endpoints might expect sendrecv. | |
1891 cricket::RtpTransceiverDirection(true, true), false)); | |
1892 *data_index = session_options->media_description_options.size() - 1; | |
1893 } | |
1894 } | |
1895 } | 1798 } |
| 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; |
1896 } | 1816 } |
1897 | 1817 |
1898 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { | 1818 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { |
1899 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); | 1819 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); |
1900 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, | 1820 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, |
1901 media_type, nullptr); | 1821 media_type, nullptr); |
1902 } | 1822 } |
1903 | 1823 |
1904 void PeerConnection::UpdateRemoteStreamsList( | 1824 void PeerConnection::UpdateRemoteStreamsList( |
1905 const cricket::StreamParamsVec& streams, | 1825 const cricket::StreamParamsVec& streams, |
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2358 if (!channel.get()) { | 2278 if (!channel.get()) { |
2359 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; | 2279 LOG(LS_ERROR) << "Failed to create DataChannel from the OPEN message."; |
2360 return; | 2280 return; |
2361 } | 2281 } |
2362 | 2282 |
2363 rtc::scoped_refptr<DataChannelInterface> proxy_channel = | 2283 rtc::scoped_refptr<DataChannelInterface> proxy_channel = |
2364 DataChannelProxy::Create(signaling_thread(), channel); | 2284 DataChannelProxy::Create(signaling_thread(), channel); |
2365 observer_->OnDataChannel(std::move(proxy_channel)); | 2285 observer_->OnDataChannel(std::move(proxy_channel)); |
2366 } | 2286 } |
2367 | 2287 |
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 | |
2377 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { | 2288 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { |
2378 auto it = std::find_if( | 2289 auto it = std::find_if( |
2379 senders_.begin(), senders_.end(), | 2290 senders_.begin(), senders_.end(), |
2380 [id](const rtc::scoped_refptr< | 2291 [id](const rtc::scoped_refptr< |
2381 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { | 2292 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { |
2382 return sender->id() == id; | 2293 return sender->id() == id; |
2383 }); | 2294 }); |
2384 return it != senders_.end() ? (*it)->internal() : nullptr; | 2295 return it != senders_.end() ? (*it)->internal() : nullptr; |
2385 } | 2296 } |
2386 | 2297 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2523 return event_log_->StartLogging(file, max_size_bytes); | 2434 return event_log_->StartLogging(file, max_size_bytes); |
2524 } | 2435 } |
2525 | 2436 |
2526 void PeerConnection::StopRtcEventLog_w() { | 2437 void PeerConnection::StopRtcEventLog_w() { |
2527 if (event_log_) { | 2438 if (event_log_) { |
2528 event_log_->StopLogging(); | 2439 event_log_->StopLogging(); |
2529 } | 2440 } |
2530 } | 2441 } |
2531 | 2442 |
2532 } // namespace webrtc | 2443 } // namespace webrtc |
OLD | NEW |