Remove BaseChannel's dependency on TransportController.

The BaseChannel can set the transport directly without depending on
TransportController.

When initializing the network of the BaseChannel, the ChannelManager will
create TransportChannels with the TransportController.
When enabling bundling, WebRtcSession will get or create TransportChannels
with the TransportController.

When a TransportChannel of the BaseChannel needs to be destroyed, it will
fire a signal to notify the WebRtcSession.

BUG=none.

Review-Url: https://codereview.webrtc.org/2614263002
Cr-Original-Commit-Position: refs/heads/master@{#16043}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: f5b251b816ca9ad7579321a4d94535c623618dbb
diff --git a/api/rtcstatscollector_unittest.cc b/api/rtcstatscollector_unittest.cc
index 72d00c4..4d17003 100644
--- a/api/rtcstatscollector_unittest.cc
+++ b/api/rtcstatscollector_unittest.cc
@@ -596,14 +596,15 @@
 TEST_F(RTCStatsCollectorTest, CollectRTCCodecStats) {
   MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
   cricket::VoiceChannel voice_channel(
-      test_->worker_thread(), test_->network_thread(), test_->media_engine(),
-      voice_media_channel, nullptr, "VoiceContentName", kDefaultRtcpEnabled,
-      kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      test_->media_engine(), voice_media_channel, "VoiceContentName",
+      kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      test_->worker_thread(), test_->network_thread(), video_media_channel,
-      nullptr, "VideoContentName", kDefaultRtcpEnabled, kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      video_media_channel, "VideoContentName", kDefaultRtcpEnabled,
+      kDefaultSrtpRequired);
 
   // Audio
   cricket::VoiceMediaInfo voice_media_info;
@@ -1443,9 +1444,9 @@
 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Audio) {
   MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
   cricket::VoiceChannel voice_channel(
-      test_->worker_thread(), test_->network_thread(), test_->media_engine(),
-      voice_media_channel, nullptr, "VoiceContentName", kDefaultRtcpEnabled,
-      kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      test_->media_engine(), voice_media_channel, "VoiceContentName",
+      kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   cricket::VoiceMediaInfo voice_media_info;
 
@@ -1516,8 +1517,9 @@
 TEST_F(RTCStatsCollectorTest, CollectRTCInboundRTPStreamStats_Video) {
   MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      test_->worker_thread(), test_->network_thread(), video_media_channel,
-      nullptr, "VideoContentName", kDefaultRtcpEnabled, kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      video_media_channel, "VideoContentName", kDefaultRtcpEnabled,
+      kDefaultSrtpRequired);
 
   cricket::VideoMediaInfo video_media_info;
 
@@ -1594,9 +1596,9 @@
 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Audio) {
   MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
   cricket::VoiceChannel voice_channel(
-      test_->worker_thread(), test_->network_thread(), test_->media_engine(),
-      voice_media_channel, nullptr, "VoiceContentName", kDefaultRtcpEnabled,
-      kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      test_->media_engine(), voice_media_channel, "VoiceContentName",
+      kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   cricket::VoiceMediaInfo voice_media_info;
 
@@ -1662,8 +1664,9 @@
 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Video) {
   MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      test_->worker_thread(), test_->network_thread(), video_media_channel,
-      nullptr, "VideoContentName", kDefaultRtcpEnabled, kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      video_media_channel, "VideoContentName", kDefaultRtcpEnabled,
+      kDefaultSrtpRequired);
 
   cricket::VideoMediaInfo video_media_info;
 
@@ -1739,13 +1742,14 @@
 TEST_F(RTCStatsCollectorTest, CollectRTCOutboundRTPStreamStats_Default) {
   MockVoiceMediaChannel* voice_media_channel = new MockVoiceMediaChannel();
   cricket::VoiceChannel voice_channel(
-      test_->worker_thread(), test_->network_thread(), test_->media_engine(),
-      voice_media_channel, nullptr, "VoiceContentName", kDefaultRtcpEnabled,
-      kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      test_->media_engine(), voice_media_channel, "VoiceContentName",
+      kDefaultRtcpEnabled, kDefaultSrtpRequired);
   MockVideoMediaChannel* video_media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      test_->worker_thread(), test_->network_thread(), video_media_channel,
-      nullptr, "VideoContentName", kDefaultRtcpEnabled, kDefaultSrtpRequired);
+      test_->worker_thread(), test_->network_thread(), nullptr,
+      video_media_channel, "VideoContentName", kDefaultRtcpEnabled,
+      kDefaultSrtpRequired);
 
   cricket::VoiceMediaInfo voice_media_info;
   voice_media_info.senders.push_back(cricket::VoiceSenderInfo());
diff --git a/api/rtpsenderreceiver_unittest.cc b/api/rtpsenderreceiver_unittest.cc
index a79b297..b6c5184 100644
--- a/api/rtpsenderreceiver_unittest.cc
+++ b/api/rtpsenderreceiver_unittest.cc
@@ -64,12 +64,17 @@
     channel_manager_.Init();
     bool rtcp_enabled = false;
     bool srtp_required = true;
+    cricket::TransportChannel* rtp_transport =
+        fake_transport_controller_.CreateTransportChannel(
+            cricket::CN_AUDIO, cricket::ICE_CANDIDATE_COMPONENT_RTP);
     voice_channel_ = channel_manager_.CreateVoiceChannel(
-        &fake_media_controller_, &fake_transport_controller_, cricket::CN_AUDIO,
-        nullptr, rtcp_enabled, srtp_required, cricket::AudioOptions());
+        &fake_media_controller_, rtp_transport, nullptr, rtc::Thread::Current(),
+        cricket::CN_AUDIO, nullptr, rtcp_enabled, srtp_required,
+        cricket::AudioOptions());
     video_channel_ = channel_manager_.CreateVideoChannel(
-        &fake_media_controller_, &fake_transport_controller_, cricket::CN_VIDEO,
-        nullptr, rtcp_enabled, srtp_required, cricket::VideoOptions());
+        &fake_media_controller_, rtp_transport, nullptr, rtc::Thread::Current(),
+        cricket::CN_VIDEO, nullptr, rtcp_enabled, srtp_required,
+        cricket::VideoOptions());
     voice_media_channel_ = media_engine_->GetVoiceChannel(0);
     video_media_channel_ = media_engine_->GetVideoChannel(0);
     RTC_CHECK(voice_channel_);
diff --git a/api/statscollector_unittest.cc b/api/statscollector_unittest.cc
index 50ae51d..5cabaaf 100644
--- a/api/statscollector_unittest.cc
+++ b/api/statscollector_unittest.cc
@@ -866,7 +866,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_channel,
       kVideoChannelName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   StatsReports reports;  // returned values.
   cricket::VideoSenderInfo video_sender_info;
@@ -915,7 +915,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_channel,
       kVideoChannelName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   StatsReports reports;  // returned values.
@@ -991,7 +991,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr, "video",
+      worker_thread_, network_thread_, nullptr, media_channel, "video",
       kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingVideoTrackStats();
   stats.AddStream(stream_);
@@ -1030,7 +1030,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_channel,
       kVideoChannelName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingVideoTrackStats();
   stats.AddStream(stream_);
@@ -1099,7 +1099,7 @@
   // The transport_name known by the video channel.
   const std::string kVcName("vcname");
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr, kVcName,
+      worker_thread_, network_thread_, nullptr, media_channel, kVcName,
       kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingVideoTrackStats();
   stats.AddStream(stream_);
@@ -1160,7 +1160,7 @@
   // The transport_name known by the video channel.
   const std::string kVcName("vcname");
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr, kVcName,
+      worker_thread_, network_thread_, nullptr, media_channel, kVcName,
       kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingVideoTrackStats();
   stats.AddStream(stream_);
@@ -1187,7 +1187,7 @@
   // The transport_name known by the video channel.
   const std::string kVcName("vcname");
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr, kVcName,
+      worker_thread_, network_thread_, nullptr, media_channel, kVcName,
       kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingVideoTrackStats();
   stats.AddStream(stream_);
@@ -1247,7 +1247,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_channel,
       kVideoChannelName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddIncomingVideoTrackStats();
   stats.AddStream(stream_);
@@ -1560,7 +1560,7 @@
   // The transport_name known by the voice channel.
   const std::string kVcName("vcname");
   cricket::VoiceChannel voice_channel(
-      worker_thread_, network_thread_, media_engine_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_engine_, media_channel,
       kVcName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   // Create a local stream with a local audio track and adds it to the stats.
@@ -1670,7 +1670,7 @@
   // The transport_name known by the voice channel.
   const std::string kVcName("vcname");
   cricket::VoiceChannel voice_channel(
-      worker_thread_, network_thread_, media_engine_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_engine_, media_channel,
       kVcName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingAudioTrackStats();
   stats.AddStream(stream_);
@@ -1706,7 +1706,7 @@
   // The transport_name known by the voice channel.
   const std::string kVcName("vcname");
   cricket::VoiceChannel voice_channel(
-      worker_thread_, network_thread_, media_engine_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_engine_, media_channel,
       kVcName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddIncomingAudioTrackStats();
   stats.AddStream(stream_);
@@ -1736,7 +1736,7 @@
   // The transport_name known by the voice channel.
   const std::string kVcName("vcname");
   cricket::VoiceChannel voice_channel(
-      worker_thread_, network_thread_, media_engine_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_engine_, media_channel,
       kVcName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   AddOutgoingAudioTrackStats();
   stats.AddStream(stream_);
@@ -1800,7 +1800,7 @@
   // The transport_name known by the voice channel.
   const std::string kVcName("vcname");
   cricket::VoiceChannel voice_channel(
-      worker_thread_, network_thread_, media_engine_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_engine_, media_channel,
       kVcName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   // Create a local stream with a local audio track and adds it to the stats.
@@ -1890,7 +1890,7 @@
   // The transport_name known by the voice channel.
   const std::string kVcName("vcname");
   cricket::VoiceChannel voice_channel(
-      worker_thread_, network_thread_, media_engine_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_engine_, media_channel,
       kVcName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
 
   // Create a local stream with a local audio track and adds it to the stats.
@@ -1950,7 +1950,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_channel,
       kVideoChannelName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   StatsReports reports;  // returned values.
   cricket::VideoSenderInfo video_sender_info;
@@ -1998,7 +1998,7 @@
 
   MockVideoMediaChannel* media_channel = new MockVideoMediaChannel();
   cricket::VideoChannel video_channel(
-      worker_thread_, network_thread_, media_channel, nullptr,
+      worker_thread_, network_thread_, nullptr, media_channel,
       kVideoChannelName, kDefaultRtcpEnabled, kDefaultSrtpRequired);
   StatsReports reports;  // returned values.
   cricket::VideoReceiverInfo video_receiver_info;
diff --git a/api/webrtcsession.cc b/api/webrtcsession.cc
index 94ebc07..aa172ce 100644
--- a/api/webrtcsession.cc
+++ b/api/webrtcsession.cc
@@ -506,16 +506,13 @@
   // Destroy video_channel_ first since it may have a pointer to the
   // voice_channel_.
   if (video_channel_) {
-    SignalVideoChannelDestroyed();
-    channel_manager_->DestroyVideoChannel(video_channel_.release());
+    DestroyVideoChannel();
   }
   if (voice_channel_) {
-    SignalVoiceChannelDestroyed();
-    channel_manager_->DestroyVoiceChannel(voice_channel_.release());
+    DestroyVoiceChannel();
   }
   if (rtp_data_channel_) {
-    SignalDataChannelDestroyed();
-    channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
+    DestroyDataChannel();
   }
   if (sctp_transport_) {
     SignalDataChannelDestroyed();
@@ -736,14 +733,12 @@
   if (!UpdateSessionState(action, cricket::CS_LOCAL, err_desc)) {
     return false;
   }
-
   if (remote_description()) {
     // Now that we have a local description, we can push down remote candidates.
     UseCandidatesInSessionDescription(remote_description());
   }
 
   pending_ice_restarts_.clear();
-
   if (error() != ERROR_NONE) {
     return BadLocalSdp(desc->type(), GetSessionErrorMsg(), err_desc);
   }
@@ -1074,25 +1069,42 @@
                   << " on " << transport_name << "with QUIC.";
   }
 #endif
-
   auto maybe_set_transport = [this, bundle,
                               transport_name](cricket::BaseChannel* ch) {
     if (!ch || !bundle.HasContentName(ch->content_name())) {
       return true;
     }
 
-    if (ch->transport_name() == transport_name) {
+    std::string old_transport_name = ch->transport_name();
+    if (old_transport_name == transport_name) {
       LOG(LS_INFO) << "BUNDLE already enabled for " << ch->content_name()
                    << " on " << transport_name << ".";
       return true;
     }
 
-    if (!ch->SetTransport(transport_name)) {
+    cricket::TransportChannel* rtp_transport =
+        transport_controller_->CreateTransportChannel(
+            transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+    bool need_rtcp = (ch->rtcp_transport() != nullptr);
+    cricket::TransportChannel* rtcp_transport = nullptr;
+    if (need_rtcp) {
+      rtcp_transport = transport_controller_->CreateTransportChannel_n(
+          transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+    }
+
+    if (!ch->SetTransport(rtp_transport, rtcp_transport)) {
       LOG(LS_WARNING) << "Failed to enable BUNDLE for " << ch->content_name();
       return false;
     }
     LOG(LS_INFO) << "Enabled BUNDLE for " << ch->content_name() << " on "
                  << transport_name << ".";
+    DestroyTransport(old_transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+    // If the channel needs rtcp, it means that the channel used to have a
+    // rtcp transport which needs to be deleted now.
+    if (need_rtcp) {
+      DestroyTransport(old_transport_name,
+                       cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+    }
     return true;
   };
 
@@ -1680,23 +1692,20 @@
   const cricket::ContentInfo* video_info =
       cricket::GetFirstVideoContent(desc);
   if ((!video_info || video_info->rejected) && video_channel_) {
-    SignalVideoChannelDestroyed();
-    channel_manager_->DestroyVideoChannel(video_channel_.release());
+    DestroyVideoChannel();
   }
 
   const cricket::ContentInfo* voice_info =
       cricket::GetFirstAudioContent(desc);
   if ((!voice_info || voice_info->rejected) && voice_channel_) {
-    SignalVoiceChannelDestroyed();
-    channel_manager_->DestroyVoiceChannel(voice_channel_.release());
+    DestroyVoiceChannel();
   }
 
   const cricket::ContentInfo* data_info =
       cricket::GetFirstDataContent(desc);
   if (!data_info || data_info->rejected) {
     if (rtp_data_channel_) {
-      SignalDataChannelDestroyed();
-      channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
+      DestroyDataChannel();
     }
     if (sctp_transport_) {
       SignalDataChannelDestroyed();
@@ -1779,13 +1788,30 @@
   bool require_rtcp_mux =
       rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
   bool create_rtcp_transport_channel = !require_rtcp_mux;
+
+  std::string transport_name =
+      bundle_transport ? *bundle_transport : content->name;
+
+  cricket::TransportChannel* rtp_transport =
+      transport_controller_->CreateTransportChannel(
+          transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  cricket::TransportChannel* rtcp_transport = nullptr;
+  if (create_rtcp_transport_channel) {
+    rtcp_transport = transport_controller_->CreateTransportChannel(
+        transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+
   voice_channel_.reset(channel_manager_->CreateVoiceChannel(
-      media_controller_, transport_controller_.get(), content->name,
+      media_controller_, rtp_transport, rtcp_transport,
+      transport_controller_->signaling_thread(), content->name,
       bundle_transport, create_rtcp_transport_channel, SrtpRequired(),
       audio_options_));
   if (!voice_channel_) {
     return false;
   }
+
+  voice_channel_->SignalDestroyRtcpTransport.connect(
+      this, &WebRtcSession::OnDestroyRtcpTransport_n);
   if (require_rtcp_mux) {
     voice_channel_->ActivateRtcpMux();
   }
@@ -1804,13 +1830,31 @@
   bool require_rtcp_mux =
       rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
   bool create_rtcp_transport_channel = !require_rtcp_mux;
+
+  std::string transport_name =
+      bundle_transport ? *bundle_transport : content->name;
+
+  cricket::TransportChannel* rtp_transport =
+      transport_controller_->CreateTransportChannel(
+          transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  cricket::TransportChannel* rtcp_transport = nullptr;
+  if (create_rtcp_transport_channel) {
+    rtcp_transport = transport_controller_->CreateTransportChannel(
+        transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+
   video_channel_.reset(channel_manager_->CreateVideoChannel(
-      media_controller_, transport_controller_.get(), content->name,
+      media_controller_, rtp_transport, rtcp_transport,
+      transport_controller_->signaling_thread(), content->name,
       bundle_transport, create_rtcp_transport_channel, SrtpRequired(),
       video_options_));
+
   if (!video_channel_) {
     return false;
   }
+
+  video_channel_->SignalDestroyRtcpTransport.connect(
+      this, &WebRtcSession::OnDestroyRtcpTransport_n);
   if (require_rtcp_mux) {
     video_channel_->ActivateRtcpMux();
   }
@@ -1851,12 +1895,30 @@
     bool require_rtcp_mux =
         rtcp_mux_policy_ == PeerConnectionInterface::kRtcpMuxPolicyRequire;
     bool create_rtcp_transport_channel = !sctp && !require_rtcp_mux;
+
+    std::string transport_name =
+        bundle_transport ? *bundle_transport : content->name;
+    cricket::TransportChannel* rtp_transport =
+        transport_controller_->CreateTransportChannel(
+            transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+    cricket::TransportChannel* rtcp_transport = nullptr;
+    if (create_rtcp_transport_channel) {
+      rtcp_transport = transport_controller_->CreateTransportChannel(
+          transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+    }
+
     rtp_data_channel_.reset(channel_manager_->CreateRtpDataChannel(
-        media_controller_, transport_controller_.get(), content->name,
+        media_controller_, rtp_transport, rtcp_transport,
+        transport_controller_->signaling_thread(), content->name,
         bundle_transport, create_rtcp_transport_channel, SrtpRequired()));
+
     if (!rtp_data_channel_) {
       return false;
     }
+
+    rtp_data_channel_->SignalDestroyRtcpTransport.connect(
+        this, &WebRtcSession::OnDestroyRtcpTransport_n);
+
     if (require_rtcp_mux) {
       rtp_data_channel_->ActivateRtcpMux();
     }
@@ -1867,6 +1929,7 @@
   }
 
   SignalDataChannelCreated();
+
   return true;
 }
 
@@ -2318,4 +2381,57 @@
   return channel->transport_name();
 }
 
+void WebRtcSession::DestroyTransport(const std::string& transport_name,
+                                     int component) {
+  network_thread_->Invoke<void>(
+      RTC_FROM_HERE,
+      rtc::Bind(&cricket::TransportController::DestroyTransportChannel_n,
+                transport_controller_.get(), transport_name, component));
+}
+
+void WebRtcSession::OnDestroyRtcpTransport_n(
+    const std::string& transport_name) {
+  ASSERT(network_thread()->IsCurrent());
+  transport_controller_->DestroyTransportChannel_n(
+      transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+}
+
+void WebRtcSession::DestroyVideoChannel() {
+  SignalVideoChannelDestroyed();
+  RTC_DCHECK(video_channel_->rtp_transport());
+  std::string transport_name;
+  transport_name = video_channel_->rtp_transport()->transport_name();
+  bool need_to_delete_rtcp = (video_channel_->rtcp_transport() != nullptr);
+  channel_manager_->DestroyVideoChannel(video_channel_.release());
+  DestroyTransport(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  if (need_to_delete_rtcp) {
+    DestroyTransport(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+}
+
+void WebRtcSession::DestroyVoiceChannel() {
+  SignalVoiceChannelDestroyed();
+  RTC_DCHECK(voice_channel_->rtp_transport());
+  std::string transport_name;
+  transport_name = voice_channel_->rtp_transport()->transport_name();
+  bool need_to_delete_rtcp = (voice_channel_->rtcp_transport() != nullptr);
+  channel_manager_->DestroyVoiceChannel(voice_channel_.release());
+  DestroyTransport(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  if (need_to_delete_rtcp) {
+    DestroyTransport(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+}
+
+void WebRtcSession::DestroyDataChannel() {
+  SignalDataChannelDestroyed();
+  RTC_DCHECK(rtp_data_channel_->rtp_transport());
+  std::string transport_name;
+  transport_name = rtp_data_channel_->rtp_transport()->transport_name();
+  bool need_to_delete_rtcp = (rtp_data_channel_->rtcp_transport() != nullptr);
+  channel_manager_->DestroyRtpDataChannel(rtp_data_channel_.release());
+  DestroyTransport(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  if (need_to_delete_rtcp) {
+    DestroyTransport(transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+}
 }  // namespace webrtc
diff --git a/api/webrtcsession.h b/api/webrtcsession.h
index e346112..42e0e4b 100644
--- a/api/webrtcsession.h
+++ b/api/webrtcsession.h
@@ -553,6 +553,12 @@
 
   const std::string GetTransportName(const std::string& content_name);
 
+  void DestroyTransport(const std::string& transport_name, int component);
+  void OnDestroyRtcpTransport_n(const std::string& transport_name);
+  void DestroyVideoChannel();
+  void DestroyVoiceChannel();
+  void DestroyDataChannel();
+
   rtc::Thread* const network_thread_;
   rtc::Thread* const worker_thread_;
   rtc::Thread* const signaling_thread_;
diff --git a/api/webrtcsession_unittest.cc b/api/webrtcsession_unittest.cc
index f739c16..3e1a583 100644
--- a/api/webrtcsession_unittest.cc
+++ b/api/webrtcsession_unittest.cc
@@ -306,7 +306,7 @@
     if (!ch) {
       return nullptr;
     }
-    return ch->transport_channel();
+    return ch->rtp_transport();
   }
 
   rtc::PacketTransportInterface* rtcp_transport_channel(
@@ -314,7 +314,7 @@
     if (!ch) {
       return nullptr;
     }
-    return ch->rtcp_transport_channel();
+    return ch->rtcp_transport();
   }
 };
 
diff --git a/p2p/base/faketransportcontroller.h b/p2p/base/faketransportcontroller.h
index 28eb86c..a73d464 100644
--- a/p2p/base/faketransportcontroller.h
+++ b/p2p/base/faketransportcontroller.h
@@ -665,6 +665,11 @@
     return new FakeCandidatePair(local_candidate, remote_candidate);
   }
 
+  void DestroyRtcpTransport(const std::string& transport_name) {
+    DestroyTransportChannel_n(transport_name,
+                              cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+
  protected:
   // The ICE channel is never actually used by TransportController directly,
   // since (currently) the DTLS channel pretends to be both ICE + DTLS. This
diff --git a/p2p/base/transportcontroller.cc b/p2p/base/transportcontroller.cc
index 2781b0b..810b96e 100644
--- a/p2p/base/transportcontroller.cc
+++ b/p2p/base/transportcontroller.cc
@@ -227,6 +227,14 @@
                                metrics_observer));
 }
 
+TransportChannel* TransportController::CreateTransportChannel(
+    const std::string& transport_name,
+    int component) {
+  return network_thread_->Invoke<TransportChannel*>(
+      RTC_FROM_HERE, rtc::Bind(&TransportController::CreateTransportChannel_n,
+                               this, transport_name, component));
+}
+
 TransportChannel* TransportController::CreateTransportChannel_n(
     const std::string& transport_name,
     int component) {
@@ -292,7 +300,6 @@
     const std::string& transport_name,
     int component) {
   RTC_DCHECK(network_thread_->IsCurrent());
-
   auto it = GetChannelIterator_n(transport_name, component);
   if (it == channels_.end()) {
     LOG(LS_WARNING) << "Attempting to delete " << transport_name
@@ -313,7 +320,6 @@
   if (!t->HasChannels()) {
     transports_.erase(transport_name);
   }
-
   // Removing a channel could cause aggregate state to change.
   UpdateAggregateStates_n();
 }
diff --git a/p2p/base/transportcontroller.h b/p2p/base/transportcontroller.h
index 7929cf0..147d568 100644
--- a/p2p/base/transportcontroller.h
+++ b/p2p/base/transportcontroller.h
@@ -113,6 +113,8 @@
 
   // Creates a channel if it doesn't exist. Otherwise, increments a reference
   // count and returns an existing channel.
+  TransportChannel* CreateTransportChannel(const std::string& transport_name,
+                                           int component);
   virtual TransportChannel* CreateTransportChannel_n(
       const std::string& transport_name,
       int component);
diff --git a/pc/channel.cc b/pc/channel.cc
index 45141c8..182d4ca 100644
--- a/pc/channel.cc
+++ b/pc/channel.cc
@@ -160,25 +160,20 @@
 
 BaseChannel::BaseChannel(rtc::Thread* worker_thread,
                          rtc::Thread* network_thread,
+                         rtc::Thread* signaling_thread,
                          MediaChannel* media_channel,
-                         TransportController* transport_controller,
                          const std::string& content_name,
                          bool rtcp,
                          bool srtp_required)
     : worker_thread_(worker_thread),
       network_thread_(network_thread),
-
+      signaling_thread_(signaling_thread),
       content_name_(content_name),
-
-      transport_controller_(transport_controller),
       rtcp_enabled_(rtcp),
       srtp_required_(srtp_required),
       media_channel_(media_channel),
       selected_candidate_pair_(nullptr) {
   RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
-  if (transport_controller) {
-    RTC_DCHECK_EQ(network_thread, transport_controller->network_thread());
-  }
   LOG(LS_INFO) << "Created channel for " << content_name;
 }
 
@@ -194,11 +189,7 @@
   // the media channel may try to send on the dead transport channel. NULLing
   // is not an effective strategy since the sends will come on another thread.
   delete media_channel_;
-  // Note that we don't just call SetTransportChannel_n(nullptr) because that
-  // would call a pure virtual method which we can't do from a destructor.
-  network_thread_->Invoke<void>(
-      RTC_FROM_HERE, Bind(&BaseChannel::DestroyTransportChannels_n, this));
-  LOG(LS_INFO) << "Destroyed channel";
+  LOG(LS_INFO) << "Destroyed channel: " << content_name_;
 }
 
 void BaseChannel::DisconnectTransportChannels_n() {
@@ -207,11 +198,11 @@
 
   // Stop signals from transport channels, but keep them alive because
   // media_channel may use them from a different thread.
-  if (transport_channel_) {
-    DisconnectFromTransportChannel(transport_channel_);
+  if (rtp_transport_) {
+    DisconnectFromTransportChannel(rtp_transport_);
   }
-  if (rtcp_transport_channel_) {
-    DisconnectFromTransportChannel(rtcp_transport_channel_);
+  if (rtcp_transport_) {
+    DisconnectFromTransportChannel(rtcp_transport_);
   }
 
   // Clear pending read packets/messages.
@@ -219,24 +210,11 @@
   network_thread_->Clear(this);
 }
 
-void BaseChannel::DestroyTransportChannels_n() {
-  if (transport_channel_) {
-    transport_controller_->DestroyTransportChannel_n(
-        transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTP);
-  }
-  if (rtcp_transport_channel_) {
-    transport_controller_->DestroyTransportChannel_n(
-        transport_name_, cricket::ICE_CANDIDATE_COMPONENT_RTCP);
-  }
-  // Clear pending send packets/messages.
-  network_thread_->Clear(&invoker_);
-  network_thread_->Clear(this);
-}
-
-bool BaseChannel::Init_w(const std::string* bundle_transport_name) {
+bool BaseChannel::Init_w(TransportChannel* rtp_transport,
+                         TransportChannel* rtcp_transport) {
   if (!network_thread_->Invoke<bool>(
-          RTC_FROM_HERE,
-          Bind(&BaseChannel::InitNetwork_n, this, bundle_transport_name))) {
+          RTC_FROM_HERE, Bind(&BaseChannel::InitNetwork_n, this, rtp_transport,
+                              rtcp_transport))) {
     return false;
   }
 
@@ -247,19 +225,19 @@
   return true;
 }
 
-bool BaseChannel::InitNetwork_n(const std::string* bundle_transport_name) {
+bool BaseChannel::InitNetwork_n(TransportChannel* rtp_transport,
+                                TransportChannel* rtcp_transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
-  const std::string& transport_name =
-      (bundle_transport_name ? *bundle_transport_name : content_name());
-  if (!SetTransport_n(transport_name)) {
+  //  const std::string& transport_name =
+  //      (bundle_transport_name ? *bundle_transport_name : content_name());
+  if (!SetTransport_n(rtp_transport, rtcp_transport)) {
     return false;
   }
 
-  if (!SetDtlsSrtpCryptoSuites_n(transport_channel_, false)) {
+  if (!SetDtlsSrtpCryptoSuites_n(rtp_transport_, false)) {
     return false;
   }
-  if (rtcp_transport_channel_ &&
-      !SetDtlsSrtpCryptoSuites_n(rtcp_transport_channel_, true)) {
+  if (rtcp_transport_ && !SetDtlsSrtpCryptoSuites_n(rtcp_transport_, true)) {
     return false;
   }
   return true;
@@ -275,19 +253,34 @@
       RTC_FROM_HERE, Bind(&BaseChannel::DisconnectTransportChannels_n, this));
 }
 
-bool BaseChannel::SetTransport(const std::string& transport_name) {
+bool BaseChannel::SetTransport(TransportChannel* rtp_transport,
+                               TransportChannel* rtcp_transport) {
   return network_thread_->Invoke<bool>(
-      RTC_FROM_HERE, Bind(&BaseChannel::SetTransport_n, this, transport_name));
+      RTC_FROM_HERE,
+      Bind(&BaseChannel::SetTransport_n, this, rtp_transport, rtcp_transport));
 }
 
-bool BaseChannel::SetTransport_n(const std::string& transport_name) {
+bool BaseChannel::SetTransport_n(TransportChannel* rtp_transport,
+                                 TransportChannel* rtcp_transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
+  if (!rtp_transport && !rtcp_transport) {
+    LOG(LS_ERROR) << "Setting nullptr to RTP Transport and RTCP Transport.";
+    return false;
+  }
 
-  if (transport_name == transport_name_) {
+  if (rtcp_transport) {
+    RTC_DCHECK(rtp_transport->transport_name() ==
+               rtcp_transport->transport_name());
+    RTC_DCHECK(NeedsRtcpTransport());
+  }
+
+  if (rtp_transport->transport_name() == transport_name_) {
     // Nothing to do if transport name isn't changing.
     return true;
   }
 
+  transport_name_ = rtp_transport->transport_name();
+
   // When using DTLS-SRTP, we must reset the SrtpFilter every time the transport
   // changes and wait until the DTLS handshake is complete to set the newly
   // negotiated parameters.
@@ -300,28 +293,22 @@
 
   // If this BaseChannel uses RTCP and we haven't fully negotiated RTCP mux,
   // we need an RTCP channel.
-  if (rtcp_enabled_ && !rtcp_mux_filter_.IsFullyActive()) {
-    LOG(LS_INFO) << "Create RTCP TransportChannel for " << content_name()
-                 << " on " << transport_name << " transport ";
-    SetTransportChannel_n(
-        true, transport_controller_->CreateTransportChannel_n(
-                  transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTCP));
-    if (!rtcp_transport_channel_) {
+  if (NeedsRtcpTransport()) {
+    LOG(LS_INFO) << "Setting RTCP Transport for " << content_name() << " on "
+                 << transport_name() << " transport " << rtcp_transport;
+    SetTransportChannel_n(true, rtcp_transport);
+    if (!rtcp_transport_) {
       return false;
     }
   }
 
-  LOG(LS_INFO) << "Create non-RTCP TransportChannel for " << content_name()
-               << " on " << transport_name << " transport ";
-  SetTransportChannel_n(
-      false, transport_controller_->CreateTransportChannel_n(
-                 transport_name, cricket::ICE_CANDIDATE_COMPONENT_RTP));
-  if (!transport_channel_) {
+  LOG(LS_INFO) << "Setting non-RTCP Transport for " << content_name() << " on "
+               << transport_name() << " transport " << rtp_transport;
+  SetTransportChannel_n(false, rtp_transport);
+  if (!rtp_transport_) {
     return false;
   }
 
-  transport_name_ = transport_name;
-
   // Update aggregate writable/ready-to-send state between RTP and RTCP upon
   // setting new transport channels.
   UpdateWritableState_n();
@@ -334,44 +321,38 @@
   // This won't always be accurate (the last SendPacket call from another
   // BaseChannel could have resulted in an error), but even so, we'll just
   // encounter the error again and update "ready to send" accordingly.
+  SetTransportChannelReadyToSend(false,
+                                 rtp_transport_ && rtp_transport_->writable());
   SetTransportChannelReadyToSend(
-      false, transport_channel_ && transport_channel_->writable());
-  SetTransportChannelReadyToSend(
-      true, rtcp_transport_channel_ && rtcp_transport_channel_->writable());
+      true, rtcp_transport_ && rtcp_transport_->writable());
   return true;
 }
 
 void BaseChannel::SetTransportChannel_n(bool rtcp,
-                                        TransportChannel* new_channel) {
+                                        TransportChannel* new_transport) {
   RTC_DCHECK(network_thread_->IsCurrent());
-  TransportChannel*& old_channel =
-      rtcp ? rtcp_transport_channel_ : transport_channel_;
-
-  if (!old_channel && !new_channel) {
+  TransportChannel*& old_transport = rtcp ? rtcp_transport_ : rtp_transport_;
+  if (!old_transport && !new_transport) {
     // Nothing to do.
     return;
   }
-  RTC_DCHECK(old_channel != new_channel);
-
-  if (old_channel) {
-    DisconnectFromTransportChannel(old_channel);
-    transport_controller_->DestroyTransportChannel_n(
-        transport_name_, rtcp ? cricket::ICE_CANDIDATE_COMPONENT_RTCP
-                              : cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  RTC_DCHECK(old_transport != new_transport);
+  if (old_transport) {
+    DisconnectFromTransportChannel(old_transport);
   }
 
-  old_channel = new_channel;
+  old_transport = new_transport;
 
-  if (new_channel) {
+  if (new_transport) {
     if (rtcp) {
       RTC_CHECK(!(ShouldSetupDtlsSrtp_n() && srtp_filter_.IsActive()))
           << "Setting RTCP for DTLS/SRTP after SrtpFilter is active "
           << "should never happen.";
     }
-    ConnectToTransportChannel(new_channel);
+    ConnectToTransportChannel(new_transport);
     auto& socket_options = rtcp ? rtcp_socket_options_ : socket_options_;
     for (const auto& pair : socket_options) {
-      new_channel->SetOption(pair.first, pair.second);
+      new_transport->SetOption(pair.first, pair.second);
     }
   }
 }
@@ -445,8 +426,8 @@
 }
 
 void BaseChannel::StartConnectionMonitor(int cms) {
-  // We pass in the BaseChannel instead of the transport_channel_
-  // because if the transport_channel_ changes, the ConnectionMonitor
+  // We pass in the BaseChannel instead of the rtp_transport_
+  // because if the rtp_transport_ changes, the ConnectionMonitor
   // would be pointing to the wrong TransportChannel.
   // We pass in the network thread because on that thread connection monitor
   // will call BaseChannel::GetConnectionStats which must be called on the
@@ -467,7 +448,11 @@
 
 bool BaseChannel::GetConnectionStats(ConnectionInfos* infos) {
   RTC_DCHECK(network_thread_->IsCurrent());
-  return transport_channel_->GetStats(infos);
+  return rtp_transport_->GetStats(infos);
+}
+
+bool BaseChannel::NeedsRtcpTransport() {
+  return rtcp_enabled_ && !rtcp_mux_filter_.IsFullyActive();
 }
 
 bool BaseChannel::IsReadyToReceiveMedia_w() const {
@@ -513,12 +498,12 @@
   TransportChannel* channel = nullptr;
   switch (type) {
     case ST_RTP:
-      channel = transport_channel_;
+      channel = rtp_transport_;
       socket_options_.push_back(
           std::pair<rtc::Socket::Option, int>(opt, value));
       break;
     case ST_RTCP:
-      channel = rtcp_transport_channel_;
+      channel = rtcp_transport_;
       rtcp_socket_options_.push_back(
           std::pair<rtc::Socket::Option, int>(opt, value));
       break;
@@ -532,8 +517,7 @@
 }
 
 void BaseChannel::OnWritableState(rtc::PacketTransportInterface* transport) {
-  RTC_DCHECK(transport == transport_channel_ ||
-             transport == rtcp_transport_channel_);
+  RTC_DCHECK(transport == rtp_transport_ || transport == rtcp_transport_);
   RTC_DCHECK(network_thread_->IsCurrent());
   UpdateWritableState_n();
 }
@@ -555,9 +539,8 @@
 }
 
 void BaseChannel::OnReadyToSend(rtc::PacketTransportInterface* transport) {
-  RTC_DCHECK(transport == transport_channel_ ||
-             transport == rtcp_transport_channel_);
-  SetTransportChannelReadyToSend(transport == rtcp_transport_channel_, true);
+  RTC_DCHECK(transport == rtp_transport_ || transport == rtcp_transport_);
+  SetTransportChannelReadyToSend(transport == rtcp_transport_, true);
 }
 
 void BaseChannel::OnDtlsState(TransportChannel* channel,
@@ -581,8 +564,7 @@
     CandidatePairInterface* selected_candidate_pair,
     int last_sent_packet_id,
     bool ready_to_send) {
-  RTC_DCHECK(channel == transport_channel_ ||
-             channel == rtcp_transport_channel_);
+  RTC_DCHECK(channel == rtp_transport_ || channel == rtcp_transport_);
   RTC_DCHECK(network_thread_->IsCurrent());
   selected_candidate_pair_ = selected_candidate_pair;
   std::string transport_name = channel->transport_name();
@@ -611,8 +593,8 @@
 
   bool ready_to_send =
       (rtp_ready_to_send_ &&
-       // In the case of rtcp mux |rtcp_transport_channel_| will be null.
-       (rtcp_ready_to_send_ || !rtcp_transport_channel_));
+       // In the case of rtcp mux |rtcp_transport_| will be null.
+       (rtcp_ready_to_send_ || !rtcp_transport_));
 
   invoker_.AsyncInvoke<void>(
       RTC_FROM_HERE, worker_thread_,
@@ -622,7 +604,7 @@
 bool BaseChannel::PacketIsRtcp(const rtc::PacketTransportInterface* transport,
                                const char* data,
                                size_t len) {
-  return (transport == rtcp_transport_channel_ ||
+  return (transport == rtcp_transport_ ||
           rtcp_mux_filter_.DemuxRtcp(data, static_cast<int>(len)));
 }
 
@@ -651,8 +633,8 @@
   // packet before doing anything. (We might get RTCP packets that we don't
   // intend to send.) If we've negotiated RTCP mux, send RTCP over the RTP
   // transport.
-  TransportChannel* channel = (!rtcp || rtcp_mux_filter_.IsActive()) ?
-      transport_channel_ : rtcp_transport_channel_;
+  TransportChannel* channel =
+      (!rtcp || rtcp_mux_filter_.IsActive()) ? rtp_transport_ : rtcp_transport_;
   if (!channel || !channel->writable()) {
     return false;
   }
@@ -900,8 +882,8 @@
 }
 
 void BaseChannel::UpdateWritableState_n() {
-  if (transport_channel_ && transport_channel_->writable() &&
-      (!rtcp_transport_channel_ || rtcp_transport_channel_->writable())) {
+  if (rtp_transport_ && rtp_transport_->writable() &&
+      (!rtcp_transport_ || rtcp_transport_->writable())) {
     ChannelWritable_n();
   } else {
     ChannelNotWritable_n();
@@ -956,7 +938,7 @@
 
 bool BaseChannel::ShouldSetupDtlsSrtp_n() const {
   // Since DTLS is applied to all channels, checking RTP should be enough.
-  return transport_channel_ && transport_channel_->IsDtlsActive();
+  return rtp_transport_ && rtp_transport_->IsDtlsActive();
 }
 
 // This function returns true if either DTLS-SRTP is not in use
@@ -965,8 +947,7 @@
   RTC_DCHECK(network_thread_->IsCurrent());
   bool ret = false;
 
-  TransportChannel* channel =
-      rtcp_channel ? rtcp_transport_channel_ : transport_channel_;
+  TransportChannel* channel = rtcp_channel ? rtcp_transport_ : rtp_transport_;
 
   RTC_DCHECK(channel->IsDtlsActive());
 
@@ -1064,7 +1045,7 @@
     return;
   }
 
-  if (rtcp_transport_channel_) {
+  if (rtcp_transport_) {
     if (!SetupDtlsSrtp_n(true)) {
       SignalDtlsSrtpSetupFailure_n(true);
       return;
@@ -1121,7 +1102,7 @@
 bool BaseChannel::CheckSrtpConfig_n(const std::vector<CryptoParams>& cryptos,
                                     bool* dtls,
                                     std::string* error_desc) {
-  *dtls = transport_channel_->IsDtlsActive();
+  *dtls = rtp_transport_->IsDtlsActive();
   if (*dtls && !cryptos.empty()) {
     SafeSetError("Cryptos must be empty when DTLS is active.", error_desc);
     return false;
@@ -1184,7 +1165,11 @@
 void BaseChannel::ActivateRtcpMux_n() {
   if (!rtcp_mux_filter_.IsActive()) {
     rtcp_mux_filter_.SetActive();
+    bool need_to_delete_rtcp = (rtcp_transport() != nullptr);
     SetTransportChannel_n(true, nullptr);
+    if (need_to_delete_rtcp) {
+      SignalDestroyRtcpTransport(rtp_transport()->transport_name());
+    }
     // Update aggregate writable/ready-to-send state between RTP and RTCP upon
     // removing channel.
     UpdateWritableState_n();
@@ -1213,7 +1198,11 @@
         LOG(LS_INFO) << "Enabling rtcp-mux for " << content_name()
                      << " by destroying RTCP transport channel for "
                      << transport_name();
+        bool need_to_delete_rtcp = (rtcp_transport() != nullptr);
         SetTransportChannel_n(true, nullptr);
+        if (need_to_delete_rtcp) {
+          SignalDestroyRtcpTransport(rtp_transport()->transport_name());
+        }
         UpdateWritableState_n();
         SetTransportChannelReadyToSend(true, false);
       }
@@ -1234,7 +1223,7 @@
   // received a final answer.
   if (rtcp_mux_filter_.IsActive()) {
     // If the RTP transport is already writable, then so are we.
-    if (transport_channel_->writable()) {
+    if (rtp_transport_->writable()) {
       ChannelWritable_n();
     }
   }
@@ -1469,16 +1458,16 @@
 
 VoiceChannel::VoiceChannel(rtc::Thread* worker_thread,
                            rtc::Thread* network_thread,
+                           rtc::Thread* signaling_thread,
                            MediaEngineInterface* media_engine,
                            VoiceMediaChannel* media_channel,
-                           TransportController* transport_controller,
                            const std::string& content_name,
                            bool rtcp,
                            bool srtp_required)
     : BaseChannel(worker_thread,
                   network_thread,
+                  signaling_thread,
                   media_channel,
-                  transport_controller,
                   content_name,
                   rtcp,
                   srtp_required),
@@ -1494,11 +1483,9 @@
   Deinit();
 }
 
-bool VoiceChannel::Init_w(const std::string* bundle_transport_name) {
-  if (!BaseChannel::Init_w(bundle_transport_name)) {
-    return false;
-  }
-  return true;
+bool VoiceChannel::Init_w(TransportChannel* rtp_transport,
+                          TransportChannel* rtcp_transport) {
+  return BaseChannel::Init_w(rtp_transport, rtcp_transport);
 }
 
 bool VoiceChannel::SetAudioSend(uint32_t ssrc,
@@ -1885,24 +1872,22 @@
 
 VideoChannel::VideoChannel(rtc::Thread* worker_thread,
                            rtc::Thread* network_thread,
+                           rtc::Thread* signaling_thread,
                            VideoMediaChannel* media_channel,
-                           TransportController* transport_controller,
                            const std::string& content_name,
                            bool rtcp,
                            bool srtp_required)
     : BaseChannel(worker_thread,
                   network_thread,
+                  signaling_thread,
                   media_channel,
-                  transport_controller,
                   content_name,
                   rtcp,
                   srtp_required) {}
 
-bool VideoChannel::Init_w(const std::string* bundle_transport_name) {
-  if (!BaseChannel::Init_w(bundle_transport_name)) {
-    return false;
-  }
-  return true;
+bool VideoChannel::Init_w(TransportChannel* rtp_transport,
+                          TransportChannel* rtcp_transport) {
+  return BaseChannel::Init_w(rtp_transport, rtcp_transport);
 }
 
 VideoChannel::~VideoChannel() {
@@ -2148,15 +2133,15 @@
 
 RtpDataChannel::RtpDataChannel(rtc::Thread* worker_thread,
                                rtc::Thread* network_thread,
+                               rtc::Thread* signaling_thread,
                                DataMediaChannel* media_channel,
-                               TransportController* transport_controller,
                                const std::string& content_name,
                                bool rtcp,
                                bool srtp_required)
     : BaseChannel(worker_thread,
                   network_thread,
+                  signaling_thread,
                   media_channel,
-                  transport_controller,
                   content_name,
                   rtcp,
                   srtp_required) {}
@@ -2170,8 +2155,9 @@
   Deinit();
 }
 
-bool RtpDataChannel::Init_w(const std::string* bundle_transport_name) {
-  if (!BaseChannel::Init_w(bundle_transport_name)) {
+bool RtpDataChannel::Init_w(TransportChannel* rtp_transport,
+                            TransportChannel* rtcp_transport) {
+  if (!BaseChannel::Init_w(rtp_transport, rtcp_transport)) {
     return false;
   }
   media_channel()->SignalDataReceived.connect(this,
diff --git a/pc/channel.h b/pc/channel.h
index ff98a2f..e5180ca 100644
--- a/pc/channel.h
+++ b/pc/channel.h
@@ -80,13 +80,14 @@
   // RTP/RTCP packets without using SRTP (either using SDES or DTLS-SRTP).
   BaseChannel(rtc::Thread* worker_thread,
               rtc::Thread* network_thread,
+              rtc::Thread* signaling_thread,
               MediaChannel* channel,
-              TransportController* transport_controller,
               const std::string& content_name,
               bool rtcp,
               bool srtp_required);
   virtual ~BaseChannel();
-  bool Init_w(const std::string* bundle_transport_name);
+  bool Init_w(TransportChannel* rtp_transport,
+              TransportChannel* rtcp_transport);
   // Deinit may be called multiple times and is simply ignored if it's already
   // done.
   void Deinit();
@@ -111,7 +112,8 @@
   // description doesn't support RTCP mux, setting the remote
   // description will fail.
   void ActivateRtcpMux();
-  bool SetTransport(const std::string& transport_name);
+  bool SetTransport(TransportChannel* rtp_transport,
+                    TransportChannel* rtcp_transport);
   bool PushdownLocalDescription(const SessionDescription* local_desc,
                                 ContentAction action,
                                 std::string* error_desc);
@@ -159,11 +161,14 @@
   // Forward TransportChannel SignalSentPacket to worker thread.
   sigslot::signal1<const rtc::SentPacket&> SignalSentPacket;
 
-  // Only public for unit tests.  Otherwise, consider private.
-  TransportChannel* transport_channel() const { return transport_channel_; }
-  TransportChannel* rtcp_transport_channel() const {
-    return rtcp_transport_channel_;
-  }
+  // Emitted whenever the rtcp-mux is active and the rtcp-transport can be
+  // destroyed.
+  sigslot::signal1<const std::string&> SignalDestroyRtcpTransport;
+
+  TransportChannel* rtp_transport() const { return rtp_transport_; }
+  TransportChannel* rtcp_transport() const { return rtcp_transport_; }
+
+  bool NeedsRtcpTransport();
 
   // Made public for easier testing.
   //
@@ -193,15 +198,15 @@
  protected:
   virtual MediaChannel* media_channel() const { return media_channel_; }
 
-  // Sets the |transport_channel_| (and |rtcp_transport_channel_|, if
-  // |rtcp_enabled_| is true). Gets the transport channels from
-  // |transport_controller_|.
+  // Sets the |rtp_transport_| (and |rtcp_transport_|, if
+  // |rtcp_enabled_| is true).
   // This method also updates writability and "ready-to-send" state.
-  bool SetTransport_n(const std::string& transport_name);
+  bool SetTransport_n(TransportChannel* rtp_transport,
+                      TransportChannel* rtcp_transport);
 
   // This does not update writability or "ready-to-send" state; it just
   // disconnects from the old channel and connects to the new one.
-  void SetTransportChannel_n(bool rtcp, TransportChannel* new_channel);
+  void SetTransportChannel_n(bool rtcp, TransportChannel* new_transport);
 
   bool was_ever_writable() const { return was_ever_writable_; }
   void set_local_content_direction(MediaContentDirection direction) {
@@ -222,9 +227,7 @@
   // called.
   bool IsReadyToReceiveMedia_w() const;
   bool IsReadyToSendMedia_w() const;
-  rtc::Thread* signaling_thread() {
-    return transport_controller_->signaling_thread();
-  }
+  rtc::Thread* signaling_thread() { return signaling_thread_; }
 
   void ConnectToTransportChannel(TransportChannel* tc);
   void DisconnectFromTransportChannel(TransportChannel* tc);
@@ -359,9 +362,9 @@
   }
 
  private:
-  bool InitNetwork_n(const std::string* bundle_transport_name);
+  bool InitNetwork_n(TransportChannel* rtp_transport,
+                     TransportChannel* rtcp_transport);
   void DisconnectTransportChannels_n();
-  void DestroyTransportChannels_n();
   void SignalSentPacket_n(rtc::PacketTransportInterface* transport,
                           const rtc::SentPacket& sent_packet);
   void SignalSentPacket_w(const rtc::SentPacket& sent_packet);
@@ -372,22 +375,21 @@
 
   rtc::Thread* const worker_thread_;
   rtc::Thread* const network_thread_;
+  rtc::Thread* const signaling_thread_;
   rtc::AsyncInvoker invoker_;
 
   const std::string content_name_;
   std::unique_ptr<ConnectionMonitor> connection_monitor_;
 
-  // Transport related members that should be accessed from network thread.
-  TransportController* const transport_controller_;
   std::string transport_name_;
   // Is RTCP used at all by this type of channel?
   // Expected to be true (as of typing this) for everything except data
   // channels.
   const bool rtcp_enabled_;
   // TODO(johan): Replace TransportChannel* with rtc::PacketTransportInterface*.
-  TransportChannel* transport_channel_ = nullptr;
+  TransportChannel* rtp_transport_ = nullptr;
   std::vector<std::pair<rtc::Socket::Option, int> > socket_options_;
-  TransportChannel* rtcp_transport_channel_ = nullptr;
+  TransportChannel* rtcp_transport_ = nullptr;
   std::vector<std::pair<rtc::Socket::Option, int> > rtcp_socket_options_;
   SrtpFilter srtp_filter_;
   RtcpMuxFilter rtcp_mux_filter_;
@@ -422,14 +424,15 @@
  public:
   VoiceChannel(rtc::Thread* worker_thread,
                rtc::Thread* network_thread,
+               rtc::Thread* signaling_thread,
                MediaEngineInterface* media_engine,
                VoiceMediaChannel* channel,
-               TransportController* transport_controller,
                const std::string& content_name,
                bool rtcp,
                bool srtp_required);
   ~VoiceChannel();
-  bool Init_w(const std::string* bundle_transport_name);
+  bool Init_w(TransportChannel* rtp_transport,
+              TransportChannel* rtcp_transport);
 
   // Configure sending media on the stream with SSRC |ssrc|
   // If there is only one sending stream SSRC 0 can be used.
@@ -540,14 +543,15 @@
 class VideoChannel : public BaseChannel {
  public:
   VideoChannel(rtc::Thread* worker_thread,
-               rtc::Thread* netwokr_thread,
+               rtc::Thread* network_thread,
+               rtc::Thread* signaling_thread,
                VideoMediaChannel* channel,
-               TransportController* transport_controller,
                const std::string& content_name,
                bool rtcp,
                bool srtp_required);
   ~VideoChannel();
-  bool Init_w(const std::string* bundle_transport_name);
+  bool Init_w(TransportChannel* rtp_transport,
+              TransportChannel* rtcp_transport);
 
   // downcasts a MediaChannel
   VideoMediaChannel* media_channel() const override {
@@ -620,13 +624,14 @@
  public:
   RtpDataChannel(rtc::Thread* worker_thread,
                  rtc::Thread* network_thread,
-                 DataMediaChannel* media_channel,
-                 TransportController* transport_controller,
+                 rtc::Thread* signaling_thread,
+                 DataMediaChannel* channel,
                  const std::string& content_name,
                  bool rtcp,
                  bool srtp_required);
   ~RtpDataChannel();
-  bool Init_w(const std::string* bundle_transport_name);
+  bool Init_w(TransportChannel* rtp_transport,
+              TransportChannel* rtcp_transport);
 
   virtual bool SendData(const SendDataParams& params,
                         const rtc::CopyOnWriteBuffer& payload,
diff --git a/pc/channel_unittest.cc b/pc/channel_unittest.cc
index 589ebd5..f8346c9 100644
--- a/pc/channel_unittest.cc
+++ b/pc/channel_unittest.cc
@@ -145,6 +145,12 @@
                                           &ChannelTest<T>::OnMediaMonitor1);
     channel2_->SignalMediaMonitor.connect(this,
                                           &ChannelTest<T>::OnMediaMonitor2);
+    channel1_->SignalDestroyRtcpTransport.connect(
+        transport_controller1_.get(),
+        &cricket::FakeTransportController::DestroyRtcpTransport);
+    channel2_->SignalDestroyRtcpTransport.connect(
+        transport_controller2_.get(),
+        &cricket::FakeTransportController::DestroyRtcpTransport);
     if ((flags1 & DTLS) && (flags2 & DTLS)) {
       flags1 = (flags1 & ~SECURE);
       flags2 = (flags2 & ~SECURE);
@@ -190,13 +196,24 @@
       typename T::MediaChannel* ch,
       cricket::TransportController* transport_controller,
       int flags) {
+    rtc::Thread* signaling_thread =
+        transport_controller ? transport_controller->signaling_thread()
+                             : nullptr;
     typename T::Channel* channel = new typename T::Channel(
-        worker_thread, network_thread, engine, ch, transport_controller,
+        worker_thread, network_thread, signaling_thread, engine, ch,
         cricket::CN_AUDIO, (flags & RTCP) != 0, (flags & SECURE) != 0);
     rtc::CryptoOptions crypto_options;
     crypto_options.enable_gcm_crypto_suites = (flags & GCM_CIPHER) != 0;
     channel->SetCryptoOptions(crypto_options);
-    if (!channel->Init_w(nullptr)) {
+    cricket::TransportChannel* rtp_transport =
+        transport_controller->CreateTransportChannel(
+            channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
+    cricket::TransportChannel* rtcp_transport = nullptr;
+    if (channel->NeedsRtcpTransport()) {
+      rtcp_transport = transport_controller->CreateTransportChannel(
+          channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+    }
+    if (!channel->Init_w(rtp_transport, rtcp_transport)) {
       delete channel;
       channel = NULL;
     }
@@ -383,7 +400,7 @@
   // Returns true if so.
   bool CheckGcmCipher(typename T::Channel* channel, int flags) {
     int suite;
-    if (!channel->transport_channel()->GetSrtpCryptoSuite(&suite)) {
+    if (!channel->rtp_transport()->GetSrtpCryptoSuite(&suite)) {
       return false;
     }
 
@@ -513,43 +530,43 @@
   // mux.
   void TestSetContentsRtcpMux() {
     CreateChannels(RTCP, RTCP);
-    EXPECT_TRUE(channel1_->rtcp_transport_channel() != NULL);
-    EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
+    EXPECT_TRUE(channel1_->rtcp_transport() != NULL);
+    EXPECT_TRUE(channel2_->rtcp_transport() != NULL);
     typename T::Content content;
     CreateContent(0, kPcmuCodec, kH264Codec, &content);
     // Both sides agree on mux. Should no longer be a separate RTCP channel.
     content.set_rtcp_mux(true);
     EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
+    EXPECT_TRUE(channel1_->rtcp_transport() == NULL);
     // Only initiator supports mux. Should still have a separate RTCP channel.
     EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
     content.set_rtcp_mux(false);
     EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
+    EXPECT_TRUE(channel2_->rtcp_transport() != NULL);
   }
 
   // Test that SetLocalContent and SetRemoteContent properly set RTCP
   // mux when a provisional answer is received.
   void TestSetContentsRtcpMuxWithPrAnswer() {
     CreateChannels(RTCP, RTCP);
-    EXPECT_TRUE(channel1_->rtcp_transport_channel() != NULL);
-    EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
+    EXPECT_TRUE(channel1_->rtcp_transport() != NULL);
+    EXPECT_TRUE(channel2_->rtcp_transport() != NULL);
     typename T::Content content;
     CreateContent(0, kPcmuCodec, kH264Codec, &content);
     content.set_rtcp_mux(true);
     EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_PRANSWER, NULL));
-    EXPECT_TRUE(channel1_->rtcp_transport_channel() != NULL);
+    EXPECT_TRUE(channel1_->rtcp_transport() != NULL);
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
     // Both sides agree on mux. Should no longer be a separate RTCP channel.
-    EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
+    EXPECT_TRUE(channel1_->rtcp_transport() == NULL);
     // Only initiator supports mux. Should still have a separate RTCP channel.
     EXPECT_TRUE(channel2_->SetLocalContent(&content, CA_OFFER, NULL));
     content.set_rtcp_mux(false);
     EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_PRANSWER, NULL));
     EXPECT_TRUE(channel2_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel2_->rtcp_transport_channel() != NULL);
+    EXPECT_TRUE(channel2_->rtcp_transport() != NULL);
   }
 
   // Test that SetRemoteContent properly deals with a content update.
@@ -931,8 +948,7 @@
 
     CreateChannels(0, 0);
 
-    cricket::TransportChannel* transport_channel1 =
-        channel1_->transport_channel();
+    cricket::TransportChannel* transport_channel1 = channel1_->rtp_transport();
     ASSERT_TRUE(transport_channel1);
     typename T::MediaChannel* media_channel1 =
         static_cast<typename T::MediaChannel*>(channel1_->media_channel());
@@ -1804,8 +1820,7 @@
     error_handler.mode_ = cricket::SrtpFilter::UNPROTECT;
 
     network_thread_->Invoke<void>(RTC_FROM_HERE, [this] {
-      cricket::TransportChannel* transport_channel =
-          channel2_->transport_channel();
+      cricket::TransportChannel* transport_channel = channel2_->rtp_transport();
       transport_channel->SignalReadPacket(
           transport_channel, reinterpret_cast<const char*>(kBadPacket),
           sizeof(kBadPacket), rtc::PacketTime(), 0);
@@ -1818,8 +1833,8 @@
 
   void TestOnReadyToSend() {
     CreateChannels(RTCP, RTCP);
-    TransportChannel* rtp = channel1_->transport_channel();
-    TransportChannel* rtcp = channel1_->rtcp_transport_channel();
+    TransportChannel* rtp = channel1_->rtp_transport();
+    TransportChannel* rtcp = channel1_->rtcp_transport();
     EXPECT_FALSE(media_channel1_->ready_to_send());
 
     network_thread_->Invoke<void>(RTC_FROM_HERE,
@@ -1869,8 +1884,8 @@
     content.set_rtcp_mux(true);
     EXPECT_TRUE(channel1_->SetLocalContent(&content, CA_OFFER, NULL));
     EXPECT_TRUE(channel1_->SetRemoteContent(&content, CA_ANSWER, NULL));
-    EXPECT_TRUE(channel1_->rtcp_transport_channel() == NULL);
-    TransportChannel* rtp = channel1_->transport_channel();
+    EXPECT_TRUE(channel1_->rtcp_transport() == NULL);
+    TransportChannel* rtp = channel1_->rtp_transport();
     EXPECT_FALSE(media_channel1_->ready_to_send());
     // In the case of rtcp mux, the SignalReadyToSend() from rtp channel
     // should trigger the MediaChannel's OnReadyToSend.
@@ -2041,13 +2056,23 @@
     cricket::FakeVideoMediaChannel* ch,
     cricket::TransportController* transport_controller,
     int flags) {
+  rtc::Thread* signaling_thread =
+      transport_controller ? transport_controller->signaling_thread() : nullptr;
   cricket::VideoChannel* channel = new cricket::VideoChannel(
-      worker_thread, network_thread, ch, transport_controller,
-      cricket::CN_VIDEO, (flags & RTCP) != 0, (flags & SECURE) != 0);
+      worker_thread, network_thread, signaling_thread, ch, cricket::CN_VIDEO,
+      (flags & RTCP) != 0, (flags & SECURE) != 0);
   rtc::CryptoOptions crypto_options;
   crypto_options.enable_gcm_crypto_suites = (flags & GCM_CIPHER) != 0;
   channel->SetCryptoOptions(crypto_options);
-  if (!channel->Init_w(nullptr)) {
+  cricket::TransportChannel* rtp_transport =
+      transport_controller->CreateTransportChannel(
+          channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  cricket::TransportChannel* rtcp_transport = nullptr;
+  if (channel->NeedsRtcpTransport()) {
+    rtcp_transport = transport_controller->CreateTransportChannel(
+        channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+  if (!channel->Init_w(rtp_transport, rtcp_transport)) {
     delete channel;
     channel = NULL;
   }
@@ -3313,13 +3338,23 @@
     cricket::FakeDataMediaChannel* ch,
     cricket::TransportController* transport_controller,
     int flags) {
+  rtc::Thread* signaling_thread =
+      transport_controller ? transport_controller->signaling_thread() : nullptr;
   cricket::RtpDataChannel* channel = new cricket::RtpDataChannel(
-      worker_thread, network_thread, ch, transport_controller, cricket::CN_DATA,
+      worker_thread, network_thread, signaling_thread, ch, cricket::CN_DATA,
       (flags & RTCP) != 0, (flags & SECURE) != 0);
   rtc::CryptoOptions crypto_options;
   crypto_options.enable_gcm_crypto_suites = (flags & GCM_CIPHER) != 0;
   channel->SetCryptoOptions(crypto_options);
-  if (!channel->Init_w(nullptr)) {
+  cricket::TransportChannel* rtp_transport =
+      transport_controller->CreateTransportChannel(
+          channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTP);
+  cricket::TransportChannel* rtcp_transport = nullptr;
+  if (channel->NeedsRtcpTransport()) {
+    rtcp_transport = transport_controller->CreateTransportChannel(
+        channel->content_name(), cricket::ICE_CANDIDATE_COMPONENT_RTCP);
+  }
+  if (!channel->Init_w(rtp_transport, rtcp_transport)) {
     delete channel;
     channel = NULL;
   }
diff --git a/pc/channelmanager.cc b/pc/channelmanager.cc
index 4098d62..f8ed770 100644
--- a/pc/channelmanager.cc
+++ b/pc/channelmanager.cc
@@ -207,21 +207,26 @@
 
 VoiceChannel* ChannelManager::CreateVoiceChannel(
     webrtc::MediaControllerInterface* media_controller,
-    TransportController* transport_controller,
+    TransportChannel* rtp_transport,
+    TransportChannel* rtcp_transport,
+    rtc::Thread* signaling_thread,
     const std::string& content_name,
     const std::string* bundle_transport_name,
     bool rtcp,
     bool srtp_required,
     const AudioOptions& options) {
   return worker_thread_->Invoke<VoiceChannel*>(
-      RTC_FROM_HERE, Bind(&ChannelManager::CreateVoiceChannel_w, this,
-                          media_controller, transport_controller, content_name,
-                          bundle_transport_name, rtcp, srtp_required, options));
+      RTC_FROM_HERE,
+      Bind(&ChannelManager::CreateVoiceChannel_w, this, media_controller,
+           rtp_transport, rtcp_transport, signaling_thread, content_name,
+           bundle_transport_name, rtcp, srtp_required, options));
 }
 
 VoiceChannel* ChannelManager::CreateVoiceChannel_w(
     webrtc::MediaControllerInterface* media_controller,
-    TransportController* transport_controller,
+    TransportChannel* rtp_transport,
+    TransportChannel* rtcp_transport,
+    rtc::Thread* signaling_thread,
     const std::string& content_name,
     const std::string* bundle_transport_name,
     bool rtcp,
@@ -230,16 +235,18 @@
   RTC_DCHECK(initialized_);
   RTC_DCHECK(worker_thread_ == rtc::Thread::Current());
   RTC_DCHECK(nullptr != media_controller);
+
   VoiceMediaChannel* media_channel = media_engine_->CreateChannel(
       media_controller->call_w(), media_controller->config(), options);
   if (!media_channel)
     return nullptr;
 
   VoiceChannel* voice_channel = new VoiceChannel(
-      worker_thread_, network_thread_, media_engine_.get(), media_channel,
-      transport_controller, content_name, rtcp, srtp_required);
+      worker_thread_, network_thread_, signaling_thread, media_engine_.get(),
+      media_channel, content_name, rtcp, srtp_required);
   voice_channel->SetCryptoOptions(crypto_options_);
-  if (!voice_channel->Init_w(bundle_transport_name)) {
+
+  if (!voice_channel->Init_w(rtp_transport, rtcp_transport)) {
     delete voice_channel;
     return nullptr;
   }
@@ -272,21 +279,26 @@
 
 VideoChannel* ChannelManager::CreateVideoChannel(
     webrtc::MediaControllerInterface* media_controller,
-    TransportController* transport_controller,
+    TransportChannel* rtp_transport,
+    TransportChannel* rtcp_transport,
+    rtc::Thread* signaling_thread,
     const std::string& content_name,
     const std::string* bundle_transport_name,
     bool rtcp,
     bool srtp_required,
     const VideoOptions& options) {
   return worker_thread_->Invoke<VideoChannel*>(
-      RTC_FROM_HERE, Bind(&ChannelManager::CreateVideoChannel_w, this,
-                          media_controller, transport_controller, content_name,
-                          bundle_transport_name, rtcp, srtp_required, options));
+      RTC_FROM_HERE,
+      Bind(&ChannelManager::CreateVideoChannel_w, this, media_controller,
+           rtp_transport, rtcp_transport, signaling_thread, content_name,
+           bundle_transport_name, rtcp, srtp_required, options));
 }
 
 VideoChannel* ChannelManager::CreateVideoChannel_w(
     webrtc::MediaControllerInterface* media_controller,
-    TransportController* transport_controller,
+    TransportChannel* rtp_transport,
+    TransportChannel* rtcp_transport,
+    rtc::Thread* signaling_thread,
     const std::string& content_name,
     const std::string* bundle_transport_name,
     bool rtcp,
@@ -302,10 +314,10 @@
   }
 
   VideoChannel* video_channel =
-      new VideoChannel(worker_thread_, network_thread_, media_channel,
-                       transport_controller, content_name, rtcp, srtp_required);
+      new VideoChannel(worker_thread_, network_thread_, signaling_thread,
+                       media_channel, content_name, rtcp, srtp_required);
   video_channel->SetCryptoOptions(crypto_options_);
-  if (!video_channel->Init_w(bundle_transport_name)) {
+  if (!video_channel->Init_w(rtp_transport, rtcp_transport)) {
     delete video_channel;
     return NULL;
   }
@@ -339,20 +351,25 @@
 
 RtpDataChannel* ChannelManager::CreateRtpDataChannel(
     webrtc::MediaControllerInterface* media_controller,
-    TransportController* transport_controller,
+    TransportChannel* rtp_transport,
+    TransportChannel* rtcp_transport,
+    rtc::Thread* signaling_thread,
     const std::string& content_name,
     const std::string* bundle_transport_name,
     bool rtcp,
     bool srtp_required) {
   return worker_thread_->Invoke<RtpDataChannel*>(
-      RTC_FROM_HERE, Bind(&ChannelManager::CreateRtpDataChannel_w, this,
-                          media_controller, transport_controller, content_name,
-                          bundle_transport_name, rtcp, srtp_required));
+      RTC_FROM_HERE,
+      Bind(&ChannelManager::CreateRtpDataChannel_w, this, media_controller,
+           rtp_transport, rtcp_transport, signaling_thread, content_name,
+           bundle_transport_name, rtcp, srtp_required));
 }
 
 RtpDataChannel* ChannelManager::CreateRtpDataChannel_w(
     webrtc::MediaControllerInterface* media_controller,
-    TransportController* transport_controller,
+    TransportChannel* rtp_transport,
+    TransportChannel* rtcp_transport,
+    rtc::Thread* signaling_thread,
     const std::string& content_name,
     const std::string* bundle_transport_name,
     bool rtcp,
@@ -369,11 +386,11 @@
     return nullptr;
   }
 
-  RtpDataChannel* data_channel = new RtpDataChannel(
-      worker_thread_, network_thread_, media_channel, transport_controller,
-      content_name, rtcp, srtp_required);
+  RtpDataChannel* data_channel =
+      new RtpDataChannel(worker_thread_, network_thread_, signaling_thread,
+                         media_channel, content_name, rtcp, srtp_required);
   data_channel->SetCryptoOptions(crypto_options_);
-  if (!data_channel->Init_w(bundle_transport_name)) {
+  if (!data_channel->Init_w(rtp_transport, rtcp_transport)) {
     LOG(LS_WARNING) << "Failed to init data channel.";
     delete data_channel;
     return nullptr;
diff --git a/pc/channelmanager.h b/pc/channelmanager.h
index 3022eca..89af44a 100644
--- a/pc/channelmanager.h
+++ b/pc/channelmanager.h
@@ -90,7 +90,9 @@
   // Creates a voice channel, to be associated with the specified session.
   VoiceChannel* CreateVoiceChannel(
       webrtc::MediaControllerInterface* media_controller,
-      TransportController* transport_controller,
+      TransportChannel* rtp_transport,
+      TransportChannel* rtcp_transport,
+      rtc::Thread* signaling_thread,
       const std::string& content_name,
       const std::string* bundle_transport_name,
       bool rtcp,
@@ -102,7 +104,9 @@
   // associated with the specified session.
   VideoChannel* CreateVideoChannel(
       webrtc::MediaControllerInterface* media_controller,
-      TransportController* transport_controller,
+      TransportChannel* rtp_transport,
+      TransportChannel* rtcp_transport,
+      rtc::Thread* signaling_thread,
       const std::string& content_name,
       const std::string* bundle_transport_name,
       bool rtcp,
@@ -112,7 +116,9 @@
   void DestroyVideoChannel(VideoChannel* video_channel);
   RtpDataChannel* CreateRtpDataChannel(
       webrtc::MediaControllerInterface* media_controller,
-      TransportController* transport_controller,
+      TransportChannel* rtp_transport,
+      TransportChannel* rtcp_transport,
+      rtc::Thread* signaling_thread,
       const std::string& content_name,
       const std::string* bundle_transport_name,
       bool rtcp,
@@ -161,7 +167,9 @@
   bool SetCryptoOptions_w(const rtc::CryptoOptions& crypto_options);
   VoiceChannel* CreateVoiceChannel_w(
       webrtc::MediaControllerInterface* media_controller,
-      TransportController* transport_controller,
+      TransportChannel* rtp_transport,
+      TransportChannel* rtcp_transport,
+      rtc::Thread* signaling_thread,
       const std::string& content_name,
       const std::string* bundle_transport_name,
       bool rtcp,
@@ -170,7 +178,9 @@
   void DestroyVoiceChannel_w(VoiceChannel* voice_channel);
   VideoChannel* CreateVideoChannel_w(
       webrtc::MediaControllerInterface* media_controller,
-      TransportController* transport_controller,
+      TransportChannel* rtp_transport,
+      TransportChannel* rtcp_transport,
+      rtc::Thread* signaling_thread,
       const std::string& content_name,
       const std::string* bundle_transport_name,
       bool rtcp,
@@ -179,7 +189,9 @@
   void DestroyVideoChannel_w(VideoChannel* video_channel);
   RtpDataChannel* CreateRtpDataChannel_w(
       webrtc::MediaControllerInterface* media_controller,
-      TransportController* transport_controller,
+      TransportChannel* rtp_transport,
+      TransportChannel* rtcp_transport,
+      rtc::Thread* signaling_thread,
       const std::string& content_name,
       const std::string* bundle_transport_name,
       bool rtcp,
diff --git a/pc/channelmanager_unittest.cc b/pc/channelmanager_unittest.cc
index 30d2fe5..34d9108 100644
--- a/pc/channelmanager_unittest.cc
+++ b/pc/channelmanager_unittest.cc
@@ -102,17 +102,23 @@
 // Test that we can create and destroy a voice and video channel.
 TEST_F(ChannelManagerTest, CreateDestroyChannels) {
   EXPECT_TRUE(cm_->Init());
+  cricket::TransportChannel* rtp_transport =
+      transport_controller_->CreateTransportChannel(
+          cricket::CN_AUDIO, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
-      &fake_mc_, transport_controller_, cricket::CN_AUDIO, nullptr,
-      kDefaultRtcpEnabled, kDefaultSrtpRequired, AudioOptions());
+      &fake_mc_, rtp_transport, nullptr /*rtcp_transport*/,
+      rtc::Thread::Current(), cricket::CN_AUDIO, nullptr, kDefaultRtcpEnabled,
+      kDefaultSrtpRequired, AudioOptions());
   EXPECT_TRUE(voice_channel != nullptr);
   cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
-      &fake_mc_, transport_controller_, cricket::CN_VIDEO, nullptr,
-      kDefaultRtcpEnabled, kDefaultSrtpRequired, VideoOptions());
+      &fake_mc_, rtp_transport, nullptr /*rtcp_transport*/,
+      rtc::Thread::Current(), cricket::CN_VIDEO, nullptr, kDefaultRtcpEnabled,
+      kDefaultSrtpRequired, VideoOptions());
   EXPECT_TRUE(video_channel != nullptr);
   cricket::RtpDataChannel* rtp_data_channel = cm_->CreateRtpDataChannel(
-      &fake_mc_, transport_controller_, cricket::CN_DATA, nullptr,
-      kDefaultRtcpEnabled, kDefaultSrtpRequired);
+      &fake_mc_, rtp_transport, nullptr /*rtcp_transport*/,
+      rtc::Thread::Current(), cricket::CN_DATA, nullptr, kDefaultRtcpEnabled,
+      kDefaultSrtpRequired);
   EXPECT_TRUE(rtp_data_channel != nullptr);
   cm_->DestroyVideoChannel(video_channel);
   cm_->DestroyVoiceChannel(voice_channel);
@@ -130,17 +136,23 @@
   delete transport_controller_;
   transport_controller_ =
       new cricket::FakeTransportController(&network_, ICEROLE_CONTROLLING);
+  cricket::TransportChannel* rtp_transport =
+      transport_controller_->CreateTransportChannel(
+          cricket::CN_AUDIO, cricket::ICE_CANDIDATE_COMPONENT_RTP);
   cricket::VoiceChannel* voice_channel = cm_->CreateVoiceChannel(
-      &fake_mc_, transport_controller_, cricket::CN_AUDIO, nullptr,
-      kDefaultRtcpEnabled, kDefaultSrtpRequired, AudioOptions());
+      &fake_mc_, rtp_transport, nullptr /*rtcp_transport*/,
+      rtc::Thread::Current(), cricket::CN_AUDIO, nullptr, kDefaultRtcpEnabled,
+      kDefaultSrtpRequired, AudioOptions());
   EXPECT_TRUE(voice_channel != nullptr);
   cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
-      &fake_mc_, transport_controller_, cricket::CN_VIDEO, nullptr,
-      kDefaultRtcpEnabled, kDefaultSrtpRequired, VideoOptions());
+      &fake_mc_, rtp_transport, nullptr /*rtcp_transport*/,
+      rtc::Thread::Current(), cricket::CN_VIDEO, nullptr, kDefaultRtcpEnabled,
+      kDefaultSrtpRequired, VideoOptions());
   EXPECT_TRUE(video_channel != nullptr);
   cricket::RtpDataChannel* rtp_data_channel = cm_->CreateRtpDataChannel(
-      &fake_mc_, transport_controller_, cricket::CN_DATA, nullptr,
-      kDefaultRtcpEnabled, kDefaultSrtpRequired);
+      &fake_mc_, rtp_transport, nullptr /*rtcp_transport*/,
+      rtc::Thread::Current(), cricket::CN_DATA, nullptr, kDefaultRtcpEnabled,
+      kDefaultSrtpRequired);
   EXPECT_TRUE(rtp_data_channel != nullptr);
   cm_->DestroyVideoChannel(video_channel);
   cm_->DestroyVoiceChannel(voice_channel);