diff --git a/webrtc/api/webrtcsession.cc b/webrtc/api/webrtcsession.cc index e7d9b14fb6..80352cf832 100644 --- a/webrtc/api/webrtcsession.cc +++ b/webrtc/api/webrtcsession.cc @@ -1739,13 +1739,41 @@ void WebRtcSession::RemoveUnusedChannels(const SessionDescription* desc) { } } -// TODO(mallinath) - Add a correct error code if the channels are not created -// due to BUNDLE is enabled but rtcp-mux is disabled. +// Returns the name of the transport channel when BUNDLE is enabled, or nullptr +// if the channel is not part of any bundle. +const std::string* WebRtcSession::GetBundleTransportName( + const cricket::ContentInfo* content, + const cricket::ContentGroup* bundle) { + if (!bundle) { + return nullptr; + } + const std::string* first_content_name = bundle->FirstContentName(); + if (!first_content_name) { + LOG(LS_WARNING) << "Tried to BUNDLE with no contents."; + return nullptr; + } + if (!bundle->HasContentName(content->name)) { + LOG(LS_WARNING) << content->name << " is not part of any bundle group"; + return nullptr; + } + LOG(LS_INFO) << "Bundling " << content->name << " on " << *first_content_name; + return first_content_name; +} + bool WebRtcSession::CreateChannels(const SessionDescription* desc) { + const cricket::ContentGroup* bundle_group = nullptr; + if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { + bundle_group = desc->GetGroupByName(cricket::GROUP_TYPE_BUNDLE); + if (!bundle_group) { + LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; + return false; + } + } // Creating the media channels and transport proxies. const cricket::ContentInfo* voice = cricket::GetFirstAudioContent(desc); if (voice && !voice->rejected && !voice_channel_) { - if (!CreateVoiceChannel(voice)) { + if (!CreateVoiceChannel(voice, + GetBundleTransportName(voice, bundle_group))) { LOG(LS_ERROR) << "Failed to create voice channel."; return false; } @@ -1753,7 +1781,8 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) { const cricket::ContentInfo* video = cricket::GetFirstVideoContent(desc); if (video && !video->rejected && !video_channel_) { - if (!CreateVideoChannel(video)) { + if (!CreateVideoChannel(video, + GetBundleTransportName(video, bundle_group))) { LOG(LS_ERROR) << "Failed to create video channel."; return false; } @@ -1762,48 +1791,29 @@ bool WebRtcSession::CreateChannels(const SessionDescription* desc) { const cricket::ContentInfo* data = cricket::GetFirstDataContent(desc); if (data_channel_type_ != cricket::DCT_NONE && data && !data->rejected && !data_channel_) { - if (!CreateDataChannel(data)) { + if (!CreateDataChannel(data, GetBundleTransportName(data, bundle_group))) { LOG(LS_ERROR) << "Failed to create data channel."; return false; } } - if (rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire) { - if (voice_channel()) { - voice_channel()->ActivateRtcpMux(); - } - if (video_channel()) { - video_channel()->ActivateRtcpMux(); - } - if (data_channel()) { - data_channel()->ActivateRtcpMux(); - } - } - - // Enable BUNDLE immediately when kBundlePolicyMaxBundle is in effect. - if (bundle_policy_ == PeerConnectionInterface::kBundlePolicyMaxBundle) { - const cricket::ContentGroup* bundle_group = desc->GetGroupByName( - cricket::GROUP_TYPE_BUNDLE); - if (!bundle_group) { - LOG(LS_WARNING) << "max-bundle specified without BUNDLE specified"; - return false; - } - if (!EnableBundle(*bundle_group)) { - LOG(LS_WARNING) << "max-bundle failed to enable bundling."; - return false; - } - } - return true; } -bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) { +bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content, + const std::string* bundle_transport) { + bool require_rtcp_mux = + rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire; + bool create_rtcp_transport_channel = !require_rtcp_mux; voice_channel_.reset(channel_manager_->CreateVoiceChannel( - media_controller_, transport_controller_.get(), content->name, true, - audio_options_)); + media_controller_, transport_controller_.get(), content->name, + bundle_transport, create_rtcp_transport_channel, audio_options_)); if (!voice_channel_) { return false; } + if (require_rtcp_mux) { + voice_channel_->ActivateRtcpMux(); + } voice_channel_->SignalDtlsSetupFailure.connect( this, &WebRtcSession::OnDtlsSetupFailure); @@ -1814,14 +1824,20 @@ bool WebRtcSession::CreateVoiceChannel(const cricket::ContentInfo* content) { return true; } -bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) { +bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content, + const std::string* bundle_transport) { + bool require_rtcp_mux = + rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire; + bool create_rtcp_transport_channel = !require_rtcp_mux; video_channel_.reset(channel_manager_->CreateVideoChannel( - media_controller_, transport_controller_.get(), content->name, true, - video_options_)); + media_controller_, transport_controller_.get(), content->name, + bundle_transport, create_rtcp_transport_channel, video_options_)); if (!video_channel_) { return false; } - + if (require_rtcp_mux) { + video_channel_->ActivateRtcpMux(); + } video_channel_->SignalDtlsSetupFailure.connect( this, &WebRtcSession::OnDtlsSetupFailure); @@ -1831,13 +1847,21 @@ bool WebRtcSession::CreateVideoChannel(const cricket::ContentInfo* content) { return true; } -bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content) { +bool WebRtcSession::CreateDataChannel(const cricket::ContentInfo* content, + const std::string* bundle_transport) { bool sctp = (data_channel_type_ == cricket::DCT_SCTP); + bool require_rtcp_mux = + rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire; + bool create_rtcp_transport_channel = !sctp && !require_rtcp_mux; data_channel_.reset(channel_manager_->CreateDataChannel( - transport_controller_.get(), content->name, !sctp, data_channel_type_)); + transport_controller_.get(), content->name, bundle_transport, + create_rtcp_transport_channel, data_channel_type_)); if (!data_channel_) { return false; } + if (require_rtcp_mux) { + data_channel_->ActivateRtcpMux(); + } if (sctp) { data_channel_->SignalDataReceived.connect( @@ -1950,6 +1974,9 @@ bool WebRtcSession::ValidateSessionDescription( return BadSdp(source, type, kBundleWithoutRtcpMux, err_desc); } + // TODO(skvlad): When the local rtcp-mux policy is Require, reject any + // m-lines that do not rtcp-mux enabled. + // Verify m-lines in Answer when compared against Offer. if (action == kAnswer) { const cricket::SessionDescription* offer_desc = diff --git a/webrtc/api/webrtcsession.h b/webrtc/api/webrtcsession.h index a97bd7306c..98217bff26 100644 --- a/webrtc/api/webrtcsession.h +++ b/webrtc/api/webrtcsession.h @@ -386,6 +386,12 @@ class WebRtcSession : public AudioProviderInterface, const std::string& content_name, cricket::TransportDescription* info); + // Returns the name of the transport channel when BUNDLE is enabled, or + // nullptr if the channel is not part of any bundle. + const std::string* GetBundleTransportName( + const cricket::ContentInfo* content, + const cricket::ContentGroup* bundle); + // Cause all the BaseChannels in the bundle group to have the same // transport channel. bool EnableBundle(const cricket::ContentGroup& bundle); @@ -412,9 +418,12 @@ class WebRtcSession : public AudioProviderInterface, bool CreateChannels(const cricket::SessionDescription* desc); // Helper methods to create media channels. - bool CreateVoiceChannel(const cricket::ContentInfo* content); - bool CreateVideoChannel(const cricket::ContentInfo* content); - bool CreateDataChannel(const cricket::ContentInfo* content); + bool CreateVoiceChannel(const cricket::ContentInfo* content, + const std::string* bundle_transport); + bool CreateVideoChannel(const cricket::ContentInfo* content, + const std::string* bundle_transport); + bool CreateDataChannel(const cricket::ContentInfo* content, + const std::string* bundle_transport); // Listens to SCTP CONTROL messages on unused SIDs and process them as OPEN // messages. diff --git a/webrtc/api/webrtcsession_unittest.cc b/webrtc/api/webrtcsession_unittest.cc index ea8b3c546e..4207c24234 100644 --- a/webrtc/api/webrtcsession_unittest.cc +++ b/webrtc/api/webrtcsession_unittest.cc @@ -163,6 +163,7 @@ class MockIceObserver : public webrtc::IceObserver { void OnIceConnectionChange( PeerConnectionInterface::IceConnectionState new_state) override { ice_connection_state_ = new_state; + ice_connection_state_history_.push_back(new_state); } void OnIceGatheringChange( PeerConnectionInterface::IceGatheringState new_state) override { @@ -202,6 +203,8 @@ class MockIceObserver : public webrtc::IceObserver { std::vector mline_1_candidates_; PeerConnectionInterface::IceConnectionState ice_connection_state_; PeerConnectionInterface::IceGatheringState ice_gathering_state_; + std::vector + ice_connection_state_history_; size_t num_candidates_removed_ = 0; }; @@ -3263,6 +3266,60 @@ TEST_F(WebRtcSessionTest, TestMaxBundleWithSetRemoteDescriptionFirst) { session_->video_rtp_transport_channel()); } +// Adding a new channel to a BUNDLE which is already connected should directly +// assign the bundle transport to the channel, without first setting a +// disconnected non-bundle transport and then replacing it. The application +// should not receive any changes in the ICE state. +TEST_F(WebRtcSessionTest, TestAddChannelToConnectedBundle) { + LoopbackNetworkConfiguration config; + LoopbackNetworkManager loopback_network_manager(this, config); + // Both BUNDLE and RTCP-mux need to be enabled for the ICE state to remain + // connected. Disabling either of these two means that we need to wait for the + // answer to find out if more transports are needed. + configuration_.bundle_policy = + PeerConnectionInterface::kBundlePolicyMaxBundle; + configuration_.rtcp_mux_policy = + PeerConnectionInterface::kRtcpMuxPolicyRequire; + options_.disable_encryption = true; + Init(); + + // Negotiate an audio channel with MAX_BUNDLE enabled. + SendAudioOnlyStream2(); + SessionDescriptionInterface* offer = CreateOffer(); + SetLocalDescriptionWithoutError(offer); + EXPECT_EQ_WAIT(PeerConnectionInterface::kIceGatheringComplete, + observer_.ice_gathering_state_, kIceCandidatesTimeout); + std::string sdp; + offer->ToString(&sdp); + SessionDescriptionInterface* answer = webrtc::CreateSessionDescription( + JsepSessionDescription::kAnswer, sdp, nullptr); + ASSERT_TRUE(answer != NULL); + SetRemoteDescriptionWithoutError(answer); + + // Wait for the ICE state to stabilize. + EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted, + observer_.ice_connection_state_, kIceCandidatesTimeout); + observer_.ice_connection_state_history_.clear(); + + // Now add a video channel which should be using the same bundle transport. + SendAudioVideoStream2(); + offer = CreateOffer(); + offer->ToString(&sdp); + SetLocalDescriptionWithoutError(offer); + answer = webrtc::CreateSessionDescription(JsepSessionDescription::kAnswer, + sdp, nullptr); + ASSERT_TRUE(answer != NULL); + SetRemoteDescriptionWithoutError(answer); + + // Wait for ICE state to stabilize + rtc::Thread::Current()->ProcessMessages(0); + EXPECT_EQ_WAIT(PeerConnectionInterface::kIceConnectionCompleted, + observer_.ice_connection_state_, kIceCandidatesTimeout); + + // No ICE state changes are expected to happen. + EXPECT_EQ(0, observer_.ice_connection_state_history_.size()); +} + TEST_F(WebRtcSessionTest, TestRequireRtcpMux) { InitWithRtcpMuxPolicy(PeerConnectionInterface::kRtcpMuxPolicyRequire); SendAudioVideoStream1(); diff --git a/webrtc/pc/channel.cc b/webrtc/pc/channel.cc index 7a0d1efaff..97c1d66910 100644 --- a/webrtc/pc/channel.cc +++ b/webrtc/pc/channel.cc @@ -229,8 +229,9 @@ void BaseChannel::DestroyTransportChannels_n() { network_thread_->Clear(this); } -bool BaseChannel::Init_w() { - if (!network_thread_->Invoke(Bind(&BaseChannel::InitNetwork_n, this))) { +bool BaseChannel::Init_w(const std::string* bundle_transport_name) { + if (!network_thread_->Invoke( + Bind(&BaseChannel::InitNetwork_n, this, bundle_transport_name))) { return false; } @@ -241,9 +242,11 @@ bool BaseChannel::Init_w() { return true; } -bool BaseChannel::InitNetwork_n() { +bool BaseChannel::InitNetwork_n(const std::string* bundle_transport_name) { RTC_DCHECK(network_thread_->IsCurrent()); - if (!SetTransport_n(content_name())) { + const std::string& transport_name = + (bundle_transport_name ? *bundle_transport_name : content_name()); + if (!SetTransport_n(transport_name)) { return false; } @@ -1476,8 +1479,8 @@ VoiceChannel::~VoiceChannel() { Deinit(); } -bool VoiceChannel::Init_w() { - if (!BaseChannel::Init_w()) { +bool VoiceChannel::Init_w(const std::string* bundle_transport_name) { + if (!BaseChannel::Init_w(bundle_transport_name)) { return false; } return true; @@ -1831,8 +1834,8 @@ VideoChannel::VideoChannel(rtc::Thread* worker_thread, content_name, rtcp) {} -bool VideoChannel::Init_w() { - if (!BaseChannel::Init_w()) { +bool VideoChannel::Init_w(const std::string* bundle_transport_name) { + if (!BaseChannel::Init_w(bundle_transport_name)) { return false; } return true; @@ -2103,8 +2106,8 @@ DataChannel::~DataChannel() { Deinit(); } -bool DataChannel::Init_w() { - if (!BaseChannel::Init_w()) { +bool DataChannel::Init_w(const std::string* bundle_transport_name) { + if (!BaseChannel::Init_w(bundle_transport_name)) { return false; } media_channel()->SignalDataReceived.connect( diff --git a/webrtc/pc/channel.h b/webrtc/pc/channel.h index 32828bbea5..d9f5fd6d27 100644 --- a/webrtc/pc/channel.h +++ b/webrtc/pc/channel.h @@ -77,7 +77,7 @@ class BaseChannel const std::string& content_name, bool rtcp); virtual ~BaseChannel(); - bool Init_w(); + bool Init_w(const std::string* bundle_transport_name); // Deinit may be called multiple times and is simply ignored if it's already // done. void Deinit(); @@ -313,7 +313,7 @@ class BaseChannel } private: - bool InitNetwork_n(); + bool InitNetwork_n(const std::string* bundle_transport_name); void DisconnectTransportChannels_n(); void DestroyTransportChannels_n(); void SignalSentPacket_n(TransportChannel* channel, @@ -373,7 +373,7 @@ class VoiceChannel : public BaseChannel { const std::string& content_name, bool rtcp); ~VoiceChannel(); - bool Init_w(); + bool Init_w(const std::string* bundle_transport_name); // Configure sending media on the stream with SSRC |ssrc| // If there is only one sending stream SSRC 0 can be used. @@ -489,7 +489,7 @@ class VideoChannel : public BaseChannel { const std::string& content_name, bool rtcp); ~VideoChannel(); - bool Init_w(); + bool Init_w(const std::string* bundle_transport_name); // downcasts a MediaChannel VideoMediaChannel* media_channel() const override { @@ -564,7 +564,7 @@ class DataChannel : public BaseChannel { const std::string& content_name, bool rtcp); ~DataChannel(); - bool Init_w(); + bool Init_w(const std::string* bundle_transport_name); virtual bool SendData(const SendDataParams& params, const rtc::CopyOnWriteBuffer& payload, diff --git a/webrtc/pc/channel_unittest.cc b/webrtc/pc/channel_unittest.cc index 5c5eefa5cb..6c6a3c10e4 100644 --- a/webrtc/pc/channel_unittest.cc +++ b/webrtc/pc/channel_unittest.cc @@ -190,7 +190,7 @@ class ChannelTest : public testing::Test, public sigslot::has_slots<> { typename T::Channel* channel = new typename T::Channel(worker_thread, network_thread, engine, ch, transport_controller, cricket::CN_AUDIO, rtcp); - if (!channel->Init_w()) { + if (!channel->Init_w(nullptr)) { delete channel; channel = NULL; } @@ -2018,7 +2018,7 @@ cricket::VideoChannel* ChannelTest::CreateChannel( cricket::VideoChannel* channel = new cricket::VideoChannel(worker_thread, network_thread, ch, transport_controller, cricket::CN_VIDEO, rtcp); - if (!channel->Init_w()) { + if (!channel->Init_w(nullptr)) { delete channel; channel = NULL; } @@ -3258,7 +3258,7 @@ cricket::DataChannel* ChannelTest::CreateChannel( cricket::DataChannel* channel = new cricket::DataChannel(worker_thread, network_thread, ch, transport_controller, cricket::CN_DATA, rtcp); - if (!channel->Init_w()) { + if (!channel->Init_w(nullptr)) { delete channel; channel = NULL; } diff --git a/webrtc/pc/channelmanager.cc b/webrtc/pc/channelmanager.cc index 126eb1c172..56dd135549 100644 --- a/webrtc/pc/channelmanager.cc +++ b/webrtc/pc/channelmanager.cc @@ -205,17 +205,20 @@ VoiceChannel* ChannelManager::CreateVoiceChannel( webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const AudioOptions& options) { return worker_thread_->Invoke( Bind(&ChannelManager::CreateVoiceChannel_w, this, media_controller, - transport_controller, content_name, rtcp, options)); + transport_controller, content_name, bundle_transport_name, rtcp, + options)); } VoiceChannel* ChannelManager::CreateVoiceChannel_w( webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const AudioOptions& options) { ASSERT(initialized_); @@ -229,7 +232,7 @@ VoiceChannel* ChannelManager::CreateVoiceChannel_w( VoiceChannel* voice_channel = new VoiceChannel(worker_thread_, network_thread_, media_engine_.get(), media_channel, transport_controller, content_name, rtcp); - if (!voice_channel->Init_w()) { + if (!voice_channel->Init_w(bundle_transport_name)) { delete voice_channel; return nullptr; } @@ -263,17 +266,20 @@ VideoChannel* ChannelManager::CreateVideoChannel( webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const VideoOptions& options) { return worker_thread_->Invoke( Bind(&ChannelManager::CreateVideoChannel_w, this, media_controller, - transport_controller, content_name, rtcp, options)); + transport_controller, content_name, bundle_transport_name, rtcp, + options)); } VideoChannel* ChannelManager::CreateVideoChannel_w( webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const VideoOptions& options) { ASSERT(initialized_); @@ -288,7 +294,7 @@ VideoChannel* ChannelManager::CreateVideoChannel_w( VideoChannel* video_channel = new VideoChannel(worker_thread_, network_thread_, media_channel, transport_controller, content_name, rtcp); - if (!video_channel->Init_w()) { + if (!video_channel->Init_w(bundle_transport_name)) { delete video_channel; return NULL; } @@ -322,16 +328,18 @@ void ChannelManager::DestroyVideoChannel_w(VideoChannel* video_channel) { DataChannel* ChannelManager::CreateDataChannel( TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, DataChannelType channel_type) { return worker_thread_->Invoke( Bind(&ChannelManager::CreateDataChannel_w, this, transport_controller, - content_name, rtcp, channel_type)); + content_name, bundle_transport_name, rtcp, channel_type)); } DataChannel* ChannelManager::CreateDataChannel_w( TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, DataChannelType data_channel_type) { // This is ok to alloc from a thread other than the worker thread. @@ -347,7 +355,7 @@ DataChannel* ChannelManager::CreateDataChannel_w( DataChannel* data_channel = new DataChannel(worker_thread_, network_thread_, media_channel, transport_controller, content_name, rtcp); - if (!data_channel->Init_w()) { + if (!data_channel->Init_w(bundle_transport_name)) { LOG(LS_WARNING) << "Failed to init data channel."; delete data_channel; return NULL; diff --git a/webrtc/pc/channelmanager.h b/webrtc/pc/channelmanager.h index 2c333b0027..3b0c0e967e 100644 --- a/webrtc/pc/channelmanager.h +++ b/webrtc/pc/channelmanager.h @@ -91,6 +91,7 @@ class ChannelManager { webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const AudioOptions& options); // Destroys a voice channel created with the Create API. @@ -101,12 +102,14 @@ class ChannelManager { webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const VideoOptions& options); // Destroys a video channel created with the Create API. void DestroyVideoChannel(VideoChannel* video_channel); DataChannel* CreateDataChannel(TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, DataChannelType data_channel_type); // Destroys a data channel created with the Create API. @@ -158,6 +161,7 @@ class ChannelManager { webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const AudioOptions& options); void DestroyVoiceChannel_w(VoiceChannel* voice_channel); @@ -165,11 +169,13 @@ class ChannelManager { webrtc::MediaControllerInterface* media_controller, TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, const VideoOptions& options); void DestroyVideoChannel_w(VideoChannel* video_channel); DataChannel* CreateDataChannel_w(TransportController* transport_controller, const std::string& content_name, + const std::string* bundle_transport_name, bool rtcp, DataChannelType data_channel_type); void DestroyDataChannel_w(DataChannel* data_channel); diff --git a/webrtc/pc/channelmanager_unittest.cc b/webrtc/pc/channelmanager_unittest.cc index a642af5a26..e5e7b4f7de 100644 --- a/webrtc/pc/channelmanager_unittest.cc +++ b/webrtc/pc/channelmanager_unittest.cc @@ -98,16 +98,17 @@ TEST_F(ChannelManagerTest, StartupShutdownOnThread) { // Test that we can create and destroy a voice and video channel. TEST_F(ChannelManagerTest, CreateDestroyChannels) { EXPECT_TRUE(cm_->Init()); - cricket::VoiceChannel* voice_channel = - cm_->CreateVoiceChannel(&fake_mc_, transport_controller_, - cricket::CN_AUDIO, false, AudioOptions()); + cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel( + &fake_mc_, transport_controller_, cricket::CN_AUDIO, nullptr, false, + AudioOptions()); EXPECT_TRUE(voice_channel != nullptr); - cricket::VideoChannel* video_channel = - cm_->CreateVideoChannel(&fake_mc_, transport_controller_, - cricket::CN_VIDEO, false, VideoOptions()); + cricket::VideoChannel* video_channel = cm_->CreateVideoChannel( + &fake_mc_, transport_controller_, cricket::CN_VIDEO, nullptr, false, + VideoOptions()); EXPECT_TRUE(video_channel != nullptr); - cricket::DataChannel* data_channel = cm_->CreateDataChannel( - transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP); + cricket::DataChannel* data_channel = + cm_->CreateDataChannel(transport_controller_, cricket::CN_DATA, nullptr, + false, cricket::DCT_RTP); EXPECT_TRUE(data_channel != nullptr); cm_->DestroyVideoChannel(video_channel); cm_->DestroyVoiceChannel(voice_channel); @@ -125,16 +126,17 @@ TEST_F(ChannelManagerTest, CreateDestroyChannelsOnThread) { delete transport_controller_; transport_controller_ = new cricket::FakeTransportController(&network_, ICEROLE_CONTROLLING); - cricket::VoiceChannel* voice_channel = - cm_->CreateVoiceChannel(&fake_mc_, transport_controller_, - cricket::CN_AUDIO, false, AudioOptions()); + cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel( + &fake_mc_, transport_controller_, cricket::CN_AUDIO, nullptr, false, + AudioOptions()); EXPECT_TRUE(voice_channel != nullptr); - cricket::VideoChannel* video_channel = - cm_->CreateVideoChannel(&fake_mc_, transport_controller_, - cricket::CN_VIDEO, false, VideoOptions()); + cricket::VideoChannel* video_channel = cm_->CreateVideoChannel( + &fake_mc_, transport_controller_, cricket::CN_VIDEO, nullptr, false, + VideoOptions()); EXPECT_TRUE(video_channel != nullptr); - cricket::DataChannel* data_channel = cm_->CreateDataChannel( - transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP); + cricket::DataChannel* data_channel = + cm_->CreateDataChannel(transport_controller_, cricket::CN_DATA, nullptr, + false, cricket::DCT_RTP); EXPECT_TRUE(data_channel != nullptr); cm_->DestroyVideoChannel(video_channel); cm_->DestroyVoiceChannel(voice_channel); @@ -152,16 +154,17 @@ TEST_F(ChannelManagerTest, NoTransportChannelTest) { ASSERT_TRUE(transport_controller_->CreateTransportChannel_n( "audio", cricket::ICE_CANDIDATE_COMPONENT_RTP) == nullptr); - cricket::VoiceChannel* voice_channel = - cm_->CreateVoiceChannel(&fake_mc_, transport_controller_, - cricket::CN_AUDIO, false, AudioOptions()); + cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel( + &fake_mc_, transport_controller_, cricket::CN_AUDIO, nullptr, false, + AudioOptions()); EXPECT_TRUE(voice_channel == nullptr); - cricket::VideoChannel* video_channel = - cm_->CreateVideoChannel(&fake_mc_, transport_controller_, - cricket::CN_VIDEO, false, VideoOptions()); + cricket::VideoChannel* video_channel = cm_->CreateVideoChannel( + &fake_mc_, transport_controller_, cricket::CN_VIDEO, nullptr, false, + VideoOptions()); EXPECT_TRUE(video_channel == nullptr); - cricket::DataChannel* data_channel = cm_->CreateDataChannel( - transport_controller_, cricket::CN_DATA, false, cricket::DCT_RTP); + cricket::DataChannel* data_channel = + cm_->CreateDataChannel(transport_controller_, cricket::CN_DATA, nullptr, + false, cricket::DCT_RTP); EXPECT_TRUE(data_channel == nullptr); cm_->Terminate(); }