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