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 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
344 ? desc->streams() | 344 ? desc->streams() |
345 : std::vector<cricket::StreamParams>(); | 345 : std::vector<cricket::StreamParams>(); |
346 } | 346 } |
347 | 347 |
348 bool IsValidOfferToReceiveMedia(int value) { | 348 bool IsValidOfferToReceiveMedia(int value) { |
349 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; | 349 typedef PeerConnectionInterface::RTCOfferAnswerOptions Options; |
350 return (value >= Options::kUndefined) && | 350 return (value >= Options::kUndefined) && |
351 (value <= Options::kMaxOfferToReceiveMedia); | 351 (value <= Options::kMaxOfferToReceiveMedia); |
352 } | 352 } |
353 | 353 |
354 // Add the stream and RTP data channel info to |session_options|. | 354 // Add options to |[audio/video]_media_description_options| from |senders|. |
355 void AddSendStreams( | 355 void AddRtpSenderOptions( |
356 cricket::MediaSessionOptions* session_options, | |
357 const std::vector<rtc::scoped_refptr< | 356 const std::vector<rtc::scoped_refptr< |
358 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders, | 357 RtpSenderProxyWithInternal<RtpSenderInternal>>>& senders, |
| 358 cricket::MediaDescriptionOptions* audio_media_description_options, |
| 359 cricket::MediaDescriptionOptions* video_media_description_options) { |
| 360 for (const auto& sender : senders) { |
| 361 if (sender->media_type() == cricket::MEDIA_TYPE_AUDIO) { |
| 362 if (audio_media_description_options) { |
| 363 audio_media_description_options->AddAudioSender( |
| 364 sender->id(), sender->internal()->stream_id()); |
| 365 } |
| 366 } else { |
| 367 RTC_DCHECK(sender->media_type() == cricket::MEDIA_TYPE_VIDEO); |
| 368 if (video_media_description_options) { |
| 369 video_media_description_options->AddVideoSender( |
| 370 sender->id(), sender->internal()->stream_id(), 1); |
| 371 } |
| 372 } |
| 373 } |
| 374 } |
| 375 |
| 376 // Add options to |session_options| from |rtp_data_channels|. |
| 377 void AddRtpDataChannelOptions( |
359 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& | 378 const std::map<std::string, rtc::scoped_refptr<DataChannel>>& |
360 rtp_data_channels) { | 379 rtp_data_channels, |
361 session_options->streams.clear(); | 380 cricket::MediaDescriptionOptions* data_media_description_options) { |
362 for (const auto& sender : senders) { | 381 if (!data_media_description_options) { |
363 session_options->AddSendStream(sender->media_type(), sender->id(), | 382 return; |
364 sender->internal()->stream_id()); | |
365 } | 383 } |
366 | |
367 // Check for data channels. | 384 // Check for data channels. |
368 for (const auto& kv : rtp_data_channels) { | 385 for (const auto& kv : rtp_data_channels) { |
369 const DataChannel* channel = kv.second; | 386 const DataChannel* channel = kv.second; |
370 if (channel->state() == DataChannel::kConnecting || | 387 if (channel->state() == DataChannel::kConnecting || |
371 channel->state() == DataChannel::kOpen) { | 388 channel->state() == DataChannel::kOpen) { |
372 // |streamid| and |sync_label| are both set to the DataChannel label | 389 // Legacy RTP data channels are signaled with the track/stream ID set to |
373 // here so they can be signaled the same way as MediaStreams and Tracks. | 390 // the data channel's label. |
374 // For MediaStreams, the sync_label is the MediaStream label and the | 391 data_media_description_options->AddRtpDataChannel(channel->label(), |
375 // track label is the same as |streamid|. | 392 channel->label()); |
376 const std::string& streamid = channel->label(); | |
377 const std::string& sync_label = channel->label(); | |
378 session_options->AddSendStream(cricket::MEDIA_TYPE_DATA, streamid, | |
379 sync_label); | |
380 } | 393 } |
381 } | 394 } |
382 } | 395 } |
383 | 396 |
384 uint32_t ConvertIceTransportTypeToCandidateFilter( | 397 uint32_t ConvertIceTransportTypeToCandidateFilter( |
385 PeerConnectionInterface::IceTransportsType type) { | 398 PeerConnectionInterface::IceTransportsType type) { |
386 switch (type) { | 399 switch (type) { |
387 case PeerConnectionInterface::kNone: | 400 case PeerConnectionInterface::kNone: |
388 return cricket::CF_NONE; | 401 return cricket::CF_NONE; |
389 case PeerConnectionInterface::kRelay: | 402 case PeerConnectionInterface::kRelay: |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
452 // Generate a RTCP CNAME when a PeerConnection is created. | 465 // Generate a RTCP CNAME when a PeerConnection is created. |
453 std::string GenerateRtcpCname() { | 466 std::string GenerateRtcpCname() { |
454 std::string cname; | 467 std::string cname; |
455 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) { | 468 if (!rtc::CreateRandomString(kRtcpCnameLength, &cname)) { |
456 LOG(LS_ERROR) << "Failed to generate CNAME."; | 469 LOG(LS_ERROR) << "Failed to generate CNAME."; |
457 RTC_DCHECK(false); | 470 RTC_DCHECK(false); |
458 } | 471 } |
459 return cname; | 472 return cname; |
460 } | 473 } |
461 | 474 |
462 bool ExtractMediaSessionOptions( | 475 bool ValidateOfferAnswerOptions( |
| 476 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options) { |
| 477 return IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) && |
| 478 IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video); |
| 479 } |
| 480 |
| 481 // From |rtc_options| and |is_offer|, fill |recv_audio| and |recv_video|. |
| 482 // TODO: delete, it's simpler without a function |
| 483 void ExtractAudioVideoRecvPreferences( |
463 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 484 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
464 bool is_offer, | 485 bool is_offer, |
465 cricket::MediaSessionOptions* session_options) { | 486 bool* recv_audio, |
| 487 bool* recv_video) { |
466 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; | 488 typedef PeerConnectionInterface::RTCOfferAnswerOptions RTCOfferAnswerOptions; |
467 if (!IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_audio) || | 489 |
468 !IsValidOfferToReceiveMedia(rtc_options.offer_to_receive_video)) { | 490 // If constraints don't prevent us, we always accept audio. |
469 return false; | 491 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) { |
| 492 *recv_audio = (rtc_options.offer_to_receive_audio > 0); |
| 493 } else { |
| 494 *recv_audio = true; |
470 } | 495 } |
471 | 496 |
472 // If constraints don't prevent us, we always accept video. | |
473 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) { | |
474 session_options->recv_audio = (rtc_options.offer_to_receive_audio > 0); | |
475 } else { | |
476 session_options->recv_audio = true; | |
477 } | |
478 // For offers, we only offer video if we have it or it's forced by options. | 497 // For offers, we only offer video if we have it or it's forced by options. |
479 // For answers, we will always accept video (if offered). | 498 // For answers, we will always accept video (if offered). |
480 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { | 499 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { |
481 session_options->recv_video = (rtc_options.offer_to_receive_video > 0); | 500 *recv_video = (rtc_options.offer_to_receive_video > 0); |
482 } else if (is_offer) { | 501 } else if (is_offer) { |
483 session_options->recv_video = false; | 502 *recv_video = false; |
484 } else { | 503 } else { |
485 session_options->recv_video = true; | 504 *recv_video = true; |
| 505 } |
| 506 } |
| 507 |
| 508 // From |rtc_options|, fill parts of |session_options| shared by all generated |
| 509 // m= sections (in other words, nothign that involves a map/array). |
| 510 void ExtractSharedMediaSessionOptions( |
| 511 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
| 512 cricket::MediaSessionOptions* session_options) { |
| 513 session_options->vad_enabled = rtc_options.voice_activity_detection; |
| 514 session_options->bundle_enabled = rtc_options.use_rtp_mux; |
| 515 } |
| 516 |
| 517 bool ConvertConstraintsToOfferAnswerOptions( |
| 518 const MediaConstraintsInterface* constraints, |
| 519 PeerConnectionInterface::RTCOfferAnswerOptions* offer_answer_options) { |
| 520 if (!constraints) { |
| 521 return true; |
486 } | 522 } |
487 | 523 |
488 session_options->vad_enabled = rtc_options.voice_activity_detection; | |
489 session_options->bundle_enabled = rtc_options.use_rtp_mux; | |
490 for (auto& kv : session_options->transport_options) { | |
491 kv.second.ice_restart = rtc_options.ice_restart; | |
492 } | |
493 | |
494 return true; | |
495 } | |
496 | |
497 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, | |
498 cricket::MediaSessionOptions* session_options) { | |
499 bool value = false; | 524 bool value = false; |
500 size_t mandatory_constraints_satisfied = 0; | 525 size_t mandatory_constraints_satisfied = 0; |
501 | 526 |
502 // kOfferToReceiveAudio defaults to true according to spec. | 527 if (FindConstraint(constraints, |
503 if (!FindConstraint(constraints, | 528 MediaConstraintsInterface::kOfferToReceiveAudio, &value, |
504 MediaConstraintsInterface::kOfferToReceiveAudio, &value, | 529 &mandatory_constraints_satisfied)) { |
505 &mandatory_constraints_satisfied) || | 530 offer_answer_options->offer_to_receive_audio = |
506 value) { | 531 value ? PeerConnectionInterface::RTCOfferAnswerOptions:: |
507 session_options->recv_audio = true; | 532 kOfferToReceiveMediaTrue |
| 533 : 0; |
508 } | 534 } |
509 | 535 if (FindConstraint(constraints, |
510 // kOfferToReceiveVideo defaults to false according to spec. But | 536 MediaConstraintsInterface::kOfferToReceiveVideo, &value, |
511 // if it is an answer and video is offered, we should still accept video | 537 &mandatory_constraints_satisfied)) { |
512 // per default. | 538 offer_answer_options->offer_to_receive_video = |
513 value = false; | 539 value ? PeerConnectionInterface::RTCOfferAnswerOptions:: |
514 if (!FindConstraint(constraints, | 540 kOfferToReceiveMediaTrue |
515 MediaConstraintsInterface::kOfferToReceiveVideo, &value, | 541 : 0; |
516 &mandatory_constraints_satisfied) || | |
517 value) { | |
518 session_options->recv_video = true; | |
519 } | 542 } |
520 | |
521 if (FindConstraint(constraints, | 543 if (FindConstraint(constraints, |
522 MediaConstraintsInterface::kVoiceActivityDetection, &value, | 544 MediaConstraintsInterface::kVoiceActivityDetection, &value, |
523 &mandatory_constraints_satisfied)) { | 545 &mandatory_constraints_satisfied)) { |
524 session_options->vad_enabled = value; | 546 offer_answer_options->voice_activity_detection = value; |
| 547 } |
| 548 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value, |
| 549 &mandatory_constraints_satisfied)) { |
| 550 offer_answer_options->use_rtp_mux = value; |
| 551 } |
| 552 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart, |
| 553 &value, &mandatory_constraints_satisfied)) { |
| 554 offer_answer_options->ice_restart = value; |
525 } | 555 } |
526 | 556 |
527 if (FindConstraint(constraints, MediaConstraintsInterface::kUseRtpMux, &value, | |
528 &mandatory_constraints_satisfied)) { | |
529 session_options->bundle_enabled = value; | |
530 } else { | |
531 // kUseRtpMux defaults to true according to spec. | |
532 session_options->bundle_enabled = true; | |
533 } | |
534 | |
535 bool ice_restart = false; | |
536 if (FindConstraint(constraints, MediaConstraintsInterface::kIceRestart, | |
537 &value, &mandatory_constraints_satisfied)) { | |
538 // kIceRestart defaults to false according to spec. | |
539 ice_restart = true; | |
540 } | |
541 for (auto& kv : session_options->transport_options) { | |
542 kv.second.ice_restart = ice_restart; | |
543 } | |
544 | |
545 if (!constraints) { | |
546 return true; | |
547 } | |
548 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); | 557 return mandatory_constraints_satisfied == constraints->GetMandatory().size(); |
549 } | 558 } |
550 | 559 |
551 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, | 560 bool ParseIceServers(const PeerConnectionInterface::IceServers& servers, |
552 cricket::ServerAddresses* stun_servers, | 561 cricket::ServerAddresses* stun_servers, |
553 std::vector<cricket::RelayServerConfig>* turn_servers) { | 562 std::vector<cricket::RelayServerConfig>* turn_servers) { |
554 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) { | 563 for (const webrtc::PeerConnectionInterface::IceServer& server : servers) { |
555 if (!server.urls.empty()) { | 564 if (!server.urls.empty()) { |
556 for (const std::string& url : server.urls) { | 565 for (const std::string& url : server.urls) { |
557 if (url.empty()) { | 566 if (url.empty()) { |
(...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
981 return DataChannelProxy::Create(signaling_thread(), channel.get()); | 990 return DataChannelProxy::Create(signaling_thread(), channel.get()); |
982 } | 991 } |
983 | 992 |
984 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, | 993 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, |
985 const MediaConstraintsInterface* constraints) { | 994 const MediaConstraintsInterface* constraints) { |
986 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); | 995 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); |
987 if (!VERIFY(observer != nullptr)) { | 996 if (!VERIFY(observer != nullptr)) { |
988 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; | 997 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; |
989 return; | 998 return; |
990 } | 999 } |
991 RTCOfferAnswerOptions options; | |
992 | 1000 |
993 bool value; | 1001 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options; |
994 size_t mandatory_constraints = 0; | 1002 if (!ConvertConstraintsToOfferAnswerOptions(constraints, |
995 | 1003 &offer_answer_options)) { |
996 if (FindConstraint(constraints, | 1004 std::string error = "CreateOffer called with invalid constraints."; |
997 MediaConstraintsInterface::kOfferToReceiveAudio, | 1005 LOG(LS_ERROR) << error; |
998 &value, | 1006 PostCreateSessionDescriptionFailure(observer, error); |
999 &mandatory_constraints)) { | 1007 return; |
1000 options.offer_to_receive_audio = | |
1001 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0; | |
1002 } | 1008 } |
1003 | 1009 |
1004 if (FindConstraint(constraints, | 1010 CreateOffer(observer, offer_answer_options); |
1005 MediaConstraintsInterface::kOfferToReceiveVideo, | |
1006 &value, | |
1007 &mandatory_constraints)) { | |
1008 options.offer_to_receive_video = | |
1009 value ? RTCOfferAnswerOptions::kOfferToReceiveMediaTrue : 0; | |
1010 } | |
1011 | |
1012 if (FindConstraint(constraints, | |
1013 MediaConstraintsInterface::kVoiceActivityDetection, | |
1014 &value, | |
1015 &mandatory_constraints)) { | |
1016 options.voice_activity_detection = value; | |
1017 } | |
1018 | |
1019 if (FindConstraint(constraints, | |
1020 MediaConstraintsInterface::kIceRestart, | |
1021 &value, | |
1022 &mandatory_constraints)) { | |
1023 options.ice_restart = value; | |
1024 } | |
1025 | |
1026 if (FindConstraint(constraints, | |
1027 MediaConstraintsInterface::kUseRtpMux, | |
1028 &value, | |
1029 &mandatory_constraints)) { | |
1030 options.use_rtp_mux = value; | |
1031 } | |
1032 | |
1033 CreateOffer(observer, options); | |
1034 } | 1011 } |
1035 | 1012 |
1036 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, | 1013 void PeerConnection::CreateOffer(CreateSessionDescriptionObserver* observer, |
1037 const RTCOfferAnswerOptions& options) { | 1014 const RTCOfferAnswerOptions& options) { |
1038 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); | 1015 TRACE_EVENT0("webrtc", "PeerConnection::CreateOffer"); |
1039 if (!VERIFY(observer != nullptr)) { | 1016 if (!VERIFY(observer != nullptr)) { |
1040 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; | 1017 LOG(LS_ERROR) << "CreateOffer - observer is NULL."; |
1041 return; | 1018 return; |
1042 } | 1019 } |
1043 | 1020 |
1044 cricket::MediaSessionOptions session_options; | 1021 if (!ValidateOfferAnswerOptions(options)) { |
1045 if (!GetOptionsForOffer(options, &session_options)) { | |
1046 std::string error = "CreateOffer called with invalid options."; | 1022 std::string error = "CreateOffer called with invalid options."; |
1047 LOG(LS_ERROR) << error; | 1023 LOG(LS_ERROR) << error; |
1048 PostCreateSessionDescriptionFailure(observer, error); | 1024 PostCreateSessionDescriptionFailure(observer, error); |
1049 return; | |
1050 } | 1025 } |
1051 | 1026 |
| 1027 cricket::MediaSessionOptions session_options; |
| 1028 GetOptionsForOffer(options, &session_options); |
1052 session_->CreateOffer(observer, options, session_options); | 1029 session_->CreateOffer(observer, options, session_options); |
1053 } | 1030 } |
1054 | 1031 |
1055 void PeerConnection::CreateAnswer( | 1032 void PeerConnection::CreateAnswer( |
1056 CreateSessionDescriptionObserver* observer, | 1033 CreateSessionDescriptionObserver* observer, |
1057 const MediaConstraintsInterface* constraints) { | 1034 const MediaConstraintsInterface* constraints) { |
1058 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); | 1035 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); |
1059 if (!VERIFY(observer != nullptr)) { | 1036 if (!VERIFY(observer != nullptr)) { |
1060 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; | 1037 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; |
1061 return; | 1038 return; |
1062 } | 1039 } |
1063 | 1040 |
1064 cricket::MediaSessionOptions session_options; | 1041 if (!session_->remote_description() || |
1065 if (!GetOptionsForAnswer(constraints, &session_options)) { | 1042 session_->remote_description()->type() != |
| 1043 SessionDescriptionInterface::kOffer) { |
| 1044 std::string error = "CreateAnswer called without remote offer."; |
| 1045 LOG(LS_ERROR) << error; |
| 1046 PostCreateSessionDescriptionFailure(observer, error); |
| 1047 return; |
| 1048 } |
| 1049 |
| 1050 PeerConnectionInterface::RTCOfferAnswerOptions offer_answer_options; |
| 1051 if (!ConvertConstraintsToOfferAnswerOptions(constraints, |
| 1052 &offer_answer_options)) { |
1066 std::string error = "CreateAnswer called with invalid constraints."; | 1053 std::string error = "CreateAnswer called with invalid constraints."; |
1067 LOG(LS_ERROR) << error; | 1054 LOG(LS_ERROR) << error; |
1068 PostCreateSessionDescriptionFailure(observer, error); | 1055 PostCreateSessionDescriptionFailure(observer, error); |
1069 return; | 1056 return; |
1070 } | 1057 } |
1071 | 1058 |
| 1059 cricket::MediaSessionOptions session_options; |
| 1060 GetOptionsForAnswer(offer_answer_options, &session_options); |
1072 session_->CreateAnswer(observer, session_options); | 1061 session_->CreateAnswer(observer, session_options); |
1073 } | 1062 } |
1074 | 1063 |
1075 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, | 1064 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, |
1076 const RTCOfferAnswerOptions& options) { | 1065 const RTCOfferAnswerOptions& options) { |
1077 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); | 1066 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); |
1078 if (!VERIFY(observer != nullptr)) { | 1067 if (!VERIFY(observer != nullptr)) { |
1079 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; | 1068 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; |
1080 return; | 1069 return; |
1081 } | 1070 } |
1082 | 1071 |
1083 cricket::MediaSessionOptions session_options; | 1072 cricket::MediaSessionOptions session_options; |
1084 if (!GetOptionsForAnswer(options, &session_options)) { | 1073 GetOptionsForAnswer(options, &session_options); |
1085 std::string error = "CreateAnswer called with invalid options."; | |
1086 LOG(LS_ERROR) << error; | |
1087 PostCreateSessionDescriptionFailure(observer, error); | |
1088 return; | |
1089 } | |
1090 | |
1091 session_->CreateAnswer(observer, session_options); | 1074 session_->CreateAnswer(observer, session_options); |
1092 } | 1075 } |
1093 | 1076 |
1094 void PeerConnection::SetLocalDescription( | 1077 void PeerConnection::SetLocalDescription( |
1095 SetSessionDescriptionObserver* observer, | 1078 SetSessionDescriptionObserver* observer, |
1096 SessionDescriptionInterface* desc) { | 1079 SessionDescriptionInterface* desc) { |
1097 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); | 1080 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); |
1098 if (IsClosed()) { | 1081 if (IsClosed()) { |
1099 return; | 1082 return; |
1100 } | 1083 } |
(...skipping 583 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1684 | 1667 |
1685 void PeerConnection::PostCreateSessionDescriptionFailure( | 1668 void PeerConnection::PostCreateSessionDescriptionFailure( |
1686 CreateSessionDescriptionObserver* observer, | 1669 CreateSessionDescriptionObserver* observer, |
1687 const std::string& error) { | 1670 const std::string& error) { |
1688 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); | 1671 CreateSessionDescriptionMsg* msg = new CreateSessionDescriptionMsg(observer); |
1689 msg->error = error; | 1672 msg->error = error; |
1690 signaling_thread()->Post(RTC_FROM_HERE, this, | 1673 signaling_thread()->Post(RTC_FROM_HERE, this, |
1691 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); | 1674 MSG_CREATE_SESSIONDESCRIPTION_FAILED, msg); |
1692 } | 1675 } |
1693 | 1676 |
1694 bool PeerConnection::GetOptionsForOffer( | 1677 void PeerConnection::GetOptionsForOffer( |
1695 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | 1678 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, |
1696 cricket::MediaSessionOptions* session_options) { | 1679 cricket::MediaSessionOptions* session_options) { |
1697 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of | 1680 ExtractSharedMediaSessionOptions(rtc_options, session_options); |
1698 // ContentInfos. | 1681 |
| 1682 // Figure out transceiver directional preferences. |
| 1683 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO); |
| 1684 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO); |
| 1685 // By default, generate sendrecv/recvonly m= sections. |
| 1686 bool recv_audio = true; |
| 1687 bool recv_video = true; |
| 1688 // By default, only offer a new m= section if we have media to send with it. |
| 1689 bool offer_new_audio_description = send_audio; |
| 1690 bool offer_new_video_description = send_video; |
| 1691 bool offer_new_data_description = HasDataChannels(); |
| 1692 // The "offer_to_receive_X" options allow those defaults to be overridden. |
| 1693 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) { |
| 1694 recv_audio = (rtc_options.offer_to_receive_audio > 0); |
| 1695 offer_new_audio_description = (rtc_options.offer_to_receive_audio > 0); |
| 1696 } |
| 1697 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { |
| 1698 recv_video = (rtc_options.offer_to_receive_video > 0); |
| 1699 offer_new_video_description = (rtc_options.offer_to_receive_video > 0); |
| 1700 } |
| 1701 |
| 1702 int audio_index = -1; |
| 1703 int video_index = -1; |
| 1704 int data_index = -1; |
| 1705 // If a current description exists, generate m= sections in the same order, |
| 1706 // using the first audio/video/data section that appears and rejecting |
| 1707 // extraneous ones. |
1699 if (session_->local_description()) { | 1708 if (session_->local_description()) { |
1700 for (const cricket::ContentInfo& content : | 1709 for (const cricket::ContentInfo& content : |
1701 session_->local_description()->description()->contents()) { | 1710 session_->local_description()->description()->contents()) { |
1702 session_options->transport_options[content.name] = | 1711 if (IsAudioContent(&content)) { |
1703 cricket::TransportOptions(); | 1712 // If we already have an audio m= section, reject this extra one. |
| 1713 if (audio_index != -1) { |
| 1714 session_options->media_description_options.push_back( |
| 1715 cricket::MediaDescriptionOptions( |
| 1716 cricket::MEDIA_TYPE_AUDIO, content.name, |
| 1717 cricket::RtpTransceiverDirection(false, false), true)); |
| 1718 } else { |
| 1719 session_options->media_description_options.push_back( |
| 1720 cricket::MediaDescriptionOptions( |
| 1721 cricket::MEDIA_TYPE_AUDIO, content.name, |
| 1722 cricket::RtpTransceiverDirection(send_audio, recv_audio), |
| 1723 false)); |
| 1724 audio_index = session_options->media_description_options.size() - 1; |
| 1725 } |
| 1726 } else if (IsVideoContent(&content)) { |
| 1727 // If we already have an video m= section, reject this extra one. |
| 1728 if (video_index != -1) { |
| 1729 session_options->media_description_options.push_back( |
| 1730 cricket::MediaDescriptionOptions( |
| 1731 cricket::MEDIA_TYPE_VIDEO, content.name, |
| 1732 cricket::RtpTransceiverDirection(false, false), true)); |
| 1733 } else { |
| 1734 session_options->media_description_options.push_back( |
| 1735 cricket::MediaDescriptionOptions( |
| 1736 cricket::MEDIA_TYPE_VIDEO, content.name, |
| 1737 cricket::RtpTransceiverDirection(send_video, recv_video), |
| 1738 false)); |
| 1739 video_index = session_options->media_description_options.size() - 1; |
| 1740 } |
| 1741 } else { |
| 1742 RTC_DCHECK(IsDataContent(&content)); |
| 1743 // If we already have an data m= section, reject this extra one. |
| 1744 if (data_index != -1) { |
| 1745 session_options->media_description_options.push_back( |
| 1746 cricket::MediaDescriptionOptions( |
| 1747 cricket::MEDIA_TYPE_DATA, content.name, |
| 1748 cricket::RtpTransceiverDirection(false, false), true)); |
| 1749 } else { |
| 1750 session_options->media_description_options.push_back( |
| 1751 cricket::MediaDescriptionOptions( |
| 1752 cricket::MEDIA_TYPE_DATA, content.name, |
| 1753 // Direction for data sections is meaningless, but legacy |
| 1754 // endpoints might expect sendrecv. |
| 1755 cricket::RtpTransceiverDirection(true, true), false)); |
| 1756 data_index = session_options->media_description_options.size() - 1; |
| 1757 } |
| 1758 } |
1704 } | 1759 } |
1705 } | 1760 } |
1706 session_options->enable_ice_renomination = | 1761 // Add audio/video/data m= sections to the end if needed. |
1707 configuration_.enable_ice_renomination; | 1762 if (audio_index == -1 && offer_new_audio_description) { |
1708 | 1763 session_options->media_description_options.push_back( |
1709 if (!ExtractMediaSessionOptions(rtc_options, true, session_options)) { | 1764 cricket::MediaDescriptionOptions( |
1710 return false; | 1765 cricket::MEDIA_TYPE_AUDIO, cricket::CN_AUDIO, |
1711 } | 1766 cricket::RtpTransceiverDirection(send_audio, recv_audio), false)); |
1712 | 1767 audio_index = session_options->media_description_options.size() - 1; |
1713 AddSendStreams(session_options, senders_, rtp_data_channels_); | 1768 } |
1714 // Offer to receive audio/video if the constraint is not set and there are | 1769 if (video_index == -1 && offer_new_video_description) { |
1715 // send streams, or we're currently receiving. | 1770 session_options->media_description_options.push_back( |
1716 if (rtc_options.offer_to_receive_audio == RTCOfferAnswerOptions::kUndefined) { | 1771 cricket::MediaDescriptionOptions( |
1717 session_options->recv_audio = | 1772 cricket::MEDIA_TYPE_VIDEO, cricket::CN_VIDEO, |
1718 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_AUDIO) || | 1773 cricket::RtpTransceiverDirection(send_video, recv_video), false)); |
1719 !remote_audio_tracks_.empty(); | 1774 video_index = session_options->media_description_options.size() - 1; |
1720 } | 1775 } |
1721 if (rtc_options.offer_to_receive_video == RTCOfferAnswerOptions::kUndefined) { | 1776 if (data_index == -1 && offer_new_data_description) { |
1722 session_options->recv_video = | 1777 session_options->media_description_options.push_back( |
1723 session_options->HasSendMediaStream(cricket::MEDIA_TYPE_VIDEO) || | 1778 cricket::MediaDescriptionOptions( |
1724 !remote_video_tracks_.empty(); | 1779 cricket::MEDIA_TYPE_DATA, cricket::CN_DATA, |
1725 } | 1780 cricket::RtpTransceiverDirection(true, true), false)); |
| 1781 data_index = session_options->media_description_options.size() - 1; |
| 1782 } |
| 1783 |
| 1784 cricket::MediaDescriptionOptions* audio_media_description_options = |
| 1785 audio_index == -1 |
| 1786 ? nullptr |
| 1787 : &session_options->media_description_options[audio_index]; |
| 1788 cricket::MediaDescriptionOptions* video_media_description_options = |
| 1789 video_index == -1 |
| 1790 ? nullptr |
| 1791 : &session_options->media_description_options[video_index]; |
| 1792 cricket::MediaDescriptionOptions* data_media_description_options = |
| 1793 data_index == -1 |
| 1794 ? nullptr |
| 1795 : &session_options->media_description_options[data_index]; |
| 1796 |
| 1797 // Apply ICE restart flag and renomination flag. |
| 1798 for (auto& options : session_options->media_description_options) { |
| 1799 options.transport_options.ice_restart = rtc_options.ice_restart; |
| 1800 options.transport_options.enable_ice_renomination = |
| 1801 configuration_.enable_ice_renomination; |
| 1802 } |
| 1803 |
| 1804 AddRtpSenderOptions(senders_, audio_media_description_options, |
| 1805 video_media_description_options); |
| 1806 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options); |
1726 | 1807 |
1727 // Intentionally unset the data channel type for RTP data channel with the | 1808 // Intentionally unset the data channel type for RTP data channel with the |
1728 // second condition. Otherwise the RTP data channels would be successfully | 1809 // second condition. Otherwise the RTP data channels would be successfully |
1729 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail | 1810 // negotiated by default and the unit tests in WebRtcDataBrowserTest will fail |
1730 // when building with chromium. We want to leave RTP data channels broken, so | 1811 // when building with chromium. We want to leave RTP data channels broken, so |
1731 // people won't try to use them. | 1812 // people won't try to use them. |
1732 if (HasDataChannels() && session_->data_channel_type() != cricket::DCT_RTP) { | 1813 if (session_->data_channel_type() != cricket::DCT_RTP) { |
1733 session_options->data_channel_type = session_->data_channel_type(); | 1814 session_options->data_channel_type = session_->data_channel_type(); |
1734 } | 1815 } |
1735 | 1816 |
1736 session_options->bundle_enabled = | |
1737 session_options->bundle_enabled && | |
1738 (session_options->has_audio() || session_options->has_video() || | |
1739 session_options->has_data()); | |
1740 | |
1741 session_options->rtcp_cname = rtcp_cname_; | 1817 session_options->rtcp_cname = rtcp_cname_; |
1742 session_options->crypto_options = factory_->options().crypto_options; | 1818 session_options->crypto_options = factory_->options().crypto_options; |
1743 return true; | |
1744 } | 1819 } |
1745 | 1820 |
1746 void PeerConnection::InitializeOptionsForAnswer( | 1821 void PeerConnection::GetOptionsForAnswer( |
| 1822 const RTCOfferAnswerOptions& rtc_options, |
1747 cricket::MediaSessionOptions* session_options) { | 1823 cricket::MediaSessionOptions* session_options) { |
1748 session_options->recv_audio = false; | 1824 ExtractSharedMediaSessionOptions(rtc_options, session_options); |
1749 session_options->recv_video = false; | 1825 |
1750 session_options->enable_ice_renomination = | 1826 // Figure out transceiver directional preferences. |
1751 configuration_.enable_ice_renomination; | 1827 bool send_audio = HasRtpSender(cricket::MEDIA_TYPE_AUDIO); |
1752 } | 1828 bool send_video = HasRtpSender(cricket::MEDIA_TYPE_VIDEO); |
1753 | 1829 // By default, generate sendrecv/recvonly m= sections. |
1754 void PeerConnection::FinishOptionsForAnswer( | 1830 bool recv_audio = true; |
1755 cricket::MediaSessionOptions* session_options) { | 1831 bool recv_video = true; |
1756 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of | 1832 // The "offer_to_receive_X" options allow those defaults to be overridden. |
1757 // ContentInfos. | 1833 if (rtc_options.offer_to_receive_audio != RTCOfferAnswerOptions::kUndefined) { |
1758 if (session_->remote_description()) { | 1834 recv_audio = (rtc_options.offer_to_receive_audio > 0); |
1759 // Initialize the transport_options map. | 1835 } |
1760 for (const cricket::ContentInfo& content : | 1836 if (rtc_options.offer_to_receive_video != RTCOfferAnswerOptions::kUndefined) { |
1761 session_->remote_description()->description()->contents()) { | 1837 recv_video = (rtc_options.offer_to_receive_video > 0); |
1762 session_options->transport_options[content.name] = | 1838 } |
1763 cricket::TransportOptions(); | 1839 |
| 1840 int audio_index = -1; |
| 1841 int video_index = -1; |
| 1842 int data_index = -1; |
| 1843 // There should be a pending remote description that's an offer... |
| 1844 RTC_DCHECK(session_->remote_description()); |
| 1845 RTC_DCHECK(session_->remote_description()->type() == |
| 1846 SessionDescriptionInterface::kOffer); |
| 1847 // Generate m= sections that match those in the offer. |
| 1848 // Note that mediasession.cc will handle intersection our preferred direction |
| 1849 // with the offered direction. |
| 1850 for (const cricket::ContentInfo& content : |
| 1851 session_->remote_description()->description()->contents()) { |
| 1852 if (IsAudioContent(&content)) { |
| 1853 // If we already have an audio m= section, reject this extra one. |
| 1854 if (audio_index != -1) { |
| 1855 session_options->media_description_options.push_back( |
| 1856 cricket::MediaDescriptionOptions( |
| 1857 cricket::MEDIA_TYPE_AUDIO, content.name, |
| 1858 cricket::RtpTransceiverDirection(false, false), true)); |
| 1859 } else { |
| 1860 session_options->media_description_options.push_back( |
| 1861 cricket::MediaDescriptionOptions( |
| 1862 cricket::MEDIA_TYPE_AUDIO, content.name, |
| 1863 cricket::RtpTransceiverDirection(send_audio, recv_audio), |
| 1864 false)); |
| 1865 audio_index = session_options->media_description_options.size() - 1; |
| 1866 } |
| 1867 } else if (IsVideoContent(&content)) { |
| 1868 // If we already have an video m= section, reject this extra one. |
| 1869 if (video_index != -1) { |
| 1870 session_options->media_description_options.push_back( |
| 1871 cricket::MediaDescriptionOptions( |
| 1872 cricket::MEDIA_TYPE_VIDEO, content.name, |
| 1873 cricket::RtpTransceiverDirection(false, false), true)); |
| 1874 } else { |
| 1875 session_options->media_description_options.push_back( |
| 1876 cricket::MediaDescriptionOptions( |
| 1877 cricket::MEDIA_TYPE_VIDEO, content.name, |
| 1878 cricket::RtpTransceiverDirection(send_video, recv_video), |
| 1879 false)); |
| 1880 video_index = session_options->media_description_options.size() - 1; |
| 1881 } |
| 1882 } else { |
| 1883 RTC_DCHECK(IsDataContent(&content)); |
| 1884 // If we already have an data m= section, reject this extra one. |
| 1885 if (data_index != -1) { |
| 1886 session_options->media_description_options.push_back( |
| 1887 cricket::MediaDescriptionOptions( |
| 1888 cricket::MEDIA_TYPE_DATA, content.name, |
| 1889 cricket::RtpTransceiverDirection(false, false), true)); |
| 1890 } else { |
| 1891 session_options->media_description_options.push_back( |
| 1892 cricket::MediaDescriptionOptions( |
| 1893 cricket::MEDIA_TYPE_DATA, content.name, |
| 1894 // Direction for data sections is meaningless, but legacy |
| 1895 // endpoints might expect sendrecv. |
| 1896 cricket::RtpTransceiverDirection(true, true), false)); |
| 1897 data_index = session_options->media_description_options.size() - 1; |
| 1898 } |
1764 } | 1899 } |
1765 } | 1900 } |
1766 AddSendStreams(session_options, senders_, rtp_data_channels_); | 1901 |
1767 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams | 1902 cricket::MediaDescriptionOptions* audio_media_description_options = |
1768 // are not signaled in the SDP so does not go through that path and must be | 1903 audio_index == -1 |
1769 // handled here. | 1904 ? nullptr |
| 1905 : &session_options->media_description_options[audio_index]; |
| 1906 cricket::MediaDescriptionOptions* video_media_description_options = |
| 1907 video_index == -1 |
| 1908 ? nullptr |
| 1909 : &session_options->media_description_options[video_index]; |
| 1910 cricket::MediaDescriptionOptions* data_media_description_options = |
| 1911 data_index == -1 |
| 1912 ? nullptr |
| 1913 : &session_options->media_description_options[data_index]; |
| 1914 |
| 1915 // Apply ICE renomination flag. |
| 1916 for (auto& options : session_options->media_description_options) { |
| 1917 options.transport_options.enable_ice_renomination = |
| 1918 configuration_.enable_ice_renomination; |
| 1919 } |
| 1920 |
| 1921 AddRtpSenderOptions(senders_, audio_media_description_options, |
| 1922 video_media_description_options); |
| 1923 AddRtpDataChannelOptions(rtp_data_channels_, data_media_description_options); |
| 1924 |
1770 // Intentionally unset the data channel type for RTP data channel. Otherwise | 1925 // Intentionally unset the data channel type for RTP data channel. Otherwise |
1771 // the RTP data channels would be successfully negotiated by default and the | 1926 // the RTP data channels would be successfully negotiated by default and the |
1772 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. | 1927 // unit tests in WebRtcDataBrowserTest will fail when building with chromium. |
1773 // We want to leave RTP data channels broken, so people won't try to use them. | 1928 // We want to leave RTP data channels broken, so people won't try to use them. |
1774 if (session_->data_channel_type() != cricket::DCT_RTP) { | 1929 if (session_->data_channel_type() != cricket::DCT_RTP) { |
1775 session_options->data_channel_type = session_->data_channel_type(); | 1930 session_options->data_channel_type = session_->data_channel_type(); |
1776 } | 1931 } |
1777 session_options->bundle_enabled = | |
1778 session_options->bundle_enabled && | |
1779 (session_options->has_audio() || session_options->has_video() || | |
1780 session_options->has_data()); | |
1781 | 1932 |
| 1933 session_options->rtcp_cname = rtcp_cname_; |
1782 session_options->crypto_options = factory_->options().crypto_options; | 1934 session_options->crypto_options = factory_->options().crypto_options; |
1783 } | 1935 } |
1784 | 1936 |
1785 bool PeerConnection::GetOptionsForAnswer( | |
1786 const MediaConstraintsInterface* constraints, | |
1787 cricket::MediaSessionOptions* session_options) { | |
1788 InitializeOptionsForAnswer(session_options); | |
1789 if (!ParseConstraintsForAnswer(constraints, session_options)) { | |
1790 return false; | |
1791 } | |
1792 session_options->rtcp_cname = rtcp_cname_; | |
1793 | |
1794 FinishOptionsForAnswer(session_options); | |
1795 return true; | |
1796 } | |
1797 | |
1798 bool PeerConnection::GetOptionsForAnswer( | |
1799 const RTCOfferAnswerOptions& options, | |
1800 cricket::MediaSessionOptions* session_options) { | |
1801 InitializeOptionsForAnswer(session_options); | |
1802 if (!ExtractMediaSessionOptions(options, false, session_options)) { | |
1803 return false; | |
1804 } | |
1805 session_options->rtcp_cname = rtcp_cname_; | |
1806 | |
1807 FinishOptionsForAnswer(session_options); | |
1808 return true; | |
1809 } | |
1810 | |
1811 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { | 1937 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { |
1812 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); | 1938 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); |
1813 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, | 1939 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, |
1814 media_type, nullptr); | 1940 media_type, nullptr); |
1815 } | 1941 } |
1816 | 1942 |
1817 void PeerConnection::UpdateRemoteStreamsList( | 1943 void PeerConnection::UpdateRemoteStreamsList( |
1818 const cricket::StreamParamsVec& streams, | 1944 const cricket::StreamParamsVec& streams, |
1819 bool default_track_needed, | 1945 bool default_track_needed, |
1820 cricket::MediaType media_type, | 1946 cricket::MediaType media_type, |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2279 } | 2405 } |
2280 | 2406 |
2281 rtc::scoped_refptr<DataChannelInterface> proxy_channel = | 2407 rtc::scoped_refptr<DataChannelInterface> proxy_channel = |
2282 DataChannelProxy::Create(signaling_thread(), channel); | 2408 DataChannelProxy::Create(signaling_thread(), channel); |
2283 // Call both the raw pointer and scoped_refptr versions of the method | 2409 // Call both the raw pointer and scoped_refptr versions of the method |
2284 // for compatibility. | 2410 // for compatibility. |
2285 observer_->OnDataChannel(proxy_channel.get()); | 2411 observer_->OnDataChannel(proxy_channel.get()); |
2286 observer_->OnDataChannel(std::move(proxy_channel)); | 2412 observer_->OnDataChannel(std::move(proxy_channel)); |
2287 } | 2413 } |
2288 | 2414 |
| 2415 bool PeerConnection::HasRtpSender(cricket::MediaType type) const { |
| 2416 return std::find_if( |
| 2417 senders_.begin(), senders_.end(), |
| 2418 [type](const rtc::scoped_refptr< |
| 2419 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { |
| 2420 return sender->media_type() == type; |
| 2421 }) != senders_.end(); |
| 2422 } |
| 2423 |
2289 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { | 2424 RtpSenderInternal* PeerConnection::FindSenderById(const std::string& id) { |
2290 auto it = std::find_if( | 2425 auto it = std::find_if( |
2291 senders_.begin(), senders_.end(), | 2426 senders_.begin(), senders_.end(), |
2292 [id](const rtc::scoped_refptr< | 2427 [id](const rtc::scoped_refptr< |
2293 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { | 2428 RtpSenderProxyWithInternal<RtpSenderInternal>>& sender) { |
2294 return sender->id() == id; | 2429 return sender->id() == id; |
2295 }); | 2430 }); |
2296 return it != senders_.end() ? (*it)->internal() : nullptr; | 2431 return it != senders_.end() ? (*it)->internal() : nullptr; |
2297 } | 2432 } |
2298 | 2433 |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2423 | 2558 |
2424 bool PeerConnection::StartRtcEventLog_w(rtc::PlatformFile file, | 2559 bool PeerConnection::StartRtcEventLog_w(rtc::PlatformFile file, |
2425 int64_t max_size_bytes) { | 2560 int64_t max_size_bytes) { |
2426 return event_log_->StartLogging(file, max_size_bytes); | 2561 return event_log_->StartLogging(file, max_size_bytes); |
2427 } | 2562 } |
2428 | 2563 |
2429 void PeerConnection::StopRtcEventLog_w() { | 2564 void PeerConnection::StopRtcEventLog_w() { |
2430 event_log_->StopLogging(); | 2565 event_log_->StopLogging(); |
2431 } | 2566 } |
2432 } // namespace webrtc | 2567 } // namespace webrtc |
OLD | NEW |