Remove SetLatency/GetLatency from MediaSourceInterface API level

Bug: webrtc:10287
Change-Id: I74fad31db98b75791085688438064f9510b0b6fa
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/133165
Commit-Queue: Ruslan Burakov <kuddai@google.com>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27692}
diff --git a/api/media_stream_interface.cc b/api/media_stream_interface.cc
index cf994cb..73566c4 100644
--- a/api/media_stream_interface.cc
+++ b/api/media_stream_interface.cc
@@ -32,8 +32,4 @@
   return {};
 }
 
-double MediaSourceInterface::GetLatency() const {
-  return 0.0;
-}
-
 }  // namespace webrtc
diff --git a/api/media_stream_interface.h b/api/media_stream_interface.h
index ccacb4c..f4ea4a6 100644
--- a/api/media_stream_interface.h
+++ b/api/media_stream_interface.h
@@ -62,13 +62,6 @@
 
   virtual bool remote() const = 0;
 
-  // Sets the minimum latency of the remote source until audio playout. Actual
-  // observered latency may differ depending on the source. |latency| is in the
-  // range of [0.0, 10.0] seconds.
-  // TODO(kuddai) make pure virtual once not only remote tracks support latency.
-  virtual void SetLatency(double latency) {}
-  virtual double GetLatency() const;
-
  protected:
   ~MediaSourceInterface() override = default;
 };
diff --git a/api/rtp_receiver_interface.cc b/api/rtp_receiver_interface.cc
index 615a31d..52f72df 100644
--- a/api/rtp_receiver_interface.cc
+++ b/api/rtp_receiver_interface.cc
@@ -58,7 +58,4 @@
   return nullptr;
 }
 
-void RtpReceiverInterface::SetJitterBufferMinimumDelay(
-    absl::optional<double> delay_seconds) {}
-
 }  // namespace webrtc
diff --git a/api/rtp_receiver_interface.h b/api/rtp_receiver_interface.h
index d1ef137..3934215 100644
--- a/api/rtp_receiver_interface.h
+++ b/api/rtp_receiver_interface.h
@@ -131,10 +131,9 @@
   // Sets the jitter buffer minimum delay until media playout. Actual observed
   // delay may differ depending on the congestion control. |delay_seconds| is a
   // positive value including 0.0 measured in seconds. |nullopt| means default
-  // value must be used. TODO(kuddai): remove the default implmenetation once
-  // the subclasses in Chromium implement this.
+  // value must be used.
   virtual void SetJitterBufferMinimumDelay(
-      absl::optional<double> delay_seconds);
+      absl::optional<double> delay_seconds) = 0;
 
   // TODO(zhihuang): Remove the default implementation once the subclasses
   // implement this. Currently, the only relevant subclass is the
diff --git a/api/video_track_source_proxy.h b/api/video_track_source_proxy.h
index eb11bef..820cdcb 100644
--- a/api/video_track_source_proxy.h
+++ b/api/video_track_source_proxy.h
@@ -32,8 +32,6 @@
                      rtc::VideoSinkInterface<VideoFrame>*,
                      const rtc::VideoSinkWants&)
 PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface<VideoFrame>*)
-PROXY_WORKER_METHOD1(void, SetLatency, double)
-PROXY_WORKER_CONSTMETHOD0(double, GetLatency)
 PROXY_METHOD1(void, RegisterObserver, ObserverInterface*)
 PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*)
 END_PROXY_MAP()
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index 5ff4b16..16973e4 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -135,6 +135,10 @@
     "dtmf_sender.h",
     "ice_server_parsing.cc",
     "ice_server_parsing.h",
+    "jitter_buffer_delay.cc",
+    "jitter_buffer_delay.h",
+    "jitter_buffer_delay_interface.h",
+    "jitter_buffer_delay_proxy.h",
     "jsep_ice_candidate.cc",
     "jsep_session_description.cc",
     "local_audio_source.cc",
@@ -149,10 +153,6 @@
     "peer_connection_factory.cc",
     "peer_connection_factory.h",
     "peer_connection_internal.h",
-    "playout_latency.cc",
-    "playout_latency.h",
-    "playout_latency_interface.h",
-    "playout_latency_proxy.h",
     "remote_audio_source.cc",
     "remote_audio_source.h",
     "rtc_stats_collector.cc",
@@ -447,6 +447,7 @@
       "data_channel_unittest.cc",
       "dtmf_sender_unittest.cc",
       "ice_server_parsing_unittest.cc",
+      "jitter_buffer_delay_unittest.cc",
       "jsep_session_description_unittest.cc",
       "local_audio_source_unittest.cc",
       "media_stream_unittest.cc",
@@ -466,7 +467,6 @@
       "peer_connection_simulcast_unittest.cc",
       "peer_connection_wrapper.cc",
       "peer_connection_wrapper.h",
-      "playout_latency_unittest.cc",
       "proxy_unittest.cc",
       "rtc_stats_collector_unittest.cc",
       "rtc_stats_integrationtest.cc",
diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc
index 61ea340..a470707 100644
--- a/pc/audio_rtp_receiver.cc
+++ b/pc/audio_rtp_receiver.cc
@@ -17,6 +17,8 @@
 #include "api/media_stream_proxy.h"
 #include "api/media_stream_track_proxy.h"
 #include "pc/audio_track.h"
+#include "pc/jitter_buffer_delay.h"
+#include "pc/jitter_buffer_delay_proxy.h"
 #include "pc/media_stream.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
@@ -25,10 +27,6 @@
 
 namespace webrtc {
 
-namespace {
-constexpr double kDefaultLatency = 0.0;
-}  // namespace
-
 AudioRtpReceiver::AudioRtpReceiver(rtc::Thread* worker_thread,
                                    std::string receiver_id,
                                    std::vector<std::string> stream_ids)
@@ -46,7 +44,11 @@
       track_(AudioTrackProxy::Create(rtc::Thread::Current(),
                                      AudioTrack::Create(receiver_id, source_))),
       cached_track_enabled_(track_->enabled()),
-      attachment_id_(GenerateUniqueId()) {
+      attachment_id_(GenerateUniqueId()),
+      delay_(JitterBufferDelayProxy::Create(
+          rtc::Thread::Current(),
+          worker_thread_,
+          new rtc::RefCountedObject<JitterBufferDelay>(worker_thread))) {
   RTC_DCHECK(worker_thread_);
   RTC_DCHECK(track_->GetSource()->remote());
   track_->RegisterObserver(this);
@@ -162,9 +164,11 @@
   }
   if (ssrc_) {
     source_->Stop(media_channel_, *ssrc_);
+    delay_->OnStop();
   }
   ssrc_ = ssrc;
   source_->Start(media_channel_, *ssrc_);
+  delay_->OnStart(media_channel_, *ssrc_);
   Reconfigure();
 }
 
@@ -238,7 +242,7 @@
 
 void AudioRtpReceiver::SetJitterBufferMinimumDelay(
     absl::optional<double> delay_seconds) {
-  source_->SetLatency(delay_seconds.value_or(kDefaultLatency));
+  delay_->Set(delay_seconds);
 }
 
 void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
diff --git a/pc/audio_rtp_receiver.h b/pc/audio_rtp_receiver.h
index 9ad5c61..bc80fbe 100644
--- a/pc/audio_rtp_receiver.h
+++ b/pc/audio_rtp_receiver.h
@@ -22,6 +22,7 @@
 #include "api/rtp_parameters.h"
 #include "api/scoped_refptr.h"
 #include "media/base/media_channel.h"
+#include "pc/jitter_buffer_delay_interface.h"
 #include "pc/remote_audio_source.h"
 #include "pc/rtp_receiver.h"
 #include "rtc_base/ref_counted_object.h"
@@ -122,6 +123,9 @@
   int attachment_id_ = 0;
   rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
   rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+  // Allows to thread safely change playout delay. Handles caching cases if
+  // |SetJitterBufferMinimumDelay| is called before start.
+  rtc::scoped_refptr<JitterBufferDelayInterface> delay_;
 };
 
 }  // namespace webrtc
diff --git a/pc/jitter_buffer_delay.cc b/pc/jitter_buffer_delay.cc
new file mode 100644
index 0000000..c9506b3
--- /dev/null
+++ b/pc/jitter_buffer_delay.cc
@@ -0,0 +1,67 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "pc/jitter_buffer_delay.h"
+
+#include "rtc_base/checks.h"
+#include "rtc_base/location.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/numerics/safe_minmax.h"
+#include "rtc_base/thread.h"
+#include "rtc_base/thread_checker.h"
+
+namespace {
+constexpr int kDefaultDelay = 0;
+constexpr int kMaximumDelayMs = 10000;
+}  // namespace
+
+namespace webrtc {
+
+JitterBufferDelay::JitterBufferDelay(rtc::Thread* worker_thread)
+    : signaling_thread_(rtc::Thread::Current()), worker_thread_(worker_thread) {
+  RTC_DCHECK(worker_thread_);
+}
+
+void JitterBufferDelay::OnStart(cricket::Delayable* media_channel,
+                                uint32_t ssrc) {
+  RTC_DCHECK_RUN_ON(signaling_thread_);
+
+  media_channel_ = media_channel;
+  ssrc_ = ssrc;
+
+  // Trying to apply cached delay for the audio stream.
+  if (cached_delay_seconds_) {
+    Set(cached_delay_seconds_.value());
+  }
+}
+
+void JitterBufferDelay::OnStop() {
+  RTC_DCHECK_RUN_ON(signaling_thread_);
+  // Assume that audio stream is no longer present.
+  media_channel_ = nullptr;
+  ssrc_ = absl::nullopt;
+}
+
+void JitterBufferDelay::Set(absl::optional<double> delay_seconds) {
+  RTC_DCHECK_RUN_ON(worker_thread_);
+
+  // TODO(kuddai) propagate absl::optional deeper down as default preference.
+  int delay_ms =
+      rtc::saturated_cast<int>(delay_seconds.value_or(kDefaultDelay) * 1000);
+  delay_ms = rtc::SafeClamp(delay_ms, 0, kMaximumDelayMs);
+
+  cached_delay_seconds_ = delay_seconds;
+  if (media_channel_ && ssrc_) {
+    media_channel_->SetBaseMinimumPlayoutDelayMs(ssrc_.value(), delay_ms);
+  }
+}
+
+}  // namespace webrtc
diff --git a/pc/jitter_buffer_delay.h b/pc/jitter_buffer_delay.h
new file mode 100644
index 0000000..8edfc6c
--- /dev/null
+++ b/pc/jitter_buffer_delay.h
@@ -0,0 +1,51 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef PC_JITTER_BUFFER_DELAY_H_
+#define PC_JITTER_BUFFER_DELAY_H_
+
+#include <stdint.h>
+
+#include "absl/types/optional.h"
+#include "media/base/delayable.h"
+#include "pc/jitter_buffer_delay_interface.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+
+// JitterBufferDelay converts delay from seconds to milliseconds for the
+// underlying media channel. It also handles cases when user sets delay before
+// the start of media_channel by caching its request. Note, this class is not
+// thread safe. Its thread safe version is defined in
+// pc/jitter_buffer_delay_proxy.h
+class JitterBufferDelay : public JitterBufferDelayInterface {
+ public:
+  // Must be called on signaling thread.
+  explicit JitterBufferDelay(rtc::Thread* worker_thread);
+
+  void OnStart(cricket::Delayable* media_channel, uint32_t ssrc) override;
+
+  void OnStop() override;
+
+  void Set(absl::optional<double> delay_seconds) override;
+
+ private:
+  // Throughout webrtc source, sometimes it is also called as |main_thread_|.
+  rtc::Thread* const signaling_thread_;
+  rtc::Thread* const worker_thread_;
+  // Media channel and ssrc together uniqely identify audio stream.
+  cricket::Delayable* media_channel_ = nullptr;
+  absl::optional<uint32_t> ssrc_;
+  absl::optional<double> cached_delay_seconds_;
+};
+
+}  // namespace webrtc
+
+#endif  // PC_JITTER_BUFFER_DELAY_H_
diff --git a/pc/jitter_buffer_delay_interface.h b/pc/jitter_buffer_delay_interface.h
new file mode 100644
index 0000000..f2132d3
--- /dev/null
+++ b/pc/jitter_buffer_delay_interface.h
@@ -0,0 +1,39 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef PC_JITTER_BUFFER_DELAY_INTERFACE_H_
+#define PC_JITTER_BUFFER_DELAY_INTERFACE_H_
+
+#include <stdint.h>
+
+#include "absl/types/optional.h"
+#include "media/base/delayable.h"
+#include "rtc_base/ref_count.h"
+
+namespace webrtc {
+
+// JitterBufferDelay delivers user's queries to the underlying media channel. It
+// can describe either video or audio delay for receiving stream. "Interface"
+// suffix in the interface name is required to be compatible with api/proxy.cc
+class JitterBufferDelayInterface : public rtc::RefCountInterface {
+ public:
+  // OnStart allows to uniqely identify to which receiving stream playout
+  // delay must correpond through |media_channel| and |ssrc| pair.
+  virtual void OnStart(cricket::Delayable* media_channel, uint32_t ssrc) = 0;
+
+  // Indicates that underlying receiving stream is stopped.
+  virtual void OnStop() = 0;
+
+  virtual void Set(absl::optional<double> delay_seconds) = 0;
+};
+
+}  // namespace webrtc
+
+#endif  // PC_JITTER_BUFFER_DELAY_INTERFACE_H_
diff --git a/pc/playout_latency_proxy.h b/pc/jitter_buffer_delay_proxy.h
similarity index 70%
rename from pc/playout_latency_proxy.h
rename to pc/jitter_buffer_delay_proxy.h
index 22f02c5..b3380fd 100644
--- a/pc/playout_latency_proxy.h
+++ b/pc/jitter_buffer_delay_proxy.h
@@ -8,25 +8,24 @@
  *  be found in the AUTHORS file in the root of the source tree.
  */
 
-#ifndef PC_PLAYOUT_LATENCY_PROXY_H_
-#define PC_PLAYOUT_LATENCY_PROXY_H_
+#ifndef PC_JITTER_BUFFER_DELAY_PROXY_H_
+#define PC_JITTER_BUFFER_DELAY_PROXY_H_
 
 #include <stdint.h>
 
 #include "api/proxy.h"
 #include "media/base/delayable.h"
-#include "pc/playout_latency_interface.h"
+#include "pc/jitter_buffer_delay_interface.h"
 
 namespace webrtc {
 
-BEGIN_PROXY_MAP(PlayoutLatency)
+BEGIN_PROXY_MAP(JitterBufferDelay)
 PROXY_SIGNALING_THREAD_DESTRUCTOR()
 PROXY_METHOD2(void, OnStart, cricket::Delayable*, uint32_t)
 PROXY_METHOD0(void, OnStop)
-PROXY_WORKER_METHOD1(void, SetLatency, double)
-PROXY_WORKER_CONSTMETHOD0(double, GetLatency)
+PROXY_WORKER_METHOD1(void, Set, absl::optional<double>)
 END_PROXY_MAP()
 
 }  // namespace webrtc
 
-#endif  // PC_PLAYOUT_LATENCY_PROXY_H_
+#endif  // PC_JITTER_BUFFER_DELAY_PROXY_H_
diff --git a/pc/jitter_buffer_delay_unittest.cc b/pc/jitter_buffer_delay_unittest.cc
new file mode 100644
index 0000000..383a4b7
--- /dev/null
+++ b/pc/jitter_buffer_delay_unittest.cc
@@ -0,0 +1,90 @@
+/*
+ *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
+ *
+ *  Use of this source code is governed by a BSD-style license
+ *  that can be found in the LICENSE file in the root of the source
+ *  tree. An additional intellectual property rights grant can be found
+ *  in the file PATENTS.  All contributing project authors may
+ *  be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdint.h>
+
+#include "absl/types/optional.h"
+#include "api/scoped_refptr.h"
+#include "pc/jitter_buffer_delay.h"
+#include "pc/test/mock_delayable.h"
+#include "rtc_base/ref_counted_object.h"
+#include "rtc_base/thread.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+using ::testing::Return;
+
+namespace {
+constexpr int kSsrc = 1234;
+}  // namespace
+
+namespace webrtc {
+
+class JitterBufferDelayTest : public ::testing::Test {
+ public:
+  JitterBufferDelayTest()
+      : delay_(new rtc::RefCountedObject<JitterBufferDelay>(
+            rtc::Thread::Current())) {}
+
+ protected:
+  rtc::scoped_refptr<JitterBufferDelayInterface> delay_;
+  MockDelayable delayable_;
+};
+
+TEST_F(JitterBufferDelayTest, Set) {
+  delay_->OnStart(&delayable_, kSsrc);
+
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 3000))
+      .WillOnce(Return(true));
+
+  // Delay in seconds.
+  delay_->Set(3.0);
+}
+
+TEST_F(JitterBufferDelayTest, Caching) {
+  // Check that value is cached before start.
+  delay_->Set(4.0);
+
+  // Check that cached value applied on the start.
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 4000))
+      .WillOnce(Return(true));
+  delay_->OnStart(&delayable_, kSsrc);
+}
+
+TEST_F(JitterBufferDelayTest, Clamping) {
+  delay_->OnStart(&delayable_, kSsrc);
+
+  // In current Jitter Buffer implementation (Audio or Video) maximum supported
+  // value is 10000 milliseconds.
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 10000))
+      .WillOnce(Return(true));
+  delay_->Set(10.5);
+
+  // Test int overflow.
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 10000))
+      .WillOnce(Return(true));
+  delay_->Set(21474836470.0);
+
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 0))
+      .WillOnce(Return(true));
+  delay_->Set(-21474836470.0);
+
+  // Boundary value in seconds to milliseconds conversion.
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 0))
+      .WillOnce(Return(true));
+  delay_->Set(0.0009);
+
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 0))
+      .WillOnce(Return(true));
+
+  delay_->Set(-2.0);
+}
+
+}  // namespace webrtc
diff --git a/pc/playout_latency.cc b/pc/playout_latency.cc
deleted file mode 100644
index 063f232..0000000
--- a/pc/playout_latency.cc
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include "pc/playout_latency.h"
-
-#include "rtc_base/checks.h"
-#include "rtc_base/location.h"
-#include "rtc_base/logging.h"
-#include "rtc_base/numerics/safe_conversions.h"
-#include "rtc_base/numerics/safe_minmax.h"
-#include "rtc_base/thread.h"
-#include "rtc_base/thread_checker.h"
-
-namespace {
-constexpr int kDefaultLatency = 0;
-constexpr int kMaximumDelayMs = 10000;
-}  // namespace
-
-namespace webrtc {
-
-PlayoutLatency::PlayoutLatency(rtc::Thread* worker_thread)
-    : signaling_thread_(rtc::Thread::Current()), worker_thread_(worker_thread) {
-  RTC_DCHECK(worker_thread_);
-}
-
-void PlayoutLatency::OnStart(cricket::Delayable* media_channel, uint32_t ssrc) {
-  RTC_DCHECK_RUN_ON(signaling_thread_);
-
-  media_channel_ = media_channel;
-  ssrc_ = ssrc;
-
-  // Trying to apply cached latency for the audio stream.
-  if (cached_latency_) {
-    SetLatency(cached_latency_.value());
-  }
-}
-
-void PlayoutLatency::OnStop() {
-  RTC_DCHECK_RUN_ON(signaling_thread_);
-  // Assume that audio stream is no longer present for latency calls.
-  media_channel_ = nullptr;
-  ssrc_ = absl::nullopt;
-}
-
-void PlayoutLatency::SetLatency(double latency) {
-  RTC_DCHECK_RUN_ON(worker_thread_);
-
-  int delay_ms = rtc::dchecked_cast<int>(latency * 1000);
-  delay_ms = rtc::SafeClamp(delay_ms, 0, kMaximumDelayMs);
-
-  cached_latency_ = latency;
-  if (media_channel_ && ssrc_) {
-    media_channel_->SetBaseMinimumPlayoutDelayMs(ssrc_.value(), delay_ms);
-  }
-}
-
-double PlayoutLatency::GetLatency() const {
-  RTC_DCHECK_RUN_ON(worker_thread_);
-
-  absl::optional<int> delay_ms;
-  if (media_channel_ && ssrc_) {
-    delay_ms = media_channel_->GetBaseMinimumPlayoutDelayMs(ssrc_.value());
-  }
-
-  if (delay_ms) {
-    return delay_ms.value() / 1000.0;
-  } else {
-    return cached_latency_.value_or(kDefaultLatency);
-  }
-}
-
-}  // namespace webrtc
diff --git a/pc/playout_latency.h b/pc/playout_latency.h
deleted file mode 100644
index f51a927..0000000
--- a/pc/playout_latency.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef PC_PLAYOUT_LATENCY_H_
-#define PC_PLAYOUT_LATENCY_H_
-
-#include <stdint.h>
-
-#include "absl/types/optional.h"
-#include "media/base/delayable.h"
-#include "pc/playout_latency_interface.h"
-#include "rtc_base/thread.h"
-
-namespace webrtc {
-
-// PlayoutLatency converts latency measured in seconds to delay measured in
-// milliseconds for the underlying media channel. It also handles cases when
-// user sets Latency before the start of media_channel by caching its request.
-// Note, this class is not thread safe. Its thread safe version is defined in
-// pc/playout_latency_proxy.h
-class PlayoutLatency : public PlayoutLatencyInterface {
- public:
-  // Must be called on signaling thread.
-  explicit PlayoutLatency(rtc::Thread* worker_thread);
-
-  void OnStart(cricket::Delayable* media_channel, uint32_t ssrc) override;
-
-  void OnStop() override;
-
-  void SetLatency(double latency) override;
-
-  double GetLatency() const override;
-
- private:
-  // Throughout webrtc source, sometimes it is also called as |main_thread_|.
-  rtc::Thread* const signaling_thread_;
-  rtc::Thread* const worker_thread_;
-  // Media channel and ssrc together uniqely identify audio stream.
-  cricket::Delayable* media_channel_ = nullptr;
-  absl::optional<uint32_t> ssrc_;
-  absl::optional<double> cached_latency_;
-};
-
-}  // namespace webrtc
-
-#endif  // PC_PLAYOUT_LATENCY_H_
diff --git a/pc/playout_latency_interface.h b/pc/playout_latency_interface.h
deleted file mode 100644
index e995733..0000000
--- a/pc/playout_latency_interface.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#ifndef PC_PLAYOUT_LATENCY_INTERFACE_H_
-#define PC_PLAYOUT_LATENCY_INTERFACE_H_
-
-#include <stdint.h>
-
-#include "media/base/delayable.h"
-#include "rtc_base/ref_count.h"
-
-namespace webrtc {
-
-// PlayoutLatency delivers user's latency queries to the underlying media
-// channel. It can describe either video or audio latency for receiving stream.
-// "Interface" suffix in the interface name is required to be compatible with
-// api/proxy.cc
-class PlayoutLatencyInterface : public rtc::RefCountInterface {
- public:
-  // OnStart allows to uniqely identify to which receiving stream playout
-  // latency must correpond through |media_channel| and |ssrc| pair.
-  virtual void OnStart(cricket::Delayable* media_channel, uint32_t ssrc) = 0;
-
-  // Indicates that underlying receiving stream is stopped.
-  virtual void OnStop() = 0;
-
-  // Sets latency in seconds.
-  virtual void SetLatency(double latency) = 0;
-
-  // Returns latency in seconds.
-  virtual double GetLatency() const = 0;
-};
-
-}  // namespace webrtc
-
-#endif  // PC_PLAYOUT_LATENCY_INTERFACE_H_
diff --git a/pc/playout_latency_unittest.cc b/pc/playout_latency_unittest.cc
deleted file mode 100644
index db139f4..0000000
--- a/pc/playout_latency_unittest.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- *  Copyright 2019 The WebRTC project authors. All Rights Reserved.
- *
- *  Use of this source code is governed by a BSD-style license
- *  that can be found in the LICENSE file in the root of the source
- *  tree. An additional intellectual property rights grant can be found
- *  in the file PATENTS.  All contributing project authors may
- *  be found in the AUTHORS file in the root of the source tree.
- */
-
-#include <stdint.h>
-
-#include "absl/types/optional.h"
-#include "api/scoped_refptr.h"
-#include "pc/playout_latency.h"
-#include "pc/test/mock_delayable.h"
-#include "rtc_base/ref_counted_object.h"
-#include "rtc_base/thread.h"
-#include "test/gmock.h"
-#include "test/gtest.h"
-
-using ::testing::Return;
-
-namespace {
-constexpr int kSsrc = 1234;
-}  // namespace
-
-namespace webrtc {
-
-class PlayoutLatencyTest : public ::testing::Test {
- public:
-  PlayoutLatencyTest()
-      : latency_(
-            new rtc::RefCountedObject<PlayoutLatency>(rtc::Thread::Current())) {
-  }
-
- protected:
-  rtc::scoped_refptr<PlayoutLatencyInterface> latency_;
-  MockDelayable delayable_;
-};
-
-TEST_F(PlayoutLatencyTest, DefaultValue) {
-  EXPECT_DOUBLE_EQ(0.0, latency_->GetLatency());
-}
-
-TEST_F(PlayoutLatencyTest, GetLatency) {
-  latency_->OnStart(&delayable_, kSsrc);
-
-  EXPECT_CALL(delayable_, GetBaseMinimumPlayoutDelayMs(kSsrc))
-      .WillOnce(Return(2000));
-  // Latency in seconds.
-  EXPECT_DOUBLE_EQ(2.0, latency_->GetLatency());
-
-  EXPECT_CALL(delayable_, GetBaseMinimumPlayoutDelayMs(kSsrc))
-      .WillOnce(Return(absl::nullopt));
-  // When no value is returned by GetBaseMinimumPlayoutDelayMs, and there are
-  // no caching, then return default value.
-  EXPECT_DOUBLE_EQ(0.0, latency_->GetLatency());
-}
-
-TEST_F(PlayoutLatencyTest, SetLatency) {
-  latency_->OnStart(&delayable_, kSsrc);
-
-  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 3000))
-      .WillOnce(Return(true));
-
-  // Latency in seconds.
-  latency_->SetLatency(3.0);
-}
-
-TEST_F(PlayoutLatencyTest, Caching) {
-  // Check that value is cached before start.
-  latency_->SetLatency(4.0);
-  // Latency in seconds.
-  EXPECT_DOUBLE_EQ(4.0, latency_->GetLatency());
-
-  // Check that cached value applied on the start.
-  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 4000))
-      .WillOnce(Return(true));
-  latency_->OnStart(&delayable_, kSsrc);
-
-  EXPECT_CALL(delayable_, GetBaseMinimumPlayoutDelayMs(kSsrc))
-      .WillOnce(Return(absl::nullopt));
-  // On false the latest cached value is returned.
-  EXPECT_DOUBLE_EQ(4.0, latency_->GetLatency());
-
-  latency_->OnStop();
-
-  // Check that after stop it returns last cached value.
-  EXPECT_DOUBLE_EQ(4.0, latency_->GetLatency());
-}
-
-TEST_F(PlayoutLatencyTest, Clamping) {
-  latency_->OnStart(&delayable_, kSsrc);
-
-  // In current Jitter Buffer implementation (Audio or Video) maximum supported
-  // value is 10000 milliseconds.
-  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 10000))
-      .WillOnce(Return(true));
-  latency_->SetLatency(10.5);
-
-  // Boundary value in seconds to milliseconds conversion.
-  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 0))
-      .WillOnce(Return(true));
-  latency_->SetLatency(0.0009);
-
-  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 0))
-      .WillOnce(Return(true));
-
-  latency_->SetLatency(-2.0);
-}
-
-}  // namespace webrtc
diff --git a/pc/remote_audio_source.cc b/pc/remote_audio_source.cc
index aba4400..ed8ef2d 100644
--- a/pc/remote_audio_source.cc
+++ b/pc/remote_audio_source.cc
@@ -16,8 +16,6 @@
 #include "absl/algorithm/container.h"
 #include "absl/memory/memory.h"
 #include "api/scoped_refptr.h"
-#include "pc/playout_latency.h"
-#include "pc/playout_latency_proxy.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/constructor_magic.h"
 #include "rtc_base/location.h"
@@ -52,11 +50,7 @@
 RemoteAudioSource::RemoteAudioSource(rtc::Thread* worker_thread)
     : main_thread_(rtc::Thread::Current()),
       worker_thread_(worker_thread),
-      state_(MediaSourceInterface::kLive),
-      latency_(PlayoutLatencyProxy::Create(
-          main_thread_,
-          worker_thread_,
-          new rtc::RefCountedObject<PlayoutLatency>(worker_thread))) {
+      state_(MediaSourceInterface::kLive) {
   RTC_DCHECK(main_thread_);
   RTC_DCHECK(worker_thread_);
 }
@@ -79,9 +73,6 @@
     media_channel->SetRawAudioSink(ssrc,
                                    absl::make_unique<AudioDataProxy>(this));
   });
-
-  // Apply latency to the audio stream if |SetLatency| was called before.
-  latency_->OnStart(media_channel, ssrc);
 }
 
 void RemoteAudioSource::Stop(cricket::VoiceMediaChannel* media_channel,
@@ -89,8 +80,6 @@
   RTC_DCHECK_RUN_ON(main_thread_);
   RTC_DCHECK(media_channel);
 
-  latency_->OnStop();
-
   worker_thread_->Invoke<void>(
       RTC_FROM_HERE, [&] { media_channel->SetRawAudioSink(ssrc, nullptr); });
 }
@@ -113,14 +102,6 @@
   }
 }
 
-void RemoteAudioSource::SetLatency(double latency) {
-  latency_->SetLatency(latency);
-}
-
-double RemoteAudioSource::GetLatency() const {
-  return latency_->GetLatency();
-}
-
 void RemoteAudioSource::RegisterAudioObserver(AudioObserver* observer) {
   RTC_DCHECK(observer != NULL);
   RTC_DCHECK(!absl::c_linear_search(audio_observers_, observer));
diff --git a/pc/remote_audio_source.h b/pc/remote_audio_source.h
index f4a5ec8..399e7e3 100644
--- a/pc/remote_audio_source.h
+++ b/pc/remote_audio_source.h
@@ -17,7 +17,6 @@
 #include "api/call/audio_sink.h"
 #include "api/notifier.h"
 #include "pc/channel.h"
-#include "pc/playout_latency_interface.h"
 #include "rtc_base/critical_section.h"
 #include "rtc_base/message_handler.h"
 
@@ -47,8 +46,6 @@
 
   // AudioSourceInterface implementation.
   void SetVolume(double volume) override;
-  void SetLatency(double latency) override;
-  double GetLatency() const override;
   void RegisterAudioObserver(AudioObserver* observer) override;
   void UnregisterAudioObserver(AudioObserver* observer) override;
 
@@ -72,9 +69,6 @@
   rtc::CriticalSection sink_lock_;
   std::list<AudioTrackSinkInterface*> sinks_;
   SourceState state_;
-  // Allows to thread safely change playout latency. Handles caching cases if
-  // |SetLatency| is called before start.
-  rtc::scoped_refptr<PlayoutLatencyInterface> latency_;
 };
 
 }  // namespace webrtc
diff --git a/pc/rtp_sender_receiver_unittest.cc b/pc/rtp_sender_receiver_unittest.cc
index 67cbe2c..90ca03f 100644
--- a/pc/rtp_sender_receiver_unittest.cc
+++ b/pc/rtp_sender_receiver_unittest.cc
@@ -459,41 +459,6 @@
     RunSetLastLayerAsInactiveTest(video_rtp_sender_.get());
   }
 
-  void VerifyTrackLatencyBehaviour(cricket::Delayable* media_channel,
-                                   MediaStreamTrackInterface* track,
-                                   MediaSourceInterface* source,
-                                   uint32_t ssrc) {
-    absl::optional<int> delay_ms;  // In milliseconds.
-    double latency_s = 0.5;        // In seconds.
-
-    source->SetLatency(latency_s);
-    delay_ms = media_channel->GetBaseMinimumPlayoutDelayMs(ssrc);
-    EXPECT_DOUBLE_EQ(latency_s, delay_ms.value_or(0) / 1000.0);
-
-    // Disabling the track should take no effect on previously set value.
-    track->set_enabled(false);
-    delay_ms = media_channel->GetBaseMinimumPlayoutDelayMs(ssrc);
-    EXPECT_DOUBLE_EQ(latency_s, delay_ms.value_or(0) / 1000.0);
-
-    // When the track is disabled, we still should be able to set latency.
-    latency_s = 0.3;
-    source->SetLatency(latency_s);
-    delay_ms = media_channel->GetBaseMinimumPlayoutDelayMs(ssrc);
-    EXPECT_DOUBLE_EQ(latency_s, delay_ms.value_or(0) / 1000.0);
-
-    // Enabling the track should take no effect on previously set value.
-    track->set_enabled(true);
-    delay_ms = media_channel->GetBaseMinimumPlayoutDelayMs(ssrc);
-    EXPECT_DOUBLE_EQ(latency_s, delay_ms.value_or(0) / 1000.0);
-
-    // We still should be able to change latency.
-    latency_s = 0.0;
-    source->SetLatency(latency_s);
-    delay_ms = media_channel->GetBaseMinimumPlayoutDelayMs(ssrc);
-    EXPECT_EQ(0, delay_ms.value_or(-1));
-    EXPECT_DOUBLE_EQ(latency_s, delay_ms.value_or(0) / 1000.0);
-  }
-
   // Check that minimum Jitter Buffer delay is propagated to the underlying
   // |media_channel|.
   void VerifyRtpReceiverDelayBehaviour(cricket::Delayable* media_channel,
@@ -687,44 +652,10 @@
   DestroyAudioRtpReceiver();
 }
 
-TEST_F(RtpSenderReceiverTest, RemoteAudioSourceLatency) {
-  absl::optional<int> delay_ms;  // In milliseconds.
-  rtc::scoped_refptr<RemoteAudioSource> source =
-      new rtc::RefCountedObject<RemoteAudioSource>(rtc::Thread::Current());
-
-  // Set it to value different from default zero.
-  voice_media_channel_->SetBaseMinimumPlayoutDelayMs(kAudioSsrc, 300);
-
-  // Check that calling GetLatency on the source that hasn't been started yet
-  // won't trigger caching and return default value.
-  EXPECT_DOUBLE_EQ(source->GetLatency(), 0);
-
-  // Check that cached latency will be applied on start.
-  source->SetLatency(0.4);
-  EXPECT_DOUBLE_EQ(source->GetLatency(), 0.4);
-  source->Start(voice_media_channel_, kAudioSsrc);
-  delay_ms = voice_media_channel_->GetBaseMinimumPlayoutDelayMs(kAudioSsrc);
-  EXPECT_EQ(400, delay_ms);
-}
-
-TEST_F(RtpSenderReceiverTest, RemoteAudioTrackLatency) {
-  CreateAudioRtpReceiver();
-  VerifyTrackLatencyBehaviour(voice_media_channel_, audio_track_.get(),
-                              audio_track_->GetSource(), kAudioSsrc);
-}
-
-TEST_F(RtpSenderReceiverTest, RemoteVideoTrackLatency) {
-  CreateVideoRtpReceiver();
-  VerifyTrackLatencyBehaviour(video_media_channel_, video_track_.get(),
-                              video_track_->GetSource(), kVideoSsrc);
-}
-
 TEST_F(RtpSenderReceiverTest, AudioRtpReceiverDelay) {
   CreateAudioRtpReceiver();
   VerifyRtpReceiverDelayBehaviour(voice_media_channel_,
                                   audio_rtp_receiver_.get(), kAudioSsrc);
-  VerifyTrackLatencyBehaviour(voice_media_channel_, audio_track_.get(),
-                              audio_track_->GetSource(), kAudioSsrc);
 }
 
 TEST_F(RtpSenderReceiverTest, VideoRtpReceiverDelay) {
diff --git a/pc/video_rtp_receiver.cc b/pc/video_rtp_receiver.cc
index 5a2e778..7a9ec98 100644
--- a/pc/video_rtp_receiver.cc
+++ b/pc/video_rtp_receiver.cc
@@ -17,6 +17,8 @@
 #include "api/media_stream_proxy.h"
 #include "api/media_stream_track_proxy.h"
 #include "api/video_track_source_proxy.h"
+#include "pc/jitter_buffer_delay.h"
+#include "pc/jitter_buffer_delay_proxy.h"
 #include "pc/media_stream.h"
 #include "pc/video_track.h"
 #include "rtc_base/checks.h"
@@ -26,10 +28,6 @@
 
 namespace webrtc {
 
-namespace {
-constexpr double kDefaultLatency = 0.0;
-}  // namespace
-
 VideoRtpReceiver::VideoRtpReceiver(rtc::Thread* worker_thread,
                                    std::string receiver_id,
                                    std::vector<std::string> stream_ids)
@@ -43,7 +41,7 @@
     const std::vector<rtc::scoped_refptr<MediaStreamInterface>>& streams)
     : worker_thread_(worker_thread),
       id_(receiver_id),
-      source_(new RefCountedObject<VideoRtpTrackSource>(worker_thread_)),
+      source_(new RefCountedObject<VideoRtpTrackSource>()),
       track_(VideoTrackProxy::Create(
           rtc::Thread::Current(),
           worker_thread,
@@ -53,7 +51,11 @@
                                             worker_thread,
                                             source_),
               worker_thread))),
-      attachment_id_(GenerateUniqueId()) {
+      attachment_id_(GenerateUniqueId()),
+      delay_(JitterBufferDelayProxy::Create(
+          rtc::Thread::Current(),
+          worker_thread,
+          new rtc::RefCountedObject<JitterBufferDelay>(worker_thread))) {
   RTC_DCHECK(worker_thread_);
   SetStreams(streams);
   source_->SetState(MediaSourceInterface::kLive);
@@ -127,7 +129,7 @@
     // media channel has already been deleted.
     SetSink(nullptr);
   }
-  source_->Stop();
+  delay_->OnStop();
   stopped_ = true;
 }
 
@@ -148,7 +150,7 @@
   MaybeAttachFrameDecryptorToMediaChannel(
       ssrc_, worker_thread_, frame_decryptor_, media_channel_, stopped_);
 
-  source_->Start(media_channel_, ssrc);
+  delay_->OnStart(media_channel_, ssrc);
 }
 
 void VideoRtpReceiver::set_stream_ids(std::vector<std::string> stream_ids) {
@@ -198,7 +200,7 @@
 
 void VideoRtpReceiver::SetJitterBufferMinimumDelay(
     absl::optional<double> delay_seconds) {
-  source_->SetLatency(delay_seconds.value_or(kDefaultLatency));
+  delay_->Set(delay_seconds);
 }
 
 void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
diff --git a/pc/video_rtp_receiver.h b/pc/video_rtp_receiver.h
index 9ad4fe7..10354b0 100644
--- a/pc/video_rtp_receiver.h
+++ b/pc/video_rtp_receiver.h
@@ -27,8 +27,7 @@
 #include "api/video/video_source_interface.h"
 #include "media/base/media_channel.h"
 #include "media/base/video_broadcaster.h"
-#include "pc/playout_latency.h"
-#include "pc/playout_latency_proxy.h"
+#include "pc/jitter_buffer_delay_interface.h"
 #include "pc/rtp_receiver.h"
 #include "pc/video_track_source.h"
 #include "rtc_base/ref_counted_object.h"
@@ -108,42 +107,23 @@
 
   std::vector<RtpSource> GetSources() const override;
 
+ private:
   class VideoRtpTrackSource : public VideoTrackSource {
    public:
-    explicit VideoRtpTrackSource(rtc::Thread* worker_thread)
-        : VideoTrackSource(true /* remote */),
-          latency_(PlayoutLatencyProxy::Create(
-              rtc::Thread::Current(),
-              worker_thread,
-              new rtc::RefCountedObject<PlayoutLatency>(worker_thread))) {}
+    VideoRtpTrackSource() : VideoTrackSource(true /* remote */) {}
 
     rtc::VideoSourceInterface<VideoFrame>* source() override {
       return &broadcaster_;
     }
     rtc::VideoSinkInterface<VideoFrame>* sink() { return &broadcaster_; }
 
-    void SetLatency(double latency) override { latency_->SetLatency(latency); }
-
-    void Start(cricket::VideoMediaChannel* media_channel, uint32_t ssrc) {
-      latency_->OnStart(media_channel, ssrc);
-    }
-
-    void Stop() { latency_->OnStop(); }
-
-    double GetLatency() const override { return latency_->GetLatency(); }
-
    private:
-    // Allows to thread safely change playout latency. Handles caching cases if
-    // |SetLatency| is called before start.
-    rtc::scoped_refptr<PlayoutLatencyInterface> latency_;
-
     // |broadcaster_| is needed since the decoder can only handle one sink.
     // It might be better if the decoder can handle multiple sinks and consider
     // the VideoSinkWants.
     rtc::VideoBroadcaster broadcaster_;
   };
 
- private:
   bool SetSink(rtc::VideoSinkInterface<VideoFrame>* sink);
 
   rtc::Thread* const worker_thread_;
@@ -161,6 +141,9 @@
   int attachment_id_ = 0;
   rtc::scoped_refptr<FrameDecryptorInterface> frame_decryptor_;
   rtc::scoped_refptr<DtlsTransportInterface> dtls_transport_;
+  // Allows to thread safely change jitter buffer delay. Handles caching cases
+  // if |SetJitterBufferMinimumDelay| is called before start.
+  rtc::scoped_refptr<JitterBufferDelayInterface> delay_;
 };
 
 }  // namespace webrtc