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

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

Issue 2600153004: Adding support for Unified Plan offer/answer negotiation.
Patch Set: Got tests working (aside from ones that need to be completely rewritten) Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/api/peerconnection.h ('k') | webrtc/api/peerconnection_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « webrtc/api/peerconnection.h ('k') | webrtc/api/peerconnection_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698