Chromium Code Reviews| 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 434 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 445 | 445 |
| 446 session_options->vad_enabled = rtc_options.voice_activity_detection; | 446 session_options->vad_enabled = rtc_options.voice_activity_detection; |
| 447 session_options->bundle_enabled = rtc_options.use_rtp_mux; | 447 session_options->bundle_enabled = rtc_options.use_rtp_mux; |
| 448 for (auto& kv : session_options->transport_options) { | 448 for (auto& kv : session_options->transport_options) { |
| 449 kv.second.ice_restart = rtc_options.ice_restart; | 449 kv.second.ice_restart = rtc_options.ice_restart; |
| 450 } | 450 } |
| 451 | 451 |
| 452 return true; | 452 return true; |
| 453 } | 453 } |
| 454 | 454 |
| 455 bool ConvertRtcOptionsForAnswer( | |
| 456 const PeerConnectionInterface::RTCOfferAnswerOptions& rtc_options, | |
| 457 cricket::MediaSessionOptions* session_options) { | |
| 458 return ConvertRtcOptionsForOffer(rtc_options, session_options); | |
| 459 } | |
| 460 | |
| 455 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, | 461 bool ParseConstraintsForAnswer(const MediaConstraintsInterface* constraints, |
| 456 cricket::MediaSessionOptions* session_options) { | 462 cricket::MediaSessionOptions* session_options) { |
| 457 bool value = false; | 463 bool value = false; |
| 458 size_t mandatory_constraints_satisfied = 0; | 464 size_t mandatory_constraints_satisfied = 0; |
| 459 | 465 |
| 460 // kOfferToReceiveAudio defaults to true according to spec. | 466 // kOfferToReceiveAudio defaults to true according to spec. |
| 461 if (!FindConstraint(constraints, | 467 if (!FindConstraint(constraints, |
| 462 MediaConstraintsInterface::kOfferToReceiveAudio, &value, | 468 MediaConstraintsInterface::kOfferToReceiveAudio, &value, |
| 463 &mandatory_constraints_satisfied) || | 469 &mandatory_constraints_satisfied) || |
| 464 value) { | 470 value) { |
| 465 session_options->recv_audio = true; | 471 session_options->recv_audio = true; |
| 466 } | 472 } |
| 467 | 473 |
| 468 // kOfferToReceiveVideo defaults to false according to spec. But | 474 // kOfferToReceiveVideo defaults to false according to spec. But |
| 469 // if it is an answer and video is offered, we should still accept video | 475 // if it is an answer and video is offered, we should still accept video |
|
perkj_webrtc
2016/03/01 08:41:26
Is this no longer true? ie is your ConvertRtcOptio
| |
| 470 // per default. | 476 // per default. |
| 471 value = false; | 477 value = false; |
| 472 if (!FindConstraint(constraints, | 478 if (!FindConstraint(constraints, |
| 473 MediaConstraintsInterface::kOfferToReceiveVideo, &value, | 479 MediaConstraintsInterface::kOfferToReceiveVideo, &value, |
| 474 &mandatory_constraints_satisfied) || | 480 &mandatory_constraints_satisfied) || |
| 475 value) { | 481 value) { |
| 476 session_options->recv_video = true; | 482 session_options->recv_video = true; |
| 477 } | 483 } |
| 478 | 484 |
| 479 if (FindConstraint(constraints, | 485 if (FindConstraint(constraints, |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 558 // since it's about to be destroyed. | 564 // since it's about to be destroyed. |
| 559 for (const auto& sender : senders_) { | 565 for (const auto& sender : senders_) { |
| 560 sender->Stop(); | 566 sender->Stop(); |
| 561 } | 567 } |
| 562 for (const auto& receiver : receivers_) { | 568 for (const auto& receiver : receivers_) { |
| 563 receiver->Stop(); | 569 receiver->Stop(); |
| 564 } | 570 } |
| 565 } | 571 } |
| 566 | 572 |
| 567 bool PeerConnection::Initialize( | 573 bool PeerConnection::Initialize( |
| 574 const cricket::MediaConfig& media_config, | |
| 568 const PeerConnectionInterface::RTCConfiguration& configuration, | 575 const PeerConnectionInterface::RTCConfiguration& configuration, |
| 569 const MediaConstraintsInterface* constraints, | |
| 570 rtc::scoped_ptr<cricket::PortAllocator> allocator, | 576 rtc::scoped_ptr<cricket::PortAllocator> allocator, |
| 571 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, | 577 rtc::scoped_ptr<DtlsIdentityStoreInterface> dtls_identity_store, |
| 572 PeerConnectionObserver* observer) { | 578 PeerConnectionObserver* observer) { |
| 573 TRACE_EVENT0("webrtc", "PeerConnection::Initialize"); | 579 TRACE_EVENT0("webrtc", "PeerConnection::Initialize"); |
| 574 RTC_DCHECK(observer != nullptr); | 580 RTC_DCHECK(observer != nullptr); |
| 575 if (!observer) { | 581 if (!observer) { |
| 576 return false; | 582 return false; |
| 577 } | 583 } |
| 578 observer_ = observer; | 584 observer_ = observer; |
| 579 | 585 |
| 580 port_allocator_ = std::move(allocator); | 586 port_allocator_ = std::move(allocator); |
| 581 | 587 |
| 582 cricket::ServerAddresses stun_servers; | 588 cricket::ServerAddresses stun_servers; |
| 583 std::vector<cricket::RelayServerConfig> turn_servers; | 589 std::vector<cricket::RelayServerConfig> turn_servers; |
| 584 if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) { | 590 if (!ParseIceServers(configuration.servers, &stun_servers, &turn_servers)) { |
| 585 return false; | 591 return false; |
| 586 } | 592 } |
| 587 port_allocator_->SetIceServers(stun_servers, turn_servers); | 593 port_allocator_->SetIceServers(stun_servers, turn_servers); |
| 588 | 594 |
| 589 // To handle both internal and externally created port allocator, we will | 595 // To handle both internal and externally created port allocator, we will |
| 590 // enable BUNDLE here. | 596 // enable BUNDLE here. |
| 591 int portallocator_flags = port_allocator_->flags(); | 597 int portallocator_flags = port_allocator_->flags(); |
| 592 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | | 598 portallocator_flags |= cricket::PORTALLOCATOR_ENABLE_SHARED_SOCKET | |
| 593 cricket::PORTALLOCATOR_ENABLE_IPV6; | 599 cricket::PORTALLOCATOR_ENABLE_IPV6; |
| 594 bool value; | 600 // If the disable-IPv6 flag was specified, we'll not override it |
| 595 // If IPv6 flag was specified, we'll not override it by experiment. | 601 // by experiment. |
| 596 if (FindConstraint(constraints, MediaConstraintsInterface::kEnableIPv6, | 602 if (configuration.disable_ipv6) { |
| 597 &value, nullptr)) { | 603 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); |
| 598 if (!value) { | |
| 599 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); | |
| 600 } | |
| 601 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == | 604 } else if (webrtc::field_trial::FindFullName("WebRTC-IPv6Default") == |
| 602 "Disabled") { | 605 "Disabled") { |
| 603 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); | 606 portallocator_flags &= ~(cricket::PORTALLOCATOR_ENABLE_IPV6); |
| 604 } | 607 } |
| 605 | 608 |
| 606 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { | 609 if (configuration.tcp_candidate_policy == kTcpCandidatePolicyDisabled) { |
| 607 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; | 610 portallocator_flags |= cricket::PORTALLOCATOR_DISABLE_TCP; |
| 608 LOG(LS_INFO) << "TCP candidates are disabled."; | 611 LOG(LS_INFO) << "TCP candidates are disabled."; |
| 609 } | 612 } |
| 610 | 613 |
| 611 port_allocator_->set_flags(portallocator_flags); | 614 port_allocator_->set_flags(portallocator_flags); |
| 612 // No step delay is used while allocating ports. | 615 // No step delay is used while allocating ports. |
| 613 port_allocator_->set_step_delay(cricket::kMinimumStepDelay); | 616 port_allocator_->set_step_delay(cricket::kMinimumStepDelay); |
| 614 | 617 |
| 615 // We rely on default values when constraints aren't found. | |
| 616 cricket::MediaConfig media_config; | |
| 617 | |
| 618 media_config.disable_prerenderer_smoothing = | |
| 619 configuration.disable_prerenderer_smoothing; | |
| 620 | |
| 621 // Find DSCP constraint. | |
| 622 FindConstraint(constraints, MediaConstraintsInterface::kEnableDscp, | |
| 623 &media_config.enable_dscp, NULL); | |
| 624 // Find constraints for cpu overuse detection. | |
| 625 FindConstraint(constraints, MediaConstraintsInterface::kCpuOveruseDetection, | |
| 626 &media_config.enable_cpu_overuse_detection, NULL); | |
| 627 | |
| 628 media_controller_.reset(factory_->CreateMediaController(media_config)); | 618 media_controller_.reset(factory_->CreateMediaController(media_config)); |
| 629 | 619 |
| 630 remote_stream_factory_.reset(new RemoteMediaStreamFactory( | 620 remote_stream_factory_.reset(new RemoteMediaStreamFactory( |
| 631 factory_->signaling_thread(), media_controller_->channel_manager())); | 621 factory_->signaling_thread(), media_controller_->channel_manager())); |
| 632 | 622 |
| 633 session_.reset( | 623 session_.reset( |
| 634 new WebRtcSession(media_controller_.get(), factory_->signaling_thread(), | 624 new WebRtcSession(media_controller_.get(), factory_->signaling_thread(), |
| 635 factory_->worker_thread(), port_allocator_.get())); | 625 factory_->worker_thread(), port_allocator_.get())); |
| 636 stats_.reset(new StatsCollector(this)); | 626 stats_.reset(new StatsCollector(this)); |
| 637 | 627 |
| 638 // Initialize the WebRtcSession. It creates transport channels etc. | 628 // Initialize the WebRtcSession. It creates transport channels etc. |
| 639 if (!session_->Initialize(factory_->options(), constraints, | 629 if (!session_->Initialize(factory_->options(), std::move(dtls_identity_store), |
| 640 std::move(dtls_identity_store), configuration)) { | 630 configuration)) { |
| 641 return false; | 631 return false; |
| 642 } | 632 } |
| 643 | 633 |
| 644 // Register PeerConnection as receiver of local ice candidates. | 634 // Register PeerConnection as receiver of local ice candidates. |
| 645 // All the callbacks will be posted to the application from PeerConnection. | 635 // All the callbacks will be posted to the application from PeerConnection. |
| 646 session_->RegisterIceObserver(this); | 636 session_->RegisterIceObserver(this); |
| 647 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange); | 637 session_->SignalState.connect(this, &PeerConnection::OnSessionStateChange); |
| 648 session_->SignalVoiceChannelDestroyed.connect( | 638 session_->SignalVoiceChannelDestroyed.connect( |
| 649 this, &PeerConnection::OnVoiceChannelDestroyed); | 639 this, &PeerConnection::OnVoiceChannelDestroyed); |
| 650 session_->SignalVideoChannelDestroyed.connect( | 640 session_->SignalVideoChannelDestroyed.connect( |
| (...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 994 } | 984 } |
| 995 | 985 |
| 996 cricket::MediaSessionOptions session_options; | 986 cricket::MediaSessionOptions session_options; |
| 997 if (!GetOptionsForAnswer(constraints, &session_options)) { | 987 if (!GetOptionsForAnswer(constraints, &session_options)) { |
| 998 std::string error = "CreateAnswer called with invalid constraints."; | 988 std::string error = "CreateAnswer called with invalid constraints."; |
| 999 LOG(LS_ERROR) << error; | 989 LOG(LS_ERROR) << error; |
| 1000 PostCreateSessionDescriptionFailure(observer, error); | 990 PostCreateSessionDescriptionFailure(observer, error); |
| 1001 return; | 991 return; |
| 1002 } | 992 } |
| 1003 | 993 |
| 1004 session_->CreateAnswer(observer, constraints, session_options); | 994 session_->CreateAnswer(observer, session_options); |
| 995 } | |
| 996 | |
| 997 void PeerConnection::CreateAnswer(CreateSessionDescriptionObserver* observer, | |
| 998 const RTCOfferAnswerOptions& options) { | |
| 999 TRACE_EVENT0("webrtc", "PeerConnection::CreateAnswer"); | |
| 1000 if (!VERIFY(observer != nullptr)) { | |
| 1001 LOG(LS_ERROR) << "CreateAnswer - observer is NULL."; | |
| 1002 return; | |
| 1003 } | |
| 1004 | |
| 1005 cricket::MediaSessionOptions session_options; | |
| 1006 if (!GetOptionsForAnswer(options, &session_options)) { | |
| 1007 std::string error = "CreateAnswer called with invalid options."; | |
| 1008 LOG(LS_ERROR) << error; | |
| 1009 PostCreateSessionDescriptionFailure(observer, error); | |
| 1010 return; | |
| 1011 } | |
| 1012 | |
| 1013 session_->CreateAnswer(observer, session_options); | |
| 1005 } | 1014 } |
| 1006 | 1015 |
| 1007 void PeerConnection::SetLocalDescription( | 1016 void PeerConnection::SetLocalDescription( |
| 1008 SetSessionDescriptionObserver* observer, | 1017 SetSessionDescriptionObserver* observer, |
| 1009 SessionDescriptionInterface* desc) { | 1018 SessionDescriptionInterface* desc) { |
| 1010 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); | 1019 TRACE_EVENT0("webrtc", "PeerConnection::SetLocalDescription"); |
| 1011 if (!VERIFY(observer != nullptr)) { | 1020 if (!VERIFY(observer != nullptr)) { |
| 1012 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; | 1021 LOG(LS_ERROR) << "SetLocalDescription - observer is NULL."; |
| 1013 return; | 1022 return; |
| 1014 } | 1023 } |
| (...skipping 511 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1526 session_options->bundle_enabled && | 1535 session_options->bundle_enabled && |
| 1527 (session_options->has_audio() || session_options->has_video() || | 1536 (session_options->has_audio() || session_options->has_video() || |
| 1528 session_options->has_data()); | 1537 session_options->has_data()); |
| 1529 | 1538 |
| 1530 if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) { | 1539 if (session_->data_channel_type() == cricket::DCT_SCTP && HasDataChannels()) { |
| 1531 session_options->data_channel_type = cricket::DCT_SCTP; | 1540 session_options->data_channel_type = cricket::DCT_SCTP; |
| 1532 } | 1541 } |
| 1533 return true; | 1542 return true; |
| 1534 } | 1543 } |
| 1535 | 1544 |
| 1536 bool PeerConnection::GetOptionsForAnswer( | 1545 void PeerConnection::FinishOptionsForAnswer( |
|
perkj_webrtc
2016/03/01 08:41:26
FillTransportOptionsForAnswer ?
| |
| 1537 const MediaConstraintsInterface* constraints, | |
| 1538 cricket::MediaSessionOptions* session_options) { | 1546 cricket::MediaSessionOptions* session_options) { |
| 1539 session_options->recv_audio = false; | |
| 1540 session_options->recv_video = false; | |
| 1541 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of | 1547 // TODO(deadbeef): Once we have transceivers, enumerate them here instead of |
| 1542 // ContentInfos. | 1548 // ContentInfos. |
| 1543 if (session_->remote_description()) { | 1549 if (session_->remote_description()) { |
| 1544 // Initialize the transport_options map. | 1550 // Initialize the transport_options map. |
| 1545 for (const cricket::ContentInfo& content : | 1551 for (const cricket::ContentInfo& content : |
| 1546 session_->remote_description()->description()->contents()) { | 1552 session_->remote_description()->description()->contents()) { |
| 1547 session_options->transport_options[content.name] = | 1553 session_options->transport_options[content.name] = |
| 1548 cricket::TransportOptions(); | 1554 cricket::TransportOptions(); |
| 1549 } | 1555 } |
| 1550 } | 1556 } |
| 1551 if (!ParseConstraintsForAnswer(constraints, session_options)) { | |
| 1552 return false; | |
| 1553 } | |
| 1554 | |
| 1555 AddSendStreams(session_options, senders_, rtp_data_channels_); | 1557 AddSendStreams(session_options, senders_, rtp_data_channels_); |
| 1556 session_options->bundle_enabled = | 1558 session_options->bundle_enabled = |
| 1557 session_options->bundle_enabled && | 1559 session_options->bundle_enabled && |
| 1558 (session_options->has_audio() || session_options->has_video() || | 1560 (session_options->has_audio() || session_options->has_video() || |
| 1559 session_options->has_data()); | 1561 session_options->has_data()); |
| 1560 | 1562 |
| 1561 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams | 1563 // RTP data channel is handled in MediaSessionOptions::AddStream. SCTP streams |
| 1562 // are not signaled in the SDP so does not go through that path and must be | 1564 // are not signaled in the SDP so does not go through that path and must be |
| 1563 // handled here. | 1565 // handled here. |
| 1564 if (session_->data_channel_type() == cricket::DCT_SCTP) { | 1566 if (session_->data_channel_type() == cricket::DCT_SCTP) { |
| 1565 session_options->data_channel_type = cricket::DCT_SCTP; | 1567 session_options->data_channel_type = cricket::DCT_SCTP; |
| 1566 } | 1568 } |
| 1569 } | |
| 1570 | |
| 1571 bool PeerConnection::GetOptionsForAnswer( | |
| 1572 const MediaConstraintsInterface* constraints, | |
| 1573 cricket::MediaSessionOptions* session_options) { | |
| 1574 session_options->recv_audio = false; | |
| 1575 session_options->recv_video = false; | |
| 1576 if (!ParseConstraintsForAnswer(constraints, session_options)) { | |
| 1577 return false; | |
| 1578 } | |
| 1579 FinishOptionsForAnswer(session_options); | |
| 1567 return true; | 1580 return true; |
| 1568 } | 1581 } |
| 1569 | 1582 |
| 1583 bool PeerConnection::GetOptionsForAnswer( | |
| 1584 const RTCOfferAnswerOptions& options, | |
| 1585 cricket::MediaSessionOptions* session_options) { | |
| 1586 session_options->recv_audio = false; | |
| 1587 session_options->recv_video = false; | |
| 1588 if (!ConvertRtcOptionsForAnswer(options, session_options)) { | |
| 1589 return false; | |
| 1590 } | |
| 1591 FinishOptionsForAnswer(session_options); | |
| 1592 return true; | |
| 1593 } | |
| 1594 | |
| 1570 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { | 1595 void PeerConnection::RemoveTracks(cricket::MediaType media_type) { |
| 1571 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); | 1596 UpdateLocalTracks(std::vector<cricket::StreamParams>(), media_type); |
| 1572 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, | 1597 UpdateRemoteStreamsList(std::vector<cricket::StreamParams>(), false, |
| 1573 media_type, nullptr); | 1598 media_type, nullptr); |
| 1574 } | 1599 } |
| 1575 | 1600 |
| 1576 void PeerConnection::UpdateRemoteStreamsList( | 1601 void PeerConnection::UpdateRemoteStreamsList( |
| 1577 const cricket::StreamParamsVec& streams, | 1602 const cricket::StreamParamsVec& streams, |
| 1578 bool default_track_needed, | 1603 bool default_track_needed, |
| 1579 cricket::MediaType media_type, | 1604 cricket::MediaType media_type, |
| (...skipping 512 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2092 | 2117 |
| 2093 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { | 2118 DataChannel* PeerConnection::FindDataChannelBySid(int sid) const { |
| 2094 for (const auto& channel : sctp_data_channels_) { | 2119 for (const auto& channel : sctp_data_channels_) { |
| 2095 if (channel->id() == sid) { | 2120 if (channel->id() == sid) { |
| 2096 return channel; | 2121 return channel; |
| 2097 } | 2122 } |
| 2098 } | 2123 } |
| 2099 return nullptr; | 2124 return nullptr; |
| 2100 } | 2125 } |
| 2101 | 2126 |
| 2127 void CopyConstraintsIntoRtcConfiguration( | |
|
perkj_webrtc
2016/03/01 08:41:26
I still think this should be moved to where it is
| |
| 2128 const MediaConstraintsInterface* constraints, | |
| 2129 PeerConnectionInterface::RTCConfiguration* configuration) { | |
| 2130 // Copy info from constraints into configuration, if present. | |
| 2131 if (!constraints) { | |
| 2132 return; | |
| 2133 } | |
| 2134 | |
| 2135 bool value; | |
| 2136 if (FindConstraint(constraints, MediaConstraintsInterface::kEnableIPv6, | |
| 2137 &value, nullptr)) { | |
| 2138 if (!value) { | |
| 2139 configuration->disable_ipv6 = true; | |
| 2140 } | |
| 2141 } | |
| 2142 configuration->enable_dscp = ConstraintToOptionalBool( | |
| 2143 constraints, MediaConstraintsInterface::kEnableDscp); | |
| 2144 configuration->cpu_overuse_detection = ConstraintToOptionalBool( | |
| 2145 constraints, MediaConstraintsInterface::kCpuOveruseDetection); | |
| 2146 if (FindConstraint(constraints, | |
| 2147 MediaConstraintsInterface::kEnableRtpDataChannels, &value, | |
| 2148 NULL) && | |
| 2149 value) { | |
| 2150 configuration->enable_rtp_data_channel = true; | |
| 2151 } | |
| 2152 // Find Suspend Below Min Bitrate constraint. | |
| 2153 configuration->suspend_below_min_bitrate = ConstraintToOptionalBool( | |
| 2154 constraints, | |
| 2155 MediaConstraintsInterface::kEnableVideoSuspendBelowMinBitrate); | |
| 2156 configuration->screencast_min_bitrate = ConstraintToOptionalInt( | |
| 2157 constraints, MediaConstraintsInterface::kScreencastMinBitrate); | |
| 2158 configuration->combined_audio_video_bwe = ConstraintToOptionalBool( | |
| 2159 constraints, MediaConstraintsInterface::kCombinedAudioVideoBwe); | |
| 2160 configuration->enable_dtls_srtp = ConstraintToOptionalBool( | |
| 2161 constraints, MediaConstraintsInterface::kEnableDtlsSrtp); | |
| 2162 } | |
| 2163 | |
| 2102 } // namespace webrtc | 2164 } // namespace webrtc |
| OLD | NEW |