Wire up RTP keep-alive in ortc api.

[This CL is work in progress.]

Wire up the rtp keep-alive in webrtc::Call::Config using new
SetRtpTransportParameters() method on RtpTransportInterface.

BUG=webrtc:7907

Review-Url: https://codereview.webrtc.org/2981513002
Cr-Commit-Position: refs/heads/master@{#19287}
diff --git a/webrtc/ortc/BUILD.gn b/webrtc/ortc/BUILD.gn
index 40c0b2a..199ee62 100644
--- a/webrtc/ortc/BUILD.gn
+++ b/webrtc/ortc/BUILD.gn
@@ -36,6 +36,7 @@
     "../api/audio_codecs:builtin_audio_decoder_factory",
     "../api/audio_codecs:builtin_audio_encoder_factory",
     "../call:call_interfaces",
+    "../call:rtp_sender",
     "../logging:rtc_event_log_api",
     "../media:rtc_media",
     "../media:rtc_media_base",
diff --git a/webrtc/ortc/ortcfactory.cc b/webrtc/ortc/ortcfactory.cc
index be1c4c7..d8b117b 100644
--- a/webrtc/ortc/ortcfactory.cc
+++ b/webrtc/ortc/ortcfactory.cc
@@ -76,14 +76,14 @@
               CreateRtpTransportController)
 PROXY_METHOD4(RTCErrorOr<std::unique_ptr<RtpTransportInterface>>,
               CreateRtpTransport,
-              const RtcpParameters&,
+              const RtpTransportParameters&,
               PacketTransportInterface*,
               PacketTransportInterface*,
               RtpTransportControllerInterface*)
 
 PROXY_METHOD4(RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>,
               CreateSrtpTransport,
-              const RtcpParameters&,
+              const RtpTransportParameters&,
               PacketTransportInterface*,
               PacketTransportInterface*,
               RtpTransportControllerInterface*)
@@ -226,14 +226,14 @@
 
 RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
 OrtcFactory::CreateRtpTransport(
-    const RtcpParameters& rtcp_parameters,
+    const RtpTransportParameters& parameters,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp,
     RtpTransportControllerInterface* transport_controller) {
   RTC_DCHECK_RUN_ON(signaling_thread_);
-  RtcpParameters copied_parameters = rtcp_parameters;
-  if (copied_parameters.cname.empty()) {
-    copied_parameters.cname = default_cname_;
+  RtpTransportParameters copied_parameters = parameters;
+  if (copied_parameters.rtcp.cname.empty()) {
+    copied_parameters.rtcp.cname = default_cname_;
   }
   if (transport_controller) {
     return transport_controller->GetInternal()->CreateProxiedRtpTransport(
@@ -263,14 +263,14 @@
 
 RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>
 OrtcFactory::CreateSrtpTransport(
-    const RtcpParameters& rtcp_parameters,
+    const RtpTransportParameters& parameters,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp,
     RtpTransportControllerInterface* transport_controller) {
   RTC_DCHECK_RUN_ON(signaling_thread_);
-  RtcpParameters copied_parameters = rtcp_parameters;
-  if (copied_parameters.cname.empty()) {
-    copied_parameters.cname = default_cname_;
+  RtpTransportParameters copied_parameters = parameters;
+  if (copied_parameters.rtcp.cname.empty()) {
+    copied_parameters.rtcp.cname = default_cname_;
   }
   if (transport_controller) {
     return transport_controller->GetInternal()->CreateProxiedSrtpTransport(
diff --git a/webrtc/ortc/ortcfactory.h b/webrtc/ortc/ortcfactory.h
index 2ce7be3..f93cb63 100644
--- a/webrtc/ortc/ortcfactory.h
+++ b/webrtc/ortc/ortcfactory.h
@@ -44,13 +44,13 @@
   CreateRtpTransportController() override;
 
   RTCErrorOr<std::unique_ptr<RtpTransportInterface>> CreateRtpTransport(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       PacketTransportInterface* rtp,
       PacketTransportInterface* rtcp,
       RtpTransportControllerInterface* transport_controller) override;
 
   RTCErrorOr<std::unique_ptr<SrtpTransportInterface>> CreateSrtpTransport(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       PacketTransportInterface* rtp,
       PacketTransportInterface* rtcp,
       RtpTransportControllerInterface* transport_controller) override;
@@ -103,6 +103,9 @@
               rtc::PacketSocketFactory* socket_factory,
               AudioDeviceModule* adm);
 
+  RTCErrorOr<std::unique_ptr<RtpTransportControllerInterface>>
+  CreateRtpTransportController(const RtpTransportParameters& parameters);
+
   // Thread::Invoke doesn't support move-only arguments, so we need to remove
   // the unique_ptr wrapper from media_engine. TODO(deadbeef): Fix this.
   static RTCErrorOr<std::unique_ptr<OrtcFactoryInterface>> Create_s(
diff --git a/webrtc/ortc/ortcfactory_integrationtest.cc b/webrtc/ortc/ortcfactory_integrationtest.cc
index e05c8f5..513e972 100644
--- a/webrtc/ortc/ortcfactory_integrationtest.cc
+++ b/webrtc/ortc/ortcfactory_integrationtest.cc
@@ -128,29 +128,29 @@
   // empty if RTCP muxing is used. |transport_controllers| can be empty if
   // these transports are being created using a default transport controller.
   RtpTransportPair CreateRtpTransportPair(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       const UdpTransportPair& rtp_udp_transports,
       const UdpTransportPair& rtcp_udp_transports,
       const RtpTransportControllerPair& transport_controllers) {
     auto transport_result1 = ortc_factory1_->CreateRtpTransport(
-        rtcp_parameters, rtp_udp_transports.first.get(),
+        parameters, rtp_udp_transports.first.get(),
         rtcp_udp_transports.first.get(), transport_controllers.first.get());
     auto transport_result2 = ortc_factory2_->CreateRtpTransport(
-        rtcp_parameters, rtp_udp_transports.second.get(),
+        parameters, rtp_udp_transports.second.get(),
         rtcp_udp_transports.second.get(), transport_controllers.second.get());
     return {transport_result1.MoveValue(), transport_result2.MoveValue()};
   }
 
   SrtpTransportPair CreateSrtpTransportPair(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       const UdpTransportPair& rtp_udp_transports,
       const UdpTransportPair& rtcp_udp_transports,
       const RtpTransportControllerPair& transport_controllers) {
     auto transport_result1 = ortc_factory1_->CreateSrtpTransport(
-        rtcp_parameters, rtp_udp_transports.first.get(),
+        parameters, rtp_udp_transports.first.get(),
         rtcp_udp_transports.first.get(), transport_controllers.first.get());
     auto transport_result2 = ortc_factory2_->CreateSrtpTransport(
-        rtcp_parameters, rtp_udp_transports.second.get(),
+        parameters, rtp_udp_transports.second.get(),
         rtcp_udp_transports.second.get(), transport_controllers.second.get());
     return {transport_result1.MoveValue(), transport_result2.MoveValue()};
   }
@@ -158,18 +158,18 @@
   // For convenience when |rtcp_udp_transports| and |transport_controllers|
   // aren't needed.
   RtpTransportPair CreateRtpTransportPair(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       const UdpTransportPair& rtp_udp_transports) {
-    return CreateRtpTransportPair(rtcp_parameters, rtp_udp_transports,
+    return CreateRtpTransportPair(parameters, rtp_udp_transports,
                                   UdpTransportPair(),
                                   RtpTransportControllerPair());
   }
 
   SrtpTransportPair CreateSrtpTransportPairAndSetKeys(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       const UdpTransportPair& rtp_udp_transports) {
     SrtpTransportPair srtp_transports = CreateSrtpTransportPair(
-        rtcp_parameters, rtp_udp_transports, UdpTransportPair(),
+        parameters, rtp_udp_transports, UdpTransportPair(),
         RtpTransportControllerPair());
     EXPECT_TRUE(srtp_transports.first->SetSrtpSendKey(kTestCryptoParams1).ok());
     EXPECT_TRUE(
@@ -182,10 +182,10 @@
   }
 
   SrtpTransportPair CreateSrtpTransportPairAndSetMismatchingKeys(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& parameters,
       const UdpTransportPair& rtp_udp_transports) {
     SrtpTransportPair srtp_transports = CreateSrtpTransportPair(
-        rtcp_parameters, rtp_udp_transports, UdpTransportPair(),
+        parameters, rtp_udp_transports, UdpTransportPair(),
         RtpTransportControllerPair());
     EXPECT_TRUE(srtp_transports.first->SetSrtpSendKey(kTestCryptoParams1).ok());
     EXPECT_TRUE(
@@ -558,18 +558,18 @@
   // transport controller.
   auto transport_controllers = CreateRtpTransportControllerPair();
 
-  RtcpParameters audio_rtcp_parameters;
-  audio_rtcp_parameters.mux = false;
-  auto audio_srtp_transports =
-      CreateSrtpTransportPair(audio_rtcp_parameters, audio_rtp_udp_transports,
-                              audio_rtcp_udp_transports, transport_controllers);
+  RtpTransportParameters audio_rtp_transport_parameters;
+  audio_rtp_transport_parameters.rtcp.mux = false;
+  auto audio_srtp_transports = CreateSrtpTransportPair(
+      audio_rtp_transport_parameters, audio_rtp_udp_transports,
+      audio_rtcp_udp_transports, transport_controllers);
 
-  RtcpParameters video_rtcp_parameters;
-  video_rtcp_parameters.mux = false;
-  video_rtcp_parameters.reduced_size = true;
-  auto video_srtp_transports =
-      CreateSrtpTransportPair(video_rtcp_parameters, video_rtp_udp_transports,
-                              video_rtcp_udp_transports, transport_controllers);
+  RtpTransportParameters video_rtp_transport_parameters;
+  video_rtp_transport_parameters.rtcp.mux = false;
+  video_rtp_transport_parameters.rtcp.reduced_size = true;
+  auto video_srtp_transports = CreateSrtpTransportPair(
+      video_rtp_transport_parameters, video_rtp_udp_transports,
+      video_rtcp_udp_transports, transport_controllers);
 
   // Set keys for SRTP transports.
   audio_srtp_transports.first->SetSrtpSendKey(kTestCryptoParams1);
diff --git a/webrtc/ortc/ortcfactory_unittest.cc b/webrtc/ortc/ortcfactory_unittest.cc
index d964383..ba8dfe9 100644
--- a/webrtc/ortc/ortcfactory_unittest.cc
+++ b/webrtc/ortc/ortcfactory_unittest.cc
@@ -66,16 +66,14 @@
   rtc::FakePacketTransport rtp("rtp");
   rtc::FakePacketTransport rtcp("rtcp");
   // With muxed RTCP.
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  auto result = ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp,
-                                                  nullptr, nullptr);
+  RtpTransportParameters parameters = MakeRtcpMuxParameters();
+  auto result =
+      ortc_factory_->CreateRtpTransport(parameters, &rtp, nullptr, nullptr);
   EXPECT_TRUE(result.ok());
   result.MoveValue().reset();
   // With non-muxed RTCP.
-  rtcp_parameters.mux = false;
-  result =
-      ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp, &rtcp, nullptr);
+  parameters.rtcp.mux = false;
+  result = ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
   EXPECT_TRUE(result.ok());
 }
 
@@ -84,16 +82,14 @@
   rtc::FakePacketTransport rtp("rtp");
   rtc::FakePacketTransport rtcp("rtcp");
   // With muxed RTCP.
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  auto result = ortc_factory_->CreateSrtpTransport(rtcp_parameters, &rtp,
-                                                   nullptr, nullptr);
+  RtpTransportParameters parameters = MakeRtcpMuxParameters();
+  auto result =
+      ortc_factory_->CreateSrtpTransport(parameters, &rtp, nullptr, nullptr);
   EXPECT_TRUE(result.ok());
   result.MoveValue().reset();
   // With non-muxed RTCP.
-  rtcp_parameters.mux = false;
-  result =
-      ortc_factory_->CreateSrtpTransport(rtcp_parameters, &rtp, &rtcp, nullptr);
+  parameters.rtcp.mux = false;
+  result = ortc_factory_->CreateSrtpTransport(parameters, &rtp, &rtcp, nullptr);
   EXPECT_TRUE(result.ok());
 }
 
@@ -101,12 +97,10 @@
 // GetRtpParameters.
 TEST_F(OrtcFactoryTest, CreateRtpTransportGeneratesCname) {
   rtc::FakePacketTransport rtp("rtp");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  auto result = ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp,
+  auto result = ortc_factory_->CreateRtpTransport(MakeRtcpMuxParameters(), &rtp,
                                                   nullptr, nullptr);
   ASSERT_TRUE(result.ok());
-  EXPECT_FALSE(result.value()->GetRtcpParameters().cname.empty());
+  EXPECT_FALSE(result.value()->GetParameters().rtcp.cname.empty());
 }
 
 // Extension of the above test; multiple transports created by the same factory
@@ -114,20 +108,19 @@
 TEST_F(OrtcFactoryTest, MultipleRtpTransportsUseSameGeneratedCname) {
   rtc::FakePacketTransport packet_transport1("1");
   rtc::FakePacketTransport packet_transport2("2");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
+  RtpTransportParameters parameters = MakeRtcpMuxParameters();
   // Sanity check.
-  ASSERT_TRUE(rtcp_parameters.cname.empty());
+  ASSERT_TRUE(parameters.rtcp.cname.empty());
   auto result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &packet_transport1, nullptr, nullptr);
+      parameters, &packet_transport1, nullptr, nullptr);
   ASSERT_TRUE(result.ok());
   auto rtp_transport1 = result.MoveValue();
-  result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &packet_transport2, nullptr, nullptr);
+  result = ortc_factory_->CreateRtpTransport(parameters, &packet_transport2,
+                                             nullptr, nullptr);
   ASSERT_TRUE(result.ok());
   auto rtp_transport2 = result.MoveValue();
-  RtcpParameters params1 = rtp_transport1->GetRtcpParameters();
-  RtcpParameters params2 = rtp_transport2->GetRtcpParameters();
+  RtcpParameters params1 = rtp_transport1->GetParameters().rtcp;
+  RtcpParameters params2 = rtp_transport2->GetParameters().rtcp;
   EXPECT_FALSE(params1.cname.empty());
   EXPECT_EQ(params1.cname, params2.cname);
 }
@@ -142,10 +135,10 @@
 // packet transport are needed.
 TEST_F(OrtcFactoryTest, CreateRtpTransportWithMissingRtcpTransport) {
   rtc::FakePacketTransport rtp("rtp");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = false;
-  auto result = ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp,
-                                                  nullptr, nullptr);
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = false;
+  auto result =
+      ortc_factory_->CreateRtpTransport(parameters, &rtp, nullptr, nullptr);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 }
 
@@ -155,10 +148,8 @@
 TEST_F(OrtcFactoryTest, CreateRtpTransportWithExtraneousRtcpTransport) {
   rtc::FakePacketTransport rtp("rtp");
   rtc::FakePacketTransport rtcp("rtcp");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  auto result =
-      ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp, &rtcp, nullptr);
+  auto result = ortc_factory_->CreateRtpTransport(MakeRtcpMuxParameters(), &rtp,
+                                                  &rtcp, nullptr);
   EXPECT_EQ(RTCErrorType::INVALID_PARAMETER, result.error().type());
 }
 
diff --git a/webrtc/ortc/ortcrtpreceiver_unittest.cc b/webrtc/ortc/ortcrtpreceiver_unittest.cc
index 8273be5..0e2b722 100644
--- a/webrtc/ortc/ortcrtpreceiver_unittest.cc
+++ b/webrtc/ortc/ortcrtpreceiver_unittest.cc
@@ -36,10 +36,10 @@
         nullptr, nullptr, nullptr, nullptr, nullptr,
         std::unique_ptr<cricket::MediaEngineInterface>(fake_media_engine_));
     ortc_factory_ = ortc_factory_result.MoveValue();
-    RtcpParameters rtcp_parameters;
-    rtcp_parameters.mux = true;
+    RtpTransportParameters parameters;
+    parameters.rtcp.mux = true;
     auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
-        rtcp_parameters, &fake_packet_transport_, nullptr, nullptr);
+        parameters, &fake_packet_transport_, nullptr, nullptr);
     rtp_transport_ = rtp_transport_result.MoveValue();
   }
 
@@ -97,10 +97,10 @@
 // test/tests for it.
 TEST_F(OrtcRtpReceiverTest, SetTransportFails) {
   rtc::FakePacketTransport fake_packet_transport("another_transport");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = true;
   auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &fake_packet_transport, nullptr, nullptr);
+      parameters, &fake_packet_transport, nullptr, nullptr);
   auto rtp_transport = rtp_transport_result.MoveValue();
 
   auto receiver_result = ortc_factory_->CreateRtpReceiver(
diff --git a/webrtc/ortc/ortcrtpsender_unittest.cc b/webrtc/ortc/ortcrtpsender_unittest.cc
index ab8d821..a94ed76 100644
--- a/webrtc/ortc/ortcrtpsender_unittest.cc
+++ b/webrtc/ortc/ortcrtpsender_unittest.cc
@@ -40,10 +40,10 @@
         nullptr, nullptr, nullptr, nullptr, nullptr,
         std::unique_ptr<cricket::MediaEngineInterface>(fake_media_engine_));
     ortc_factory_ = ortc_factory_result.MoveValue();
-    RtcpParameters rtcp_parameters;
-    rtcp_parameters.mux = true;
+    RtpTransportParameters parameters;
+    parameters.rtcp.mux = true;
     auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
-        rtcp_parameters, &fake_packet_transport_, nullptr, nullptr);
+        parameters, &fake_packet_transport_, nullptr, nullptr);
     rtp_transport_ = rtp_transport_result.MoveValue();
   }
 
@@ -153,10 +153,10 @@
 // test/tests for it.
 TEST_F(OrtcRtpSenderTest, SetTransportFails) {
   rtc::FakePacketTransport fake_packet_transport("another_transport");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = true;
   auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &fake_packet_transport, nullptr, nullptr);
+      parameters, &fake_packet_transport, nullptr, nullptr);
   auto rtp_transport = rtp_transport_result.MoveValue();
 
   auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_AUDIO,
diff --git a/webrtc/ortc/rtptransport_unittest.cc b/webrtc/ortc/rtptransport_unittest.cc
index 2fc1b23..95ee1c7 100644
--- a/webrtc/ortc/rtptransport_unittest.cc
+++ b/webrtc/ortc/rtptransport_unittest.cc
@@ -45,18 +45,17 @@
   rtc::FakePacketTransport rtp("rtp");
   rtc::FakePacketTransport rtcp("rtcp");
   // With muxed RTCP.
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  auto result = ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp,
-                                                  nullptr, nullptr);
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = true;
+  auto result =
+      ortc_factory_->CreateRtpTransport(parameters, &rtp, nullptr, nullptr);
   ASSERT_TRUE(result.ok());
   EXPECT_EQ(&rtp, result.value()->GetRtpPacketTransport());
   EXPECT_EQ(nullptr, result.value()->GetRtcpPacketTransport());
   result.MoveValue().reset();
   // With non-muxed RTCP.
-  rtcp_parameters.mux = false;
-  result =
-      ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp, &rtcp, nullptr);
+  parameters.rtcp.mux = false;
+  result = ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
   ASSERT_TRUE(result.ok());
   EXPECT_EQ(&rtp, result.value()->GetRtpPacketTransport());
   EXPECT_EQ(&rtcp, result.value()->GetRtcpPacketTransport());
@@ -70,16 +69,16 @@
   rtc::FakePacketTransport rtcp("rtcp");
 
   // Create non-muxed.
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = false;
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = false;
   auto result =
-      ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp, &rtcp, nullptr);
+      ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
   ASSERT_TRUE(result.ok());
   auto rtp_transport = result.MoveValue();
 
   // Enable muxing.
-  rtcp_parameters.mux = true;
-  EXPECT_TRUE(rtp_transport->SetRtcpParameters(rtcp_parameters).ok());
+  parameters.rtcp.mux = true;
+  EXPECT_TRUE(rtp_transport->SetParameters(parameters).ok());
   EXPECT_EQ(nullptr, rtp_transport->GetRtcpPacketTransport());
 }
 
@@ -87,39 +86,39 @@
   rtc::FakePacketTransport rtp("rtp");
   rtc::FakePacketTransport rtcp("rtcp");
   // Start with non-muxed RTCP.
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = false;
-  rtcp_parameters.cname = "teST";
-  rtcp_parameters.reduced_size = false;
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = false;
+  parameters.rtcp.cname = "teST";
+  parameters.rtcp.reduced_size = false;
   auto result =
-      ortc_factory_->CreateRtpTransport(rtcp_parameters, &rtp, &rtcp, nullptr);
+      ortc_factory_->CreateRtpTransport(parameters, &rtp, &rtcp, nullptr);
   ASSERT_TRUE(result.ok());
   auto transport = result.MoveValue();
-  EXPECT_EQ(rtcp_parameters, transport->GetRtcpParameters());
+  EXPECT_EQ(parameters, transport->GetParameters());
 
   // Changing the CNAME is currently unsupported.
-  rtcp_parameters.cname = "different";
+  parameters.rtcp.cname = "different";
   EXPECT_EQ(RTCErrorType::UNSUPPORTED_OPERATION,
-            transport->SetRtcpParameters(rtcp_parameters).type());
-  rtcp_parameters.cname = "teST";
+            transport->SetParameters(parameters).type());
+  parameters.rtcp.cname = "teST";
 
   // Enable RTCP muxing and reduced-size RTCP.
-  rtcp_parameters.mux = true;
-  rtcp_parameters.reduced_size = true;
-  EXPECT_TRUE(transport->SetRtcpParameters(rtcp_parameters).ok());
-  EXPECT_EQ(rtcp_parameters, transport->GetRtcpParameters());
+  parameters.rtcp.mux = true;
+  parameters.rtcp.reduced_size = true;
+  EXPECT_TRUE(transport->SetParameters(parameters).ok());
+  EXPECT_EQ(parameters, transport->GetParameters());
 
   // Empty CNAME should result in the existing CNAME being used.
-  rtcp_parameters.cname.clear();
-  EXPECT_TRUE(transport->SetRtcpParameters(rtcp_parameters).ok());
-  EXPECT_EQ("teST", transport->GetRtcpParameters().cname);
+  parameters.rtcp.cname.clear();
+  EXPECT_TRUE(transport->SetParameters(parameters).ok());
+  EXPECT_EQ("teST", transport->GetParameters().rtcp.cname);
 
   // Disabling RTCP muxing after enabling shouldn't be allowed, since enabling
   // muxing should have made the RTP transport forget about the RTCP packet
   // transport initially passed into it.
-  rtcp_parameters.mux = false;
+  parameters.rtcp.mux = false;
   EXPECT_EQ(RTCErrorType::INVALID_STATE,
-            transport->SetRtcpParameters(rtcp_parameters).type());
+            transport->SetParameters(parameters).type());
 }
 
 // When Send or Receive is called on a sender or receiver, the RTCP parameters
@@ -129,12 +128,12 @@
 TEST_F(RtpTransportTest, SendAndReceiveApplyRtcpParametersToMediaEngine) {
   // First, create video transport with reduced-size RTCP.
   rtc::FakePacketTransport fake_packet_transport1("1");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  rtcp_parameters.reduced_size = true;
-  rtcp_parameters.cname = "foo";
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = true;
+  parameters.rtcp.reduced_size = true;
+  parameters.rtcp.cname = "foo";
   auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &fake_packet_transport1, nullptr, nullptr);
+      parameters, &fake_packet_transport1, nullptr, nullptr);
   auto video_transport = rtp_transport_result.MoveValue();
 
   // Create video sender and call Send, expecting parameters to be applied.
@@ -163,10 +162,10 @@
 
   // Create audio transport with non-reduced size RTCP.
   rtc::FakePacketTransport fake_packet_transport2("2");
-  rtcp_parameters.reduced_size = false;
-  rtcp_parameters.cname = "bar";
+  parameters.rtcp.reduced_size = false;
+  parameters.rtcp.cname = "bar";
   rtp_transport_result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &fake_packet_transport2, nullptr, nullptr);
+      parameters, &fake_packet_transport2, nullptr, nullptr);
   auto audio_transport = rtp_transport_result.MoveValue();
 
   // Create audio sender and call Send, expecting parameters to be applied.
@@ -195,17 +194,17 @@
   EXPECT_FALSE(fake_voice_channel->recv_rtcp_parameters().reduced_size);
 }
 
-// When SetRtcpParameters is called, the modified parameters should be applied
+// When SetParameters is called, the modified parameters should be applied
 // to the media engine.
 // TODO(deadbeef): Once the implementation supports changing the CNAME,
 // test that here.
 TEST_F(RtpTransportTest, SetRtcpParametersAppliesParametersToMediaEngine) {
   rtc::FakePacketTransport fake_packet_transport("fake");
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  rtcp_parameters.reduced_size = false;
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = true;
+  parameters.rtcp.reduced_size = false;
   auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
-      rtcp_parameters, &fake_packet_transport, nullptr, nullptr);
+      parameters, &fake_packet_transport, nullptr, nullptr);
   auto rtp_transport = rtp_transport_result.MoveValue();
 
   // Create video sender and call Send, applying an initial set of parameters.
@@ -215,8 +214,8 @@
   EXPECT_TRUE(sender->Send(MakeMinimalVp8Parameters()).ok());
 
   // Modify parameters and expect them to be changed at the media engine level.
-  rtcp_parameters.reduced_size = true;
-  EXPECT_TRUE(rtp_transport->SetRtcpParameters(rtcp_parameters).ok());
+  parameters.rtcp.reduced_size = true;
+  EXPECT_TRUE(rtp_transport->SetParameters(parameters).ok());
 
   cricket::FakeVideoMediaChannel* fake_video_channel =
       fake_media_engine_->GetVideoChannel(0);
@@ -224,4 +223,61 @@
   EXPECT_TRUE(fake_video_channel->send_rtcp_parameters().reduced_size);
 }
 
+// SetParameters should set keepalive for all RTP transports.
+// It is impossible to modify keepalive parameters if any streams are created.
+// Note: This is an implementation detail for current way of configuring the
+// keep-alive. It may change in the future.
+TEST_F(RtpTransportTest, CantChangeKeepAliveAfterCreatedSendStreams) {
+  rtc::FakePacketTransport fake_packet_transport("fake");
+  RtpTransportParameters parameters;
+  parameters.keepalive.timeout_interval_ms = 100;
+  auto rtp_transport_result = ortc_factory_->CreateRtpTransport(
+      parameters, &fake_packet_transport, nullptr, nullptr);
+  ASSERT_TRUE(rtp_transport_result.ok());
+  std::unique_ptr<RtpTransportInterface> rtp_transport =
+      rtp_transport_result.MoveValue();
+
+  // Updating keepalive parameters is ok, since no rtp sender created.
+  parameters.keepalive.timeout_interval_ms = 200;
+  EXPECT_TRUE(rtp_transport->SetParameters(parameters).ok());
+
+  // Create video sender. Note: |sender_result| scope must extend past the
+  // SetParameters() call below.
+  auto sender_result = ortc_factory_->CreateRtpSender(cricket::MEDIA_TYPE_VIDEO,
+                                                      rtp_transport.get());
+  EXPECT_TRUE(sender_result.ok());
+
+  // Modify parameters second time after video send stream created.
+  parameters.keepalive.timeout_interval_ms = 10;
+  EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION,
+            rtp_transport->SetParameters(parameters).type());
+}
+
+// Note: This is an implementation detail for current way of configuring the
+// keep-alive. It may change in the future.
+TEST_F(RtpTransportTest, KeepAliveMustBeSameAcrossTransportController) {
+  rtc::FakePacketTransport fake_packet_transport("fake");
+  RtpTransportParameters parameters;
+  parameters.keepalive.timeout_interval_ms = 100;
+
+  // Manually create a controller, that can be shared by multiple transports.
+  auto controller_result = ortc_factory_->CreateRtpTransportController();
+  ASSERT_TRUE(controller_result.ok());
+  std::unique_ptr<RtpTransportControllerInterface> controller =
+      controller_result.MoveValue();
+
+  // Create a first transport.
+  auto first_transport_result = ortc_factory_->CreateRtpTransport(
+      parameters, &fake_packet_transport, nullptr, controller.get());
+  ASSERT_TRUE(first_transport_result.ok());
+
+  // Update the parameters, and create another transport for the same
+  // controller.
+  parameters.keepalive.timeout_interval_ms = 10;
+  auto seconds_transport_result = ortc_factory_->CreateRtpTransport(
+      parameters, &fake_packet_transport, nullptr, controller.get());
+  EXPECT_EQ(RTCErrorType::INVALID_MODIFICATION,
+            seconds_transport_result.error().type());
+}
+
 }  // namespace webrtc
diff --git a/webrtc/ortc/rtptransportadapter.cc b/webrtc/ortc/rtptransportadapter.cc
index 1154ff6..10e5e8f 100644
--- a/webrtc/ortc/rtptransportadapter.cc
+++ b/webrtc/ortc/rtptransportadapter.cc
@@ -24,8 +24,8 @@
 PROXY_SIGNALING_THREAD_DESTRUCTOR()
 PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtpPacketTransport)
 PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtcpPacketTransport)
-PROXY_METHOD1(RTCError, SetRtcpParameters, const RtcpParameters&)
-PROXY_CONSTMETHOD0(RtcpParameters, GetRtcpParameters)
+PROXY_METHOD1(RTCError, SetParameters, const RtpTransportParameters&)
+PROXY_CONSTMETHOD0(RtpTransportParameters, GetParameters)
 protected:
 RtpTransportAdapter* GetInternal() override {
   return internal();
@@ -36,8 +36,8 @@
 PROXY_SIGNALING_THREAD_DESTRUCTOR()
 PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtpPacketTransport)
 PROXY_CONSTMETHOD0(PacketTransportInterface*, GetRtcpPacketTransport)
-PROXY_METHOD1(RTCError, SetRtcpParameters, const RtcpParameters&)
-PROXY_CONSTMETHOD0(RtcpParameters, GetRtcpParameters)
+PROXY_METHOD1(RTCError, SetParameters, const RtpTransportParameters&)
+PROXY_CONSTMETHOD0(RtpTransportParameters, GetParameters)
 PROXY_METHOD1(RTCError, SetSrtpSendKey, const cricket::CryptoParams&)
 PROXY_METHOD1(RTCError, SetSrtpReceiveKey, const cricket::CryptoParams&)
 protected:
@@ -49,7 +49,7 @@
 // static
 RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
 RtpTransportAdapter::CreateProxied(
-    const RtcpParameters& rtcp_parameters,
+    const RtpTransportParameters& parameters,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp,
     RtpTransportControllerAdapter* rtp_transport_controller) {
@@ -57,12 +57,12 @@
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                          "Must provide an RTP packet transport.");
   }
-  if (!rtcp_parameters.mux && !rtcp) {
+  if (!parameters.rtcp.mux && !rtcp) {
     LOG_AND_RETURN_ERROR(
         RTCErrorType::INVALID_PARAMETER,
         "Must provide an RTCP packet transport when RTCP muxing is not used.");
   }
-  if (rtcp_parameters.mux && rtcp) {
+  if (parameters.rtcp.mux && rtcp) {
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                          "Creating an RtpTransport with RTCP muxing enabled, "
                          "with a separate RTCP packet transport?");
@@ -74,17 +74,23 @@
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                          "Must provide an RTP transport controller.");
   }
+  std::unique_ptr<RtpTransportAdapter> transport_adapter(
+      new RtpTransportAdapter(parameters.rtcp, rtp, rtcp,
+                              rtp_transport_controller,
+                              false /*is_srtp_transport*/));
+  RTCError params_result = transport_adapter->SetParameters(parameters);
+  if (!params_result.ok()) {
+    return std::move(params_result);
+  }
+
   return RtpTransportProxyWithInternal<RtpTransportAdapter>::Create(
       rtp_transport_controller->signaling_thread(),
-      rtp_transport_controller->worker_thread(),
-      std::unique_ptr<RtpTransportAdapter>(new RtpTransportAdapter(
-          rtcp_parameters, rtp, rtcp, rtp_transport_controller,
-          /*is_srtp_transport*/ false)));
+      rtp_transport_controller->worker_thread(), std::move(transport_adapter));
 }
 
 RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>
 RtpTransportAdapter::CreateSrtpProxied(
-    const RtcpParameters& rtcp_parameters,
+    const RtpTransportParameters& parameters,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp,
     RtpTransportControllerAdapter* rtp_transport_controller) {
@@ -92,12 +98,12 @@
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                          "Must provide an RTP packet transport.");
   }
-  if (!rtcp_parameters.mux && !rtcp) {
+  if (!parameters.rtcp.mux && !rtcp) {
     LOG_AND_RETURN_ERROR(
         RTCErrorType::INVALID_PARAMETER,
         "Must provide an RTCP packet transport when RTCP muxing is not used.");
   }
-  if (rtcp_parameters.mux && rtcp) {
+  if (parameters.rtcp.mux && rtcp) {
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                          "Creating an RtpTransport with RTCP muxing enabled, "
                          "with a separate RTCP packet transport?");
@@ -109,12 +115,18 @@
     LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_PARAMETER,
                          "Must provide an RTP transport controller.");
   }
+  std::unique_ptr<RtpTransportAdapter> transport_adapter(
+      new RtpTransportAdapter(parameters.rtcp, rtp, rtcp,
+                              rtp_transport_controller,
+                              true /*is_srtp_transport*/));
+  RTCError params_result = transport_adapter->SetParameters(parameters);
+  if (!params_result.ok()) {
+    return std::move(params_result);
+  }
+
   return SrtpTransportProxyWithInternal<RtpTransportAdapter>::Create(
       rtp_transport_controller->signaling_thread(),
-      rtp_transport_controller->worker_thread(),
-      std::unique_ptr<RtpTransportAdapter>(new RtpTransportAdapter(
-          rtcp_parameters, rtp, rtcp, rtp_transport_controller,
-          /*is_srtp_transport*/ true)));
+      rtp_transport_controller->worker_thread(), std::move(transport_adapter));
 }
 
 void RtpTransportAdapter::TakeOwnershipOfRtpTransportController(
@@ -125,7 +137,7 @@
 }
 
 RtpTransportAdapter::RtpTransportAdapter(
-    const RtcpParameters& rtcp_parameters,
+    const RtcpParameters& rtcp_params,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp,
     RtpTransportControllerAdapter* rtp_transport_controller,
@@ -133,11 +145,11 @@
     : rtp_packet_transport_(rtp),
       rtcp_packet_transport_(rtcp),
       rtp_transport_controller_(rtp_transport_controller),
-      rtcp_parameters_(rtcp_parameters),
       is_srtp_transport_(is_srtp_transport) {
-  RTC_DCHECK(rtp_transport_controller);
+  parameters_.rtcp = rtcp_params;
   // CNAME should have been filled by OrtcFactory if empty.
-  RTC_DCHECK(!rtcp_parameters_.cname.empty());
+  RTC_DCHECK(!parameters_.rtcp.cname.empty());
+  RTC_DCHECK(rtp_transport_controller);
 }
 
 RtpTransportAdapter::~RtpTransportAdapter() {
@@ -152,27 +164,29 @@
   return rtcp_packet_transport_;
 }
 
-RTCError RtpTransportAdapter::SetRtcpParameters(
-    const RtcpParameters& parameters) {
-  if (!parameters.mux && rtcp_parameters_.mux) {
+RTCError RtpTransportAdapter::SetParameters(
+    const RtpTransportParameters& parameters) {
+  if (!parameters.rtcp.mux && parameters_.rtcp.mux) {
     LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::INVALID_STATE,
                          "Can't disable RTCP muxing after enabling.");
   }
-  if (!parameters.cname.empty() && parameters.cname != rtcp_parameters_.cname) {
+  if (!parameters.rtcp.cname.empty() &&
+      parameters.rtcp.cname != parameters_.rtcp.cname) {
     LOG_AND_RETURN_ERROR(webrtc::RTCErrorType::UNSUPPORTED_OPERATION,
                          "Changing the RTCP CNAME is currently unsupported.");
   }
   // If the CNAME is empty, use the existing one.
-  RtcpParameters copy = parameters;
-  if (copy.cname.empty()) {
-    copy.cname = rtcp_parameters_.cname;
+  RtpTransportParameters copy = parameters;
+  if (copy.rtcp.cname.empty()) {
+    copy.rtcp.cname = parameters_.rtcp.cname;
   }
-  RTCError err = rtp_transport_controller_->SetRtcpParameters(copy, this);
+  RTCError err =
+      rtp_transport_controller_->SetRtpTransportParameters(copy, this);
   if (!err.ok()) {
     return err;
   }
-  rtcp_parameters_ = copy;
-  if (rtcp_parameters_.mux) {
+  parameters_ = copy;
+  if (parameters_.rtcp.mux) {
     rtcp_packet_transport_ = nullptr;
   }
   return RTCError::OK();
diff --git a/webrtc/ortc/rtptransportadapter.h b/webrtc/ortc/rtptransportadapter.h
index 6fbc162..c71a4f4 100644
--- a/webrtc/ortc/rtptransportadapter.h
+++ b/webrtc/ortc/rtptransportadapter.h
@@ -36,13 +36,13 @@
   // |rtp| can't be null. |rtcp| can if RTCP muxing is used immediately (meaning
   // |rtcp_parameters.mux| is also true).
   static RTCErrorOr<std::unique_ptr<RtpTransportInterface>> CreateProxied(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& rtcp_parameters,
       PacketTransportInterface* rtp,
       PacketTransportInterface* rtcp,
       RtpTransportControllerAdapter* rtp_transport_controller);
 
   static RTCErrorOr<std::unique_ptr<SrtpTransportInterface>> CreateSrtpProxied(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& rtcp_parameters,
       PacketTransportInterface* rtp,
       PacketTransportInterface* rtcp,
       RtpTransportControllerAdapter* rtp_transport_controller);
@@ -52,8 +52,8 @@
   // RtpTransportInterface implementation.
   PacketTransportInterface* GetRtpPacketTransport() const override;
   PacketTransportInterface* GetRtcpPacketTransport() const override;
-  RTCError SetRtcpParameters(const RtcpParameters& parameters) override;
-  RtcpParameters GetRtcpParameters() const override { return rtcp_parameters_; }
+  RTCError SetParameters(const RtpTransportParameters& parameters) override;
+  RtpTransportParameters GetParameters() const override { return parameters_; }
 
   // SRTP specific implementation.
   RTCError SetSrtpSendKey(const cricket::CryptoParams& params) override;
@@ -82,7 +82,7 @@
   RtpTransportAdapter* GetInternal() override { return this; }
 
  private:
-  RtpTransportAdapter(const RtcpParameters& rtcp_parameters,
+  RtpTransportAdapter(const RtcpParameters& rtcp_params,
                       PacketTransportInterface* rtp,
                       PacketTransportInterface* rtcp,
                       RtpTransportControllerAdapter* rtp_transport_controller,
@@ -90,11 +90,11 @@
 
   PacketTransportInterface* rtp_packet_transport_;
   PacketTransportInterface* rtcp_packet_transport_;
-  RtpTransportControllerAdapter* rtp_transport_controller_;
+  RtpTransportControllerAdapter* const rtp_transport_controller_;
   // Non-null if this class owns the transport controller.
   std::unique_ptr<RtpTransportControllerInterface>
       owned_rtp_transport_controller_;
-  RtcpParameters rtcp_parameters_;
+  RtpTransportParameters parameters_;
 
   // SRTP specific members.
   rtc::Optional<cricket::CryptoParams> send_key_;
diff --git a/webrtc/ortc/rtptransportcontrolleradapter.cc b/webrtc/ortc/rtptransportcontrolleradapter.cc
index 5e0b621..f2ad995 100644
--- a/webrtc/ortc/rtptransportcontrolleradapter.cc
+++ b/webrtc/ortc/rtptransportcontrolleradapter.cc
@@ -129,11 +129,16 @@
 
 RTCErrorOr<std::unique_ptr<RtpTransportInterface>>
 RtpTransportControllerAdapter::CreateProxiedRtpTransport(
-    const RtcpParameters& rtcp_parameters,
+    const RtpTransportParameters& parameters,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp) {
-  auto result =
-      RtpTransportAdapter::CreateProxied(rtcp_parameters, rtp, rtcp, this);
+  if (!transport_proxies_.empty() && (parameters.keepalive != keepalive_)) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
+                         "Cannot create RtpTransport with different keep-alive "
+                         "from the RtpTransports already associated with this "
+                         "transport controller.");
+  }
+  auto result = RtpTransportAdapter::CreateProxied(parameters, rtp, rtcp, this);
   if (result.ok()) {
     transport_proxies_.push_back(result.value().get());
     transport_proxies_.back()->GetInternal()->SignalDestroyed.connect(
@@ -144,11 +149,11 @@
 
 RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>
 RtpTransportControllerAdapter::CreateProxiedSrtpTransport(
-    const RtcpParameters& rtcp_parameters,
+    const RtpTransportParameters& parameters,
     PacketTransportInterface* rtp,
     PacketTransportInterface* rtcp) {
   auto result =
-      RtpTransportAdapter::CreateSrtpProxied(rtcp_parameters, rtp, rtcp, this);
+      RtpTransportAdapter::CreateSrtpProxied(parameters, rtp, rtcp, this);
   if (result.ok()) {
     transport_proxies_.push_back(result.value().get());
     transport_proxies_.back()->GetInternal()->SignalDestroyed.connect(
@@ -219,12 +224,26 @@
   return transport_proxies_;
 }
 
-RTCError RtpTransportControllerAdapter::SetRtcpParameters(
-    const RtcpParameters& parameters,
+RTCError RtpTransportControllerAdapter::SetRtpTransportParameters(
+    const RtpTransportParameters& parameters,
     RtpTransportInterface* inner_transport) {
+  if ((video_channel_ != nullptr || voice_channel_ != nullptr) &&
+      (parameters.keepalive != keepalive_)) {
+    LOG_AND_RETURN_ERROR(RTCErrorType::INVALID_MODIFICATION,
+                         "Cannot change keep-alive settings after creating "
+                         "media streams or additional transports for the same "
+                         "transport controller.");
+  }
+  // Call must be configured on the worker thread.
+  worker_thread_->Invoke<void>(
+      RTC_FROM_HERE,
+      rtc::Bind(&RtpTransportControllerAdapter::SetRtpTransportParameters_w,
+                this, parameters));
+
   do {
     if (inner_transport == inner_audio_transport_) {
-      CopyRtcpParametersToDescriptions(parameters, &local_audio_description_,
+      CopyRtcpParametersToDescriptions(parameters.rtcp,
+                                       &local_audio_description_,
                                        &remote_audio_description_);
       if (!voice_channel_->SetLocalContent(&local_audio_description_,
                                            cricket::CA_OFFER, nullptr)) {
@@ -235,7 +254,8 @@
         break;
       }
     } else if (inner_transport == inner_video_transport_) {
-      CopyRtcpParametersToDescriptions(parameters, &local_video_description_,
+      CopyRtcpParametersToDescriptions(parameters.rtcp,
+                                       &local_video_description_,
                                        &remote_video_description_);
       if (!video_channel_->SetLocalContent(&local_video_description_,
                                            cricket::CA_OFFER, nullptr)) {
@@ -252,6 +272,11 @@
                        "Failed to apply new RTCP parameters.");
 }
 
+void RtpTransportControllerAdapter::SetRtpTransportParameters_w(
+    const RtpTransportParameters& parameters) {
+  call_send_rtp_transport_controller_->SetKeepAliveConfig(parameters.keepalive);
+}
+
 RTCError RtpTransportControllerAdapter::ValidateAndApplyAudioSenderParameters(
     const RtpParameters& parameters,
     uint32_t* primary_ssrc) {
@@ -270,7 +295,7 @@
   }
 
   auto stream_params_result = MakeSendStreamParamsVec(
-      parameters.encodings, inner_audio_transport_->GetRtcpParameters().cname,
+      parameters.encodings, inner_audio_transport_->GetParameters().rtcp.cname,
       local_audio_description_);
   if (!stream_params_result.ok()) {
     return stream_params_result.MoveError();
@@ -359,7 +384,7 @@
   }
 
   auto stream_params_result = MakeSendStreamParamsVec(
-      parameters.encodings, inner_video_transport_->GetRtcpParameters().cname,
+      parameters.encodings, inner_video_transport_->GetParameters().rtcp.cname,
       local_video_description_);
   if (!stream_params_result.ok()) {
     return stream_params_result.MoveError();
@@ -590,7 +615,8 @@
       worker_thread_(worker_thread),
       media_config_(config),
       channel_manager_(channel_manager),
-      event_log_(event_log) {
+      event_log_(event_log),
+      call_send_rtp_transport_controller_(nullptr) {
   RTC_DCHECK_RUN_ON(signaling_thread_);
   RTC_DCHECK(channel_manager_);
   // Add "dummy" codecs to the descriptions, because the media engines
@@ -626,11 +652,16 @@
   call_config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
   call_config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;
 
-  call_.reset(webrtc::Call::Create(call_config));
+  call_send_rtp_transport_controller_ =
+      new RtpTransportControllerSend(Clock::GetRealTimeClock(), event_log_);
+  call_.reset(webrtc::Call::Create(
+      call_config, std::unique_ptr<RtpTransportControllerSendInterface>(
+                       call_send_rtp_transport_controller_)));
 }
 
 void RtpTransportControllerAdapter::Close_w() {
   call_.reset();
+  call_send_rtp_transport_controller_ = nullptr;
 }
 
 RTCError RtpTransportControllerAdapter::AttachAudioSender(
@@ -656,7 +687,7 @@
   // If setting new transport, extract its RTCP parameters and create voice
   // channel.
   if (!inner_audio_transport_) {
-    CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
+    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                      &local_audio_description_,
                                      &remote_audio_description_);
     inner_audio_transport_ = inner_transport;
@@ -691,7 +722,7 @@
   // If setting new transport, extract its RTCP parameters and create video
   // channel.
   if (!inner_video_transport_) {
-    CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
+    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                      &local_video_description_,
                                      &remote_video_description_);
     inner_video_transport_ = inner_transport;
@@ -726,7 +757,7 @@
   // If setting new transport, extract its RTCP parameters and create voice
   // channel.
   if (!inner_audio_transport_) {
-    CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
+    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                      &local_audio_description_,
                                      &remote_audio_description_);
     inner_audio_transport_ = inner_transport;
@@ -761,7 +792,7 @@
   // If setting new transport, extract its RTCP parameters and create video
   // channel.
   if (!inner_video_transport_) {
-    CopyRtcpParametersToDescriptions(inner_transport->GetRtcpParameters(),
+    CopyRtcpParametersToDescriptions(inner_transport->GetParameters().rtcp,
                                      &local_video_description_,
                                      &remote_video_description_);
     inner_video_transport_ = inner_transport;
diff --git a/webrtc/ortc/rtptransportcontrolleradapter.h b/webrtc/ortc/rtptransportcontrolleradapter.h
index 9728c39..d4494d0 100644
--- a/webrtc/ortc/rtptransportcontrolleradapter.h
+++ b/webrtc/ortc/rtptransportcontrolleradapter.h
@@ -21,6 +21,7 @@
 #include "webrtc/api/ortc/rtptransportcontrollerinterface.h"
 #include "webrtc/api/ortc/srtptransportinterface.h"
 #include "webrtc/call/call.h"
+#include "webrtc/call/rtp_transport_controller_send.h"
 #include "webrtc/logging/rtc_event_log/rtc_event_log.h"
 #include "webrtc/media/base/mediachannel.h"  // For MediaConfig.
 #include "webrtc/pc/channelmanager.h"
@@ -77,12 +78,12 @@
   // these methods return proxies that will safely call methods on the correct
   // thread.
   RTCErrorOr<std::unique_ptr<RtpTransportInterface>> CreateProxiedRtpTransport(
-      const RtcpParameters& rtcp_parameters,
+      const RtpTransportParameters& rtcp_parameters,
       PacketTransportInterface* rtp,
       PacketTransportInterface* rtcp);
 
   RTCErrorOr<std::unique_ptr<SrtpTransportInterface>>
-  CreateProxiedSrtpTransport(const RtcpParameters& rtcp_parameters,
+  CreateProxiedSrtpTransport(const RtpTransportParameters& rtcp_parameters,
                              PacketTransportInterface* rtp,
                              PacketTransportInterface* rtcp);
 
@@ -100,8 +101,10 @@
   rtc::Thread* signaling_thread() const { return signaling_thread_; }
   rtc::Thread* worker_thread() const { return worker_thread_; }
 
-  RTCError SetRtcpParameters(const RtcpParameters& parameters,
-                             RtpTransportInterface* inner_transport);
+  // |parameters.keepalive| will be set for ALL RTP transports in the call.
+  RTCError SetRtpTransportParameters(const RtpTransportParameters& parameters,
+                                     RtpTransportInterface* inner_transport);
+  void SetRtpTransportParameters_w(const RtpTransportParameters& parameters);
 
   cricket::VoiceChannel* voice_channel() { return voice_channel_; }
   cricket::VideoChannel* video_channel() { return video_channel_; }
@@ -193,9 +196,11 @@
   RtpTransportInterface* inner_audio_transport_ = nullptr;
   RtpTransportInterface* inner_video_transport_ = nullptr;
   const cricket::MediaConfig media_config_;
+  RtpKeepAliveConfig keepalive_;
   cricket::ChannelManager* channel_manager_;
   webrtc::RtcEventLog* event_log_;
   std::unique_ptr<Call> call_;
+  webrtc::RtpTransportControllerSend* call_send_rtp_transport_controller_;
 
   // BaseChannel takes content descriptions as input, so we store them here
   // such that they can be updated when a new RtpSenderAdapter/
diff --git a/webrtc/ortc/srtptransport_unittest.cc b/webrtc/ortc/srtptransport_unittest.cc
index 69d8a29..ea9b28a 100644
--- a/webrtc/ortc/srtptransport_unittest.cc
+++ b/webrtc/ortc/srtptransport_unittest.cc
@@ -58,7 +58,7 @@
 
     fake_packet_transport_.reset(new rtc::FakePacketTransport("fake"));
     auto srtp_transport_result = ortc_factory_->CreateSrtpTransport(
-        rtcp_parameters_, fake_packet_transport_.get(), nullptr,
+        rtp_transport_parameters_, fake_packet_transport_.get(), nullptr,
         rtp_transport_controller_.get());
     srtp_transport_ = srtp_transport_result.MoveValue();
   }
@@ -69,7 +69,7 @@
   std::unique_ptr<OrtcFactoryInterface> ortc_factory_;
   std::unique_ptr<RtpTransportControllerInterface> rtp_transport_controller_;
   std::unique_ptr<SrtpTransportInterface> srtp_transport_;
-  RtcpParameters rtcp_parameters_;
+  RtpTransportParameters rtp_transport_parameters_;
   std::unique_ptr<rtc::FakePacketTransport> fake_packet_transport_;
 };
 
diff --git a/webrtc/ortc/testrtpparameters.h b/webrtc/ortc/testrtpparameters.h
index 87108ca..042dab2 100644
--- a/webrtc/ortc/testrtpparameters.h
+++ b/webrtc/ortc/testrtpparameters.h
@@ -30,10 +30,10 @@
 // parameters is applied properly should construct the parameters in the test
 // itself.
 
-inline RtcpParameters MakeRtcpMuxParameters() {
-  RtcpParameters rtcp_parameters;
-  rtcp_parameters.mux = true;
-  return rtcp_parameters;
+inline RtpTransportParameters MakeRtcpMuxParameters() {
+  RtpTransportParameters parameters;
+  parameters.rtcp.mux = true;
+  return parameters;
 }
 
 RtpParameters MakeMinimalOpusParameters();