Enable use of MediaTransportInterface for video streams.

Bug: webrtc:9719
Change-Id: I8c6027b4b15ed641e42fd210b3ea87d121508a69
Reviewed-on: https://webrtc-review.googlesource.com/c/111751
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Stefan Holmer <stefan@webrtc.org>
Reviewed-by: Peter Slatala <psla@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Commit-Queue: Niels Moller <nisse@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#26219}
diff --git a/pc/channelmanager.cc b/pc/channelmanager.cc
index 0c86cf6..d5cbd9c 100644
--- a/pc/channelmanager.cc
+++ b/pc/channelmanager.cc
@@ -226,6 +226,7 @@
     webrtc::Call* call,
     const cricket::MediaConfig& media_config,
     webrtc::RtpTransportInternal* rtp_transport,
+    webrtc::MediaTransportInterface* media_transport,
     rtc::Thread* signaling_thread,
     const std::string& content_name,
     bool srtp_required,
@@ -234,8 +235,8 @@
   if (!worker_thread_->IsCurrent()) {
     return worker_thread_->Invoke<VideoChannel*>(RTC_FROM_HERE, [&] {
       return CreateVideoChannel(call, media_config, rtp_transport,
-                                signaling_thread, content_name, srtp_required,
-                                crypto_options, options);
+                                media_transport, signaling_thread, content_name,
+                                srtp_required, crypto_options, options);
     });
   }
 
@@ -257,8 +258,7 @@
       absl::WrapUnique(media_channel), content_name, srtp_required,
       crypto_options);
 
-  // TODO(sukhanov): Add media_transport support for video channel.
-  video_channel->Init_w(rtp_transport, /*media_transport=*/nullptr);
+  video_channel->Init_w(rtp_transport, media_transport);
 
   VideoChannel* video_channel_ptr = video_channel.get();
   video_channels_.push_back(std::move(video_channel));
diff --git a/pc/channelmanager.h b/pc/channelmanager.h
index 2b7a30a..8bd30d1 100644
--- a/pc/channelmanager.h
+++ b/pc/channelmanager.h
@@ -107,14 +107,16 @@
   // Creates a video channel, synced with the specified voice channel, and
   // associated with the specified session.
   // Version of the above that takes PacketTransportInternal.
-  VideoChannel* CreateVideoChannel(webrtc::Call* call,
-                                   const cricket::MediaConfig& media_config,
-                                   webrtc::RtpTransportInternal* rtp_transport,
-                                   rtc::Thread* signaling_thread,
-                                   const std::string& content_name,
-                                   bool srtp_required,
-                                   const webrtc::CryptoOptions& crypto_options,
-                                   const VideoOptions& options);
+  VideoChannel* CreateVideoChannel(
+      webrtc::Call* call,
+      const cricket::MediaConfig& media_config,
+      webrtc::RtpTransportInternal* rtp_transport,
+      webrtc::MediaTransportInterface* media_transport,
+      rtc::Thread* signaling_thread,
+      const std::string& content_name,
+      bool srtp_required,
+      const webrtc::CryptoOptions& crypto_options,
+      const VideoOptions& options);
   // Destroys a video channel created by CreateVideoChannel.
   void DestroyVideoChannel(VideoChannel* video_channel);
 
diff --git a/pc/channelmanager_unittest.cc b/pc/channelmanager_unittest.cc
index 4d16614..ed09b72 100644
--- a/pc/channelmanager_unittest.cc
+++ b/pc/channelmanager_unittest.cc
@@ -86,7 +86,7 @@
         webrtc::CryptoOptions(), AudioOptions());
     EXPECT_TRUE(voice_channel != nullptr);
     cricket::VideoChannel* video_channel = cm_->CreateVideoChannel(
-        &fake_call_, cricket::MediaConfig(), rtp_transport,
+        &fake_call_, cricket::MediaConfig(), rtp_transport, media_transport,
         rtc::Thread::Current(), cricket::CN_VIDEO, kDefaultSrtpRequired,
         webrtc::CryptoOptions(), VideoOptions());
     EXPECT_TRUE(video_channel != nullptr);
diff --git a/pc/peerconnection.cc b/pc/peerconnection.cc
index 518a2e6..2cf14a1 100644
--- a/pc/peerconnection.cc
+++ b/pc/peerconnection.cc
@@ -5922,10 +5922,13 @@
 cricket::VideoChannel* PeerConnection::CreateVideoChannel(
     const std::string& mid) {
   RtpTransportInternal* rtp_transport = GetRtpTransport(mid);
+  MediaTransportInterface* media_transport = nullptr;
+  if (configuration_.use_media_transport) {
+    media_transport = GetMediaTransport(mid);
+  }
 
-  // TODO(sukhanov): Propagate media_transport to video channel.
   cricket::VideoChannel* video_channel = channel_manager()->CreateVideoChannel(
-      call_.get(), configuration_.media_config, rtp_transport,
+      call_.get(), configuration_.media_config, rtp_transport, media_transport,
       signaling_thread(), mid, SrtpRequired(), GetCryptoOptions(),
       video_options_);
   if (!video_channel) {
diff --git a/pc/peerconnection_integrationtest.cc b/pc/peerconnection_integrationtest.cc
index ea1b5ea..0bd3d09 100644
--- a/pc/peerconnection_integrationtest.cc
+++ b/pc/peerconnection_integrationtest.cc
@@ -3598,6 +3598,41 @@
   EXPECT_GE(first_stats.sent_audio_frames, second_stats.received_audio_frames);
 }
 
+TEST_P(PeerConnectionIntegrationTest, MediaTransportBidirectionalVideo) {
+  PeerConnectionInterface::RTCConfiguration rtc_config;
+  rtc_config.use_media_transport = true;
+  rtc_config.enable_dtls_srtp = false;  // SDES is required for media transport.
+  ASSERT_TRUE(CreatePeerConnectionWrappersWithConfigAndMediaTransportFactory(
+      rtc_config, rtc_config, loopback_media_transports()->first_factory(),
+      loopback_media_transports()->second_factory()));
+  ConnectFakeSignaling();
+
+  caller()->AddVideoTrack();
+  callee()->AddVideoTrack();
+  // Start offer/answer exchange and wait for it to complete.
+  caller()->CreateAndSetAndSignalOffer();
+  ASSERT_TRUE_WAIT(SignalingStateStable(), kDefaultTimeout);
+
+  // Ensure that the media transport is ready.
+  loopback_media_transports()->SetState(webrtc::MediaTransportState::kWritable);
+  loopback_media_transports()->FlushAsyncInvokes();
+
+  MediaExpectations media_expectations;
+  media_expectations.ExpectBidirectionalVideo();
+  ASSERT_TRUE(ExpectNewFrames(media_expectations));
+
+  webrtc::MediaTransportPair::Stats first_stats =
+      loopback_media_transports()->FirstStats();
+  webrtc::MediaTransportPair::Stats second_stats =
+      loopback_media_transports()->SecondStats();
+
+  EXPECT_GT(first_stats.received_video_frames, 0);
+  EXPECT_GE(second_stats.sent_video_frames, first_stats.received_video_frames);
+
+  EXPECT_GT(second_stats.received_video_frames, 0);
+  EXPECT_GE(first_stats.sent_video_frames, second_stats.received_video_frames);
+}
+
 // Test that the ICE connection and gathering states eventually reach
 // "complete".
 TEST_P(PeerConnectionIntegrationTest, IceStatesReachCompletion) {
diff --git a/pc/rtpsenderreceiver_unittest.cc b/pc/rtpsenderreceiver_unittest.cc
index 037446f..ec1e949 100644
--- a/pc/rtpsenderreceiver_unittest.cc
+++ b/pc/rtpsenderreceiver_unittest.cc
@@ -108,8 +108,8 @@
         srtp_required, webrtc::CryptoOptions(), cricket::AudioOptions());
     video_channel_ = channel_manager_.CreateVideoChannel(
         &fake_call_, cricket::MediaConfig(), rtp_transport_.get(),
-        rtc::Thread::Current(), cricket::CN_VIDEO, srtp_required,
-        webrtc::CryptoOptions(), cricket::VideoOptions());
+        /*media_transport=*/nullptr, rtc::Thread::Current(), cricket::CN_VIDEO,
+        srtp_required, webrtc::CryptoOptions(), cricket::VideoOptions());
     voice_channel_->Enable(true);
     video_channel_->Enable(true);
     voice_media_channel_ = media_engine_->GetVoiceChannel(0);