Add SetJitterBufferMinimumDelay method to RtpReceiverInterface.

This change is required to allow modification of Jitter Buffer delay
in javascript via Origin Trial Experiment.
Link to experiment description:
https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/Tgm4qiNepJc

Bug: webrtc:10287
Change-Id: I4f21380aad5982a4a60c55683b5173ce72ce0392
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131144
Commit-Queue: Ruslan Burakov <kuddai@google.com>
Reviewed-by: Steve Anton <steveanton@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27444}
diff --git a/api/rtp_receiver_interface.cc b/api/rtp_receiver_interface.cc
index 52f72df..615a31d 100644
--- a/api/rtp_receiver_interface.cc
+++ b/api/rtp_receiver_interface.cc
@@ -58,4 +58,7 @@
   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 7d9870b..d1ef137 100644
--- a/api/rtp_receiver_interface.h
+++ b/api/rtp_receiver_interface.h
@@ -128,6 +128,14 @@
   // Must call SetObserver(nullptr) before the observer is destroyed.
   virtual void SetObserver(RtpReceiverObserverInterface* observer) = 0;
 
+  // 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.
+  virtual void SetJitterBufferMinimumDelay(
+      absl::optional<double> delay_seconds);
+
   // TODO(zhihuang): Remove the default implementation once the subclasses
   // implement this. Currently, the only relevant subclass is the
   // content::FakeRtpReceiver in Chromium.
@@ -163,6 +171,7 @@
 PROXY_CONSTMETHOD0(RtpParameters, GetParameters)
 PROXY_METHOD1(bool, SetParameters, const RtpParameters&)
 PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*)
+PROXY_METHOD1(void, SetJitterBufferMinimumDelay, absl::optional<double>)
 PROXY_CONSTMETHOD0(std::vector<RtpSource>, GetSources)
 PROXY_METHOD1(void,
               SetFrameDecryptor,
diff --git a/api/test/mock_rtpreceiver.h b/api/test/mock_rtpreceiver.h
index c585cbf..710f8c5 100644
--- a/api/test/mock_rtpreceiver.h
+++ b/api/test/mock_rtpreceiver.h
@@ -30,6 +30,7 @@
   MOCK_CONST_METHOD0(GetParameters, RtpParameters());
   MOCK_METHOD1(SetParameters, bool(const RtpParameters&));
   MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*));
+  MOCK_METHOD1(SetJitterBufferMinimumDelay, void(absl::optional<double>));
   MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
 };
 
diff --git a/pc/audio_rtp_receiver.cc b/pc/audio_rtp_receiver.cc
index 4602fda..61ea340 100644
--- a/pc/audio_rtp_receiver.cc
+++ b/pc/audio_rtp_receiver.cc
@@ -25,6 +25,10 @@
 
 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)
@@ -232,6 +236,11 @@
   }
 }
 
+void AudioRtpReceiver::SetJitterBufferMinimumDelay(
+    absl::optional<double> delay_seconds) {
+  source_->SetLatency(delay_seconds.value_or(kDefaultLatency));
+}
+
 void AudioRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
   RTC_DCHECK(media_channel == nullptr ||
              media_channel->media_type() == media_type());
diff --git a/pc/audio_rtp_receiver.h b/pc/audio_rtp_receiver.h
index 82c8d88..9ad5c61 100644
--- a/pc/audio_rtp_receiver.h
+++ b/pc/audio_rtp_receiver.h
@@ -95,6 +95,9 @@
                       streams) override;
   void SetObserver(RtpReceiverObserverInterface* observer) override;
 
+  void SetJitterBufferMinimumDelay(
+      absl::optional<double> delay_seconds) override;
+
   void SetMediaChannel(cricket::MediaChannel* media_channel) override;
 
   std::vector<RtpSource> GetSources() const override;
diff --git a/pc/playout_latency.cc b/pc/playout_latency.cc
index be78439..aa7f950 100644
--- a/pc/playout_latency.cc
+++ b/pc/playout_latency.cc
@@ -10,8 +10,6 @@
 
 #include "pc/playout_latency.h"
 
-#include "iostream"
-
 #include "rtc_base/checks.h"
 #include "rtc_base/location.h"
 #include "rtc_base/logging.h"
@@ -21,6 +19,7 @@
 
 namespace {
 constexpr int kDefaultLatency = 0;
+constexpr int kMaximumDelayMs = 10000;
 constexpr int kRoundToZeroThresholdMs = 10;
 }  // namespace
 
@@ -52,8 +51,6 @@
 
 void PlayoutLatency::SetLatency(double latency) {
   RTC_DCHECK_RUN_ON(worker_thread_);
-  RTC_DCHECK_GE(latency, 0);
-  RTC_DCHECK_LE(latency, 10);
 
   int delay_ms = rtc::dchecked_cast<int>(latency * 1000);
   // In JitterBuffer 0 delay has special meaning of being unconstrained value
@@ -63,6 +60,10 @@
     delay_ms = 0;
   }
 
+  if (delay_ms > kMaximumDelayMs) {
+    delay_ms = kMaximumDelayMs;
+  }
+
   cached_latency_ = latency;
   if (media_channel_ && ssrc_) {
     media_channel_->SetBaseMinimumPlayoutDelayMs(ssrc_.value(), delay_ms);
diff --git a/pc/playout_latency_unittest.cc b/pc/playout_latency_unittest.cc
index 0a67161..d603477 100644
--- a/pc/playout_latency_unittest.cc
+++ b/pc/playout_latency_unittest.cc
@@ -100,4 +100,19 @@
   latency_->SetLatency(0.005);
 }
 
+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);
+
+  EXPECT_CALL(delayable_, SetBaseMinimumPlayoutDelayMs(kSsrc, 0))
+      .WillOnce(Return(true));
+
+  latency_->SetLatency(-2.0);
+}
+
 }  // namespace webrtc
diff --git a/pc/rtp_sender_receiver_unittest.cc b/pc/rtp_sender_receiver_unittest.cc
index c8d84f6..e6d0083 100644
--- a/pc/rtp_sender_receiver_unittest.cc
+++ b/pc/rtp_sender_receiver_unittest.cc
@@ -491,6 +491,17 @@
     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,
+                                       RtpReceiverInterface* receiver,
+                                       uint32_t ssrc) {
+    receiver->SetJitterBufferMinimumDelay(/*delay_seconds=*/0.5);
+    absl::optional<int> delay_ms =
+        media_channel->GetBaseMinimumPlayoutDelayMs(ssrc);  // In milliseconds.
+    EXPECT_DOUBLE_EQ(0.5, delay_ms.value_or(0) / 1000.0);
+  }
+
  protected:
   rtc::Thread* const network_thread_;
   rtc::Thread* const worker_thread_;
@@ -703,6 +714,20 @@
                               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) {
+  CreateVideoRtpReceiver();
+  VerifyRtpReceiverDelayBehaviour(video_media_channel_,
+                                  video_rtp_receiver_.get(), kVideoSsrc);
+}
+
 // Test that the media channel isn't enabled for sending if the audio sender
 // doesn't have both a track and SSRC.
 TEST_F(RtpSenderReceiverTest, AudioSenderWithoutTrackAndSsrc) {
diff --git a/pc/test/mock_rtp_receiver_internal.h b/pc/test/mock_rtp_receiver_internal.h
index f948d83..0838ada 100644
--- a/pc/test/mock_rtp_receiver_internal.h
+++ b/pc/test/mock_rtp_receiver_internal.h
@@ -35,6 +35,7 @@
   MOCK_CONST_METHOD0(GetParameters, RtpParameters());
   MOCK_METHOD1(SetParameters, bool(const RtpParameters&));
   MOCK_METHOD1(SetObserver, void(RtpReceiverObserverInterface*));
+  MOCK_METHOD1(SetJitterBufferMinimumDelay, void(absl::optional<double>));
   MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
   MOCK_METHOD1(SetFrameDecryptor,
                void(rtc::scoped_refptr<FrameDecryptorInterface>));
diff --git a/pc/video_rtp_receiver.cc b/pc/video_rtp_receiver.cc
index b112f04..5a2e778 100644
--- a/pc/video_rtp_receiver.cc
+++ b/pc/video_rtp_receiver.cc
@@ -26,6 +26,10 @@
 
 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)
@@ -192,6 +196,11 @@
   }
 }
 
+void VideoRtpReceiver::SetJitterBufferMinimumDelay(
+    absl::optional<double> delay_seconds) {
+  source_->SetLatency(delay_seconds.value_or(kDefaultLatency));
+}
+
 void VideoRtpReceiver::SetMediaChannel(cricket::MediaChannel* media_channel) {
   RTC_DCHECK(media_channel == nullptr ||
              media_channel->media_type() == media_type());
diff --git a/pc/video_rtp_receiver.h b/pc/video_rtp_receiver.h
index 2795e7a..9ad4fe7 100644
--- a/pc/video_rtp_receiver.h
+++ b/pc/video_rtp_receiver.h
@@ -99,6 +99,9 @@
 
   void SetObserver(RtpReceiverObserverInterface* observer) override;
 
+  void SetJitterBufferMinimumDelay(
+      absl::optional<double> delay_seconds) override;
+
   void SetMediaChannel(cricket::MediaChannel* media_channel) override;
 
   int AttachmentId() const override { return attachment_id_; }