Reland of actor NACK bitrate allocation (patchset #1 id:1 of https://codereview.webrtc.org/2131913003/ )

Reason for revert:
Upstream fixes in place, should be OK now.

Original issue's description:
> Revert of Refactor NACK bitrate allocation (patchset #16 id:300001 of https://codereview.webrtc.org/2061423003/ )
>
> Reason for revert:
> Breaks upstream code.
>
> Original issue's description:
> > Refactor NACK bitrate allocation
> >
> > Nack bitrate allocation should not be done on a per-rtp-module basis,
> > but rather shared bitrate pool per call. This CL moves allocation to the
> > pacer and cleans up a bunch if bitrate stats handling.
> >
> > BUG=
> > R=danilchap@webrtc.org, stefan@webrtc.org, tommi@webrtc.org
> >
> > Committed: https://chromium.googlesource.com/external/webrtc/+/5fc59e810b8ea848702f2dbc740fe190608e1413
>
> TBR=tommi@webrtc.org,danilchap@webrtc.org,stefan@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=
>
> Committed: https://crrev.com/e5dd44101eca485f5ad12e5f7ce6f6b0d204116b
> Cr-Commit-Position: refs/heads/master@{#13417}

TBR=tommi@webrtc.org,danilchap@webrtc.org,stefan@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=

Review-Url: https://codereview.webrtc.org/2146013002
Cr-Original-Commit-Position: refs/heads/master@{#13465}
Cr-Mirrored-From: https://chromium.googlesource.com/external/webrtc
Cr-Mirrored-Commit: cd349d97433636a26df087058a11770ed018a85c
diff --git a/BUILD.gn b/BUILD.gn
index 48fbebb..35cb24b 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -442,6 +442,7 @@
       "base/proxy_unittest.cc",
       "base/proxydetect_unittest.cc",
       "base/random_unittest.cc",
+      "base/rate_limiter_unittest.cc",
       "base/rate_statistics_unittest.cc",
       "base/ratelimiter_unittest.cc",
       "base/ratetracker_unittest.cc",
diff --git a/base/BUILD.gn b/base/BUILD.gn
index 621a57b..e7ed156 100644
--- a/base/BUILD.gn
+++ b/base/BUILD.gn
@@ -141,6 +141,8 @@
     "race_checker.h",
     "random.cc",
     "random.h",
+    "rate_limiter.cc",
+    "rate_limiter.h",
     "rate_statistics.cc",
     "rate_statistics.h",
     "ratetracker.cc",
diff --git a/base/base.gyp b/base/base.gyp
index b81ad12..38508ff 100644
--- a/base/base.gyp
+++ b/base/base.gyp
@@ -74,6 +74,8 @@
         'random.h',
         'rate_statistics.cc',
         'rate_statistics.h',
+        'rate_limiter.cc',
+        'rate_limiter.h',
         'ratetracker.cc',
         'ratetracker.h',
         'refcount.h',
diff --git a/base/rate_limiter.cc b/base/rate_limiter.cc
new file mode 100644
index 0000000..89bdb94
--- /dev/null
+++ b/base/rate_limiter.cc
@@ -0,0 +1,65 @@
+/*
+ *  Copyright (c) 2016 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 "webrtc/base/rate_limiter.h"
+#include "webrtc/system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+RateLimiter::RateLimiter(Clock* clock, int64_t max_window_ms)
+    : clock_(clock),
+      current_rate_(max_window_ms, RateStatistics::kBpsScale),
+      window_size_ms_(max_window_ms),
+      max_rate_bps_(std::numeric_limits<uint32_t>::max()) {}
+
+RateLimiter::~RateLimiter() {}
+
+// Usage note: This class is intended be usable in a scenario where different
+// threads may call each of the the different method. For instance, a network
+// thread trying to send data calling TryUseRate(), the bandwidth estimator
+// calling SetMaxRate() and a timed maintenance thread periodically updating
+// the RTT.
+bool RateLimiter::TryUseRate(size_t packet_size_bytes) {
+  rtc::CritScope cs(&lock_);
+  int64_t now_ms = clock_->TimeInMilliseconds();
+  rtc::Optional<uint32_t> current_rate = current_rate_.Rate(now_ms);
+  if (current_rate) {
+    // If there is a current rate, check if adding bytes would cause maximum
+    // bitrate target to be exceeded. If there is NOT a valid current rate,
+    // allow allocating rate even if target is exceeded. This prevents
+    // problems
+    // at very low rates, where for instance retransmissions would never be
+    // allowed due to too high bitrate caused by a single packet.
+
+    size_t bitrate_addition_bps =
+        (packet_size_bytes * 8 * 1000) / window_size_ms_;
+    if (*current_rate + bitrate_addition_bps > max_rate_bps_)
+      return false;
+  }
+
+  current_rate_.Update(packet_size_bytes, now_ms);
+  return true;
+}
+
+void RateLimiter::SetMaxRate(uint32_t max_rate_bps) {
+  rtc::CritScope cs(&lock_);
+  max_rate_bps_ = max_rate_bps;
+}
+
+// Set the window size over which to measure the current bitrate.
+// For retransmissions, this is typically the RTT.
+bool RateLimiter::SetWindowSize(int64_t window_size_ms) {
+  rtc::CritScope cs(&lock_);
+  window_size_ms_ = window_size_ms;
+  return current_rate_.SetWindowSize(window_size_ms,
+                                     clock_->TimeInMilliseconds());
+}
+
+}  // namespace webrtc
diff --git a/base/rate_limiter.h b/base/rate_limiter.h
new file mode 100644
index 0000000..5809fc1
--- /dev/null
+++ b/base/rate_limiter.h
@@ -0,0 +1,56 @@
+/*
+ *  Copyright (c) 2016 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 WEBRTC_BASE_RATE_LIMITER_H_
+#define WEBRTC_BASE_RATE_LIMITER_H_
+
+#include <limits>
+
+#include "webrtc/base/constructormagic.h"
+#include "webrtc/base/criticalsection.h"
+#include "webrtc/base/rate_statistics.h"
+
+namespace webrtc {
+
+class Clock;
+
+// Class used to limit a bitrate, making sure the average does not exceed a
+// maximum as measured over a sliding window. This class is thread safe; all
+// methods will acquire (the same) lock befeore executing.
+class RateLimiter {
+ public:
+  RateLimiter(Clock* clock, int64_t max_window_ms);
+  ~RateLimiter();
+
+  // Try to use rate to send bytes. Returns true on success and if so updates
+  // current rate.
+  bool TryUseRate(size_t packet_size_bytes);
+
+  // Set the maximum bitrate, in bps, that this limiter allows to send.
+  void SetMaxRate(uint32_t max_rate_bps);
+
+  // Set the window size over which to measure the current bitrate.
+  // For example, irt retransmissions, this is typically the RTT.
+  // Returns true on success and false if window_size_ms is out of range.
+  bool SetWindowSize(int64_t window_size_ms);
+
+ private:
+  Clock* const clock_;
+  rtc::CriticalSection lock_;
+  RateStatistics current_rate_ GUARDED_BY(lock_);
+  int64_t window_size_ms_ GUARDED_BY(lock_);
+  uint32_t max_rate_bps_ GUARDED_BY(lock_);
+
+  RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RateLimiter);
+};
+
+}  // namespace webrtc
+
+#endif  // WEBRTC_BASE_RATE_LIMITER_H_
diff --git a/base/rate_limiter_unittest.cc b/base/rate_limiter_unittest.cc
new file mode 100644
index 0000000..d441128
--- /dev/null
+++ b/base/rate_limiter_unittest.cc
@@ -0,0 +1,205 @@
+/*
+ *  Copyright (c) 2016 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 <algorithm>
+#include <memory>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+#include "webrtc/base/event.h"
+#include "webrtc/base/platform_thread.h"
+#include "webrtc/base/rate_limiter.h"
+#include "webrtc/base/task_queue.h"
+#include "webrtc/system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+class RateLimitTest : public ::testing::Test {
+ public:
+  RateLimitTest()
+      : clock_(0), rate_limiter(new RateLimiter(&clock_, kWindowSizeMs)) {}
+  virtual ~RateLimitTest() {}
+
+  void SetUp() override { rate_limiter->SetMaxRate(kMaxRateBps); }
+
+ protected:
+  static constexpr int64_t kWindowSizeMs = 1000;
+  static constexpr uint32_t kMaxRateBps = 100000;
+  // Bytes needed to completely saturate the rate limiter.
+  static constexpr size_t kRateFillingBytes =
+      (kMaxRateBps * kWindowSizeMs) / (8 * 1000);
+  SimulatedClock clock_;
+  std::unique_ptr<RateLimiter> rate_limiter;
+};
+
+TEST_F(RateLimitTest, IncreasingMaxRate) {
+  // Fill rate, extend window to full size.
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+  clock_.AdvanceTimeMilliseconds(kWindowSizeMs - 1);
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+
+  // All rate consumed.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+
+  // Double the available rate and fill that too.
+  rate_limiter->SetMaxRate(kMaxRateBps * 2);
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes));
+
+  // All rate consumed again.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+}
+
+TEST_F(RateLimitTest, DecreasingMaxRate) {
+  // Fill rate, extend window to full size.
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+  clock_.AdvanceTimeMilliseconds(kWindowSizeMs - 1);
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+
+  // All rate consumed.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+
+  // Halve the available rate and move window so half of the data falls out.
+  rate_limiter->SetMaxRate(kMaxRateBps / 2);
+  clock_.AdvanceTimeMilliseconds(1);
+
+  // All rate still consumed.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+}
+
+TEST_F(RateLimitTest, ChangingWindowSize) {
+  // Fill rate, extend window to full size.
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+  clock_.AdvanceTimeMilliseconds(kWindowSizeMs - 1);
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+
+  // All rate consumed.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+
+  // Decrease window size so half of the data falls out.
+  rate_limiter->SetWindowSize(kWindowSizeMs / 2);
+  // Average rate should still be the same, so rate is still all consumed.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+
+  // Increase window size again. Now the rate is only half used (removed data
+  // points don't come back to life).
+  rate_limiter->SetWindowSize(kWindowSizeMs);
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes / 2));
+
+  // All rate consumed again.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+}
+
+TEST_F(RateLimitTest, SingleUsageAlwaysOk) {
+  // Using more bytes than can fit in a window is OK for a single packet.
+  EXPECT_TRUE(rate_limiter->TryUseRate(kRateFillingBytes + 1));
+}
+
+TEST_F(RateLimitTest, WindowSizeLimits) {
+  EXPECT_TRUE(rate_limiter->SetWindowSize(1));
+  EXPECT_FALSE(rate_limiter->SetWindowSize(0));
+  EXPECT_TRUE(rate_limiter->SetWindowSize(kWindowSizeMs));
+  EXPECT_FALSE(rate_limiter->SetWindowSize(kWindowSizeMs + 1));
+}
+
+static const int64_t kMaxTimeoutMs = 30000;
+
+class ThreadTask {
+ public:
+  explicit ThreadTask(RateLimiter* rate_limiter)
+      : rate_limiter_(rate_limiter),
+        start_signal_(false, false),
+        end_signal_(false, false) {}
+  virtual ~ThreadTask() {}
+
+  void Run() {
+    start_signal_.Wait(kMaxTimeoutMs);
+    DoRun();
+    end_signal_.Set();
+  }
+
+  virtual void DoRun() = 0;
+
+  RateLimiter* const rate_limiter_;
+  rtc::Event start_signal_;
+  rtc::Event end_signal_;
+};
+
+bool RunTask(void* thread_task) {
+  reinterpret_cast<ThreadTask*>(thread_task)->Run();
+  return false;
+}
+
+TEST_F(RateLimitTest, MultiThreadedUsage) {
+  // Simple sanity test, with different threads calling the various methods.
+  // Runs a few simple tasks, each on its own thread, but coordinated with
+  // events so that they run in a serialized order. Intended to catch data
+  // races when run with tsan et al.
+
+  // Half window size, double rate -> same amount of bytes needed to fill rate.
+
+  class SetWindowSizeTask : public ThreadTask {
+   public:
+    explicit SetWindowSizeTask(RateLimiter* rate_limiter)
+        : ThreadTask(rate_limiter) {}
+    virtual ~SetWindowSizeTask() {}
+
+    void DoRun() override {
+      EXPECT_TRUE(rate_limiter_->SetWindowSize(kWindowSizeMs / 2));
+    }
+  } set_window_size_task(rate_limiter.get());
+  rtc::PlatformThread thread1(RunTask, &set_window_size_task, "Thread1");
+  thread1.Start();
+
+  class SetMaxRateTask : public ThreadTask {
+   public:
+    explicit SetMaxRateTask(RateLimiter* rate_limiter)
+        : ThreadTask(rate_limiter) {}
+    virtual ~SetMaxRateTask() {}
+
+    void DoRun() override { rate_limiter_->SetMaxRate(kMaxRateBps * 2); }
+  } set_max_rate_task(rate_limiter.get());
+  rtc::PlatformThread thread2(RunTask, &set_max_rate_task, "Thread2");
+  thread2.Start();
+
+  class UseRateTask : public ThreadTask {
+   public:
+    UseRateTask(RateLimiter* rate_limiter, SimulatedClock* clock)
+        : ThreadTask(rate_limiter), clock_(clock) {}
+    virtual ~UseRateTask() {}
+
+    void DoRun() override {
+      EXPECT_TRUE(rate_limiter_->TryUseRate(kRateFillingBytes / 2));
+      clock_->AdvanceTimeMilliseconds((kWindowSizeMs / 2) - 1);
+      EXPECT_TRUE(rate_limiter_->TryUseRate(kRateFillingBytes / 2));
+    }
+
+    SimulatedClock* const clock_;
+  } use_rate_task(rate_limiter.get(), &clock_);
+  rtc::PlatformThread thread3(RunTask, &use_rate_task, "Thread3");
+  thread3.Start();
+
+  set_window_size_task.start_signal_.Set();
+  EXPECT_TRUE(set_window_size_task.end_signal_.Wait(kMaxTimeoutMs));
+
+  set_max_rate_task.start_signal_.Set();
+  EXPECT_TRUE(set_max_rate_task.end_signal_.Wait(kMaxTimeoutMs));
+
+  use_rate_task.start_signal_.Set();
+  EXPECT_TRUE(use_rate_task.end_signal_.Wait(kMaxTimeoutMs));
+
+  // All rate consumed.
+  EXPECT_FALSE(rate_limiter->TryUseRate(1));
+
+  thread1.Stop();
+  thread2.Stop();
+  thread3.Stop();
+}
+
+}  // namespace webrtc
diff --git a/base/rate_statistics.cc b/base/rate_statistics.cc
index 1fd63cc..3122dbb 100644
--- a/base/rate_statistics.cc
+++ b/base/rate_statistics.cc
@@ -61,8 +61,10 @@
   ++num_samples_;
 }
 
-rtc::Optional<uint32_t> RateStatistics::Rate(int64_t now_ms) {
-  EraseOld(now_ms);
+rtc::Optional<uint32_t> RateStatistics::Rate(int64_t now_ms) const {
+  // Yeah, this const_cast ain't pretty, but the alternative is to declare most
+  // of the members as mutable...
+  const_cast<RateStatistics*>(this)->EraseOld(now_ms);
 
   // If window is a single bucket or there is only one sample in a data set that
   // has not grown to the full window size, treat this as rate unavailable.
@@ -112,7 +114,7 @@
   return true;
 }
 
-bool RateStatistics::IsInitialized() {
+bool RateStatistics::IsInitialized() const {
   return oldest_time_ != -max_window_size_ms_;
 }
 
diff --git a/base/rate_statistics.h b/base/rate_statistics.h
index 3e913cc..8a90a46 100644
--- a/base/rate_statistics.h
+++ b/base/rate_statistics.h
@@ -20,22 +20,37 @@
 
 class RateStatistics {
  public:
+  static constexpr float kBpsScale = 8000.0f;
+
   // max_window_size_ms = Maximum window size in ms for the rate estimation.
   //                      Initial window size is set to this, but may be changed
   //                      to something lower by calling SetWindowSize().
-  // scale = coefficient to convert counts/ms to desired units,
-  //         ex: if counts represents bytes, use 8*1000 to go to bits/s
+  // scale = coefficient to convert counts/ms to desired unit
+  //         ex: kBpsScale (8000) for bits/s if count represents bytes.
   RateStatistics(int64_t max_window_size_ms, float scale);
   ~RateStatistics();
 
+  // Reset instance to original state.
   void Reset();
+
+  // Update rate with a new data point, moving averaging window as needed.
   void Update(size_t count, int64_t now_ms);
-  rtc::Optional<uint32_t> Rate(int64_t now_ms);
+
+  // Note that despite this being a const method, it still updates the internal
+  // state (moves averaging window), but it doesn't make any alterations that
+  // are observable from the other methods, as long as supplied timestamps are
+  // from a monotonic clock. Ie, it doesn't matter if this call moves the
+  // window, since any subsequent call to Update or Rate would still have moved
+  // the window as much or more.
+  rtc::Optional<uint32_t> Rate(int64_t now_ms) const;
+
+  // Update the size of the averaging window. The maximum allowed value for
+  // window_size_ms is max_window_size_ms as supplied in the constructor.
   bool SetWindowSize(int64_t window_size_ms, int64_t now_ms);
 
  private:
   void EraseOld(int64_t now_ms);
-  bool IsInitialized();
+  bool IsInitialized() const;
 
   // Counters are kept in buckets (circular buffer), with one bucket
   // per millisecond.
diff --git a/call/rtc_event_log_unittest.cc b/call/rtc_event_log_unittest.cc
index 82f23a9..2d583a9 100644
--- a/call/rtc_event_log_unittest.cc
+++ b/call/rtc_event_log_unittest.cc
@@ -122,7 +122,8 @@
                        nullptr,   // FrameCountObserver*
                        nullptr,   // SendSideDelayObserver*
                        nullptr,   // RtcEventLog*
-                       nullptr);  // SendPacketObserver*
+                       nullptr,   // SendPacketObserver*
+                       nullptr);  // NackRateLimiter*
 
   std::vector<uint32_t> csrcs;
   for (unsigned i = 0; i < csrcs_count; i++) {
diff --git a/common_types.h b/common_types.h
index 13d0c3f..bb29af0 100644
--- a/common_types.h
+++ b/common_types.h
@@ -252,11 +252,10 @@
 
 // Rate statistics for a stream.
 struct BitrateStatistics {
-  BitrateStatistics() : bitrate_bps(0), packet_rate(0), timestamp_ms(0) {}
+  BitrateStatistics() : bitrate_bps(0), packet_rate(0) {}
 
   uint32_t bitrate_bps;   // Bitrate in bits per second.
   uint32_t packet_rate;   // Packet rate in packets per second.
-  uint64_t timestamp_ms;  // Ntp timestamp in ms at time of rate estimation.
 };
 
 // Callback, used to notify an observer whenever new rates have been estimated.
@@ -264,8 +263,8 @@
  public:
   virtual ~BitrateStatisticsObserver() {}
 
-  virtual void Notify(const BitrateStatistics& total_stats,
-                      const BitrateStatistics& retransmit_stats,
+  virtual void Notify(uint32_t total_bitrate_bps,
+                      uint32_t retransmit_bitrate_bps,
                       uint32_t ssrc) = 0;
 };
 
diff --git a/modules/congestion_controller/congestion_controller.cc b/modules/congestion_controller/congestion_controller.cc
index e28a38c..b4e5c14 100644
--- a/modules/congestion_controller/congestion_controller.cc
+++ b/modules/congestion_controller/congestion_controller.cc
@@ -17,6 +17,7 @@
 #include "webrtc/base/checks.h"
 #include "webrtc/base/constructormagic.h"
 #include "webrtc/base/logging.h"
+#include "webrtc/base/rate_limiter.h"
 #include "webrtc/base/socket.h"
 #include "webrtc/base/thread_annotations.h"
 #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
@@ -32,6 +33,8 @@
 namespace {
 
 static const uint32_t kTimeOffsetSwitchThreshold = 30;
+static const int64_t kMinRetransmitWindowSizeMs = 30;
+static const int64_t kMaxRetransmitWindowSizeMs = 1000;
 
 // Makes sure that the bitrate and the min, max values are in valid range.
 static void ClampBitrates(int* bitrate_bps,
@@ -164,6 +167,8 @@
           new WrappingBitrateEstimator(remote_bitrate_observer, clock_)),
       bitrate_controller_(
           BitrateController::CreateBitrateController(clock_, event_log)),
+      retransmission_rate_limiter_(
+          new RateLimiter(clock, kMaxRetransmitWindowSizeMs)),
       remote_estimator_proxy_(clock_, packet_router_.get()),
       transport_feedback_adapter_(bitrate_controller_.get(), clock_),
       min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps),
@@ -191,6 +196,8 @@
       // construction.
       bitrate_controller_(
           BitrateController::CreateBitrateController(clock_, event_log)),
+      retransmission_rate_limiter_(
+          new RateLimiter(clock, kMaxRetransmitWindowSizeMs)),
       remote_estimator_proxy_(clock_, packet_router_.get()),
       transport_feedback_adapter_(bitrate_controller_.get(), clock_),
       min_bitrate_bps_(RemoteBitrateEstimator::kDefaultMinBitrateBps),
@@ -266,6 +273,10 @@
   return &transport_feedback_adapter_;
 }
 
+RateLimiter* CongestionController::GetRetransmissionRateLimiter() {
+  return retransmission_rate_limiter_.get();
+}
+
 void CongestionController::SetAllocatedSendBitrateLimits(
     int min_send_bitrate_bps,
     int max_padding_bitrate_bps) {
@@ -299,6 +310,14 @@
 void CongestionController::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
   remote_bitrate_estimator_->OnRttUpdate(avg_rtt_ms, max_rtt_ms);
   transport_feedback_adapter_.OnRttUpdate(avg_rtt_ms, max_rtt_ms);
+
+  int64_t nack_window_size_ms = max_rtt_ms;
+  if (nack_window_size_ms > kMaxRetransmitWindowSizeMs) {
+    nack_window_size_ms = kMaxRetransmitWindowSizeMs;
+  } else if (nack_window_size_ms < kMinRetransmitWindowSizeMs) {
+    nack_window_size_ms = kMinRetransmitWindowSizeMs;
+  }
+  retransmission_rate_limiter_->SetWindowSize(nack_window_size_ms);
 }
 
 int64_t CongestionController::TimeUntilNextProcess() {
@@ -323,8 +342,10 @@
   int64_t rtt;
   bool estimate_changed = bitrate_controller_->GetNetworkParameters(
       &bitrate_bps, &fraction_loss, &rtt);
-  if (estimate_changed)
+  if (estimate_changed) {
     pacer_->SetEstimatedBitrate(bitrate_bps);
+    retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
+  }
 
   bitrate_bps = IsNetworkDown() || IsSendQueueFull() ? 0 : bitrate_bps;
 
diff --git a/modules/congestion_controller/include/congestion_controller.h b/modules/congestion_controller/include/congestion_controller.h
index a48f000..a0531cc 100644
--- a/modules/congestion_controller/include/congestion_controller.h
+++ b/modules/congestion_controller/include/congestion_controller.h
@@ -31,6 +31,7 @@
 class BitrateController;
 class Clock;
 class ProcessThread;
+class RateLimiter;
 class RemoteBitrateEstimator;
 class RemoteBitrateObserver;
 class RtcEventLog;
@@ -80,6 +81,7 @@
   virtual PacedSender* pacer() { return pacer_.get(); }
   virtual PacketRouter* packet_router() { return packet_router_.get(); }
   virtual TransportFeedbackObserver* GetTransportFeedbackObserver();
+  RateLimiter* GetRetransmissionRateLimiter();
 
   // SetAllocatedSendBitrateLimits sets bitrates limits imposed by send codec
   // settings.
@@ -118,6 +120,7 @@
   const std::unique_ptr<PacedSender> pacer_;
   const std::unique_ptr<RemoteBitrateEstimator> remote_bitrate_estimator_;
   const std::unique_ptr<BitrateController> bitrate_controller_;
+  const std::unique_ptr<RateLimiter> retransmission_rate_limiter_;
   RemoteEstimatorProxy remote_estimator_proxy_;
   TransportFeedbackAdapter transport_feedback_adapter_;
   int min_bitrate_bps_;
diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn
index 77cc175..39aa150 100644
--- a/modules/rtp_rtcp/BUILD.gn
+++ b/modules/rtp_rtcp/BUILD.gn
@@ -19,8 +19,6 @@
     "include/rtp_rtcp.h",
     "include/rtp_rtcp_defines.h",
     "mocks/mock_rtp_rtcp.h",
-    "source/bitrate.cc",
-    "source/bitrate.h",
     "source/byte_io.h",
     "source/dtmf_queue.cc",
     "source/dtmf_queue.h",
diff --git a/modules/rtp_rtcp/include/receive_statistics.h b/modules/rtp_rtcp/include/receive_statistics.h
index cc21e22..90a848a 100644
--- a/modules/rtp_rtcp/include/receive_statistics.h
+++ b/modules/rtp_rtcp/include/receive_statistics.h
@@ -46,7 +46,7 @@
 
 typedef std::map<uint32_t, StreamStatistician*> StatisticianMap;
 
-class ReceiveStatistics : public Module {
+class ReceiveStatistics {
  public:
   virtual ~ReceiveStatistics() {}
 
@@ -89,8 +89,6 @@
                          size_t packet_length) override;
   StatisticianMap GetActiveStatisticians() const override;
   StreamStatistician* GetStatistician(uint32_t ssrc) const override;
-  int64_t TimeUntilNextProcess() override;
-  void Process() override;
   void SetMaxReorderingThreshold(int max_reordering_threshold) override;
   void RegisterRtcpStatisticsCallback(
       RtcpStatisticsCallback* callback) override;
diff --git a/modules/rtp_rtcp/include/rtp_rtcp.h b/modules/rtp_rtcp/include/rtp_rtcp.h
index 7c72e59..bfd8e65 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp.h
@@ -23,11 +23,12 @@
 
 namespace webrtc {
 // Forward declarations.
+class RateLimiter;
 class ReceiveStatistics;
 class RemoteBitrateEstimator;
+class RtcEventLog;
 class RtpReceiver;
 class Transport;
-class RtcEventLog;
 
 RTPExtensionType StringToRtpExtensionType(const std::string& extension);
 
@@ -79,6 +80,7 @@
     SendSideDelayObserver* send_side_delay_observer;
     RtcEventLog* event_log;
     SendPacketObserver* send_packet_observer;
+    RateLimiter* retransmission_rate_limiter;
     RTC_DISALLOW_COPY_AND_ASSIGN(Configuration);
   };
 
@@ -616,11 +618,6 @@
     ***************************************************************************/
 
     /*
-    *   Set the target send bitrate
-    */
-    virtual void SetTargetSendBitrate(uint32_t bitrate_bps) = 0;
-
-    /*
     *   Turn on/off generic FEC
     */
     virtual void SetGenericFECStatus(bool enable,
diff --git a/modules/rtp_rtcp/rtp_rtcp.gypi b/modules/rtp_rtcp/rtp_rtcp.gypi
index 0c8477f..0082904 100644
--- a/modules/rtp_rtcp/rtp_rtcp.gypi
+++ b/modules/rtp_rtcp/rtp_rtcp.gypi
@@ -26,8 +26,6 @@
         'include/rtp_receiver.h',
         'include/rtp_rtcp.h',
         'include/rtp_rtcp_defines.h',
-        'source/bitrate.cc',
-        'source/bitrate.h',
         'source/byte_io.h',
         'source/fec_receiver_impl.cc',
         'source/fec_receiver_impl.h',
diff --git a/modules/rtp_rtcp/source/bitrate.cc b/modules/rtp_rtcp/source/bitrate.cc
deleted file mode 100644
index 49a2359..0000000
--- a/modules/rtp_rtcp/source/bitrate.cc
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- *  Copyright (c) 2012 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 "webrtc/modules/rtp_rtcp/source/bitrate.h"
-
-#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
-
-namespace webrtc {
-
-Bitrate::Bitrate(Clock* clock, Observer* observer)
-    : clock_(clock),
-      packet_rate_(0),
-      bitrate_(0),
-      bitrate_next_idx_(0),
-      time_last_rate_update_(0),
-      bytes_count_(0),
-      packet_count_(0),
-      observer_(observer) {
-  memset(packet_rate_array_, 0, sizeof(packet_rate_array_));
-  memset(bitrate_diff_ms_, 0, sizeof(bitrate_diff_ms_));
-  memset(bitrate_array_, 0, sizeof(bitrate_array_));
-}
-
-Bitrate::~Bitrate() {}
-
-void Bitrate::Update(const size_t bytes) {
-  rtc::CritScope cs(&crit_);
-  bytes_count_ += bytes;
-  packet_count_++;
-}
-
-uint32_t Bitrate::PacketRate() const {
-  rtc::CritScope cs(&crit_);
-  return packet_rate_;
-}
-
-uint32_t Bitrate::BitrateLast() const {
-  rtc::CritScope cs(&crit_);
-  return bitrate_;
-}
-
-uint32_t Bitrate::BitrateNow() const {
-  rtc::CritScope cs(&crit_);
-  int64_t now = clock_->TimeInMilliseconds();
-  int64_t diff_ms = now - time_last_rate_update_;
-
-  if (diff_ms > 10000) {  // 10 seconds.
-    // Too high difference, ignore.
-    return bitrate_;
-  }
-  int64_t bits_since_last_rate_update = 8 * bytes_count_ * 1000;
-
-  // We have to consider the time when the measurement was done:
-  // ((bits/sec * sec) + (bits)) / sec.
-  int64_t bitrate = (static_cast<uint64_t>(bitrate_) * 1000 +
-                           bits_since_last_rate_update) / (1000 + diff_ms);
-  return static_cast<uint32_t>(bitrate);
-}
-
-int64_t Bitrate::time_last_rate_update() const {
-  rtc::CritScope cs(&crit_);
-  return time_last_rate_update_;
-}
-
-// Triggered by timer.
-void Bitrate::Process() {
-  BitrateStatistics stats;
-  {
-    rtc::CritScope cs(&crit_);
-    int64_t now = clock_->CurrentNtpInMilliseconds();
-    int64_t diff_ms = now - time_last_rate_update_;
-
-    if (diff_ms < 100) {
-      // Not enough data, wait...
-      return;
-    }
-    if (diff_ms > 10000) {  // 10 seconds.
-      // Too high difference, ignore.
-      time_last_rate_update_ = now;
-      bytes_count_ = 0;
-      packet_count_ = 0;
-      return;
-    }
-    packet_rate_array_[bitrate_next_idx_] = (packet_count_ * 1000) / diff_ms;
-    bitrate_array_[bitrate_next_idx_] = 8 * ((bytes_count_ * 1000) / diff_ms);
-    bitrate_diff_ms_[bitrate_next_idx_] = diff_ms;
-    bitrate_next_idx_++;
-    if (bitrate_next_idx_ >= 10) {
-      bitrate_next_idx_ = 0;
-    }
-    int64_t sum_diffMS = 0;
-    int64_t sum_bitrateMS = 0;
-    int64_t sum_packetrateMS = 0;
-    for (int i = 0; i < 10; i++) {
-      sum_diffMS += bitrate_diff_ms_[i];
-      sum_bitrateMS += bitrate_array_[i] * bitrate_diff_ms_[i];
-      sum_packetrateMS += packet_rate_array_[i] * bitrate_diff_ms_[i];
-    }
-    time_last_rate_update_ = now;
-    bytes_count_ = 0;
-    packet_count_ = 0;
-    packet_rate_ = static_cast<uint32_t>(sum_packetrateMS / sum_diffMS);
-    bitrate_ = static_cast<uint32_t>(sum_bitrateMS / sum_diffMS);
-
-    stats.bitrate_bps = bitrate_;
-    stats.packet_rate = packet_rate_;
-    stats.timestamp_ms = now;
-  }
-
-  if (observer_)
-    observer_->BitrateUpdated(stats);
-}
-
-}  // namespace webrtc
diff --git a/modules/rtp_rtcp/source/bitrate.h b/modules/rtp_rtcp/source/bitrate.h
deleted file mode 100644
index 7aaaead..0000000
--- a/modules/rtp_rtcp/source/bitrate.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- *  Copyright (c) 2012 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 WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_
-#define WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_
-
-#include <stdio.h>
-
-#include <list>
-
-#include "webrtc/base/criticalsection.h"
-#include "webrtc/common_types.h"
-#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
-#include "webrtc/typedefs.h"
-
-namespace webrtc {
-
-class Clock;
-
-class Bitrate {
- public:
-  class Observer;
-  Bitrate(Clock* clock, Observer* observer);
-  virtual ~Bitrate();
-
-  // Calculates rates.
-  void Process();
-
-  // Update with a packet.
-  void Update(const size_t bytes);
-
-  // Packet rate last second, updated roughly every 100 ms.
-  uint32_t PacketRate() const;
-
-  // Bitrate last second, updated roughly every 100 ms.
-  uint32_t BitrateLast() const;
-
-  // Bitrate last second, updated now.
-  uint32_t BitrateNow() const;
-
-  int64_t time_last_rate_update() const;
-
-  class Observer {
-   public:
-    Observer() {}
-    virtual ~Observer() {}
-
-    virtual void BitrateUpdated(const BitrateStatistics& stats) = 0;
-  };
-
- protected:
-  Clock* clock_;
-
- private:
-  rtc::CriticalSection crit_;
-  uint32_t packet_rate_;
-  uint32_t bitrate_;
-  uint8_t bitrate_next_idx_;
-  int64_t packet_rate_array_[10];
-  int64_t bitrate_array_[10];
-  int64_t bitrate_diff_ms_[10];
-  int64_t time_last_rate_update_;
-  size_t bytes_count_;
-  uint32_t packet_count_;
-  Observer* const observer_;
-};
-
-}  // namespace webrtc
-
-#endif  // WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_
diff --git a/modules/rtp_rtcp/source/nack_rtx_unittest.cc b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
index f8d9243..b12c08e 100644
--- a/modules/rtp_rtcp/source/nack_rtx_unittest.cc
+++ b/modules/rtp_rtcp/source/nack_rtx_unittest.cc
@@ -15,6 +15,7 @@
 #include <set>
 
 #include "testing/gtest/include/gtest/gtest.h"
+#include "webrtc/base/rate_limiter.h"
 #include "webrtc/common_types.h"
 #include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
@@ -34,6 +35,7 @@
 const int kNumFrames = 30;
 const int kPayloadType = 123;
 const int kRtxPayloadType = 98;
+const int64_t kMaxRttMs = 1000;
 
 class VerifyingRtxReceiver : public NullRtpData {
  public:
@@ -168,11 +170,12 @@
  protected:
   RtpRtcpRtxNackTest()
       : rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
-        rtp_rtcp_module_(NULL),
+        rtp_rtcp_module_(nullptr),
         transport_(kTestSsrc + 1),
         receiver_(),
         payload_data_length(sizeof(payload_data)),
-        fake_clock(123456) {}
+        fake_clock(123456),
+        retranmission_rate_limiter_(&fake_clock, kMaxRttMs) {}
   ~RtpRtcpRtxNackTest() {}
 
   void SetUp() override {
@@ -182,6 +185,7 @@
     receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock));
     configuration.receive_statistics = receive_statistics_.get();
     configuration.outgoing_transport = &transport_;
+    configuration.retransmission_rate_limiter = &retranmission_rate_limiter_;
     rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration);
 
     rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_));
@@ -288,6 +292,7 @@
   uint8_t payload_data[65000];
   size_t payload_data_length;
   SimulatedClock fake_clock;
+  RateLimiter retranmission_rate_limiter_;
 };
 
 TEST_F(RtpRtcpRtxNackTest, LongNackList) {
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index 932be1b..4ec11b6 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -14,7 +14,7 @@
 
 #include <cstdlib>
 
-#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
 #include "webrtc/modules/rtp_rtcp/source/time_util.h"
 
 namespace webrtc {
@@ -29,7 +29,8 @@
     RtcpStatisticsCallback* rtcp_callback,
     StreamDataCountersCallback* rtp_callback)
     : clock_(clock),
-      incoming_bitrate_(clock, NULL),
+      incoming_bitrate_(kStatisticsProcessIntervalMs,
+                        RateStatistics::kBpsScale),
       ssrc_(0),
       max_reordering_threshold_(kDefaultMaxReorderingThreshold),
       jitter_q4_(0),
@@ -61,7 +62,7 @@
   rtc::CritScope cs(&stream_lock_);
   bool in_order = InOrderPacketInternal(header.sequenceNumber);
   ssrc_ = header.ssrc;
-  incoming_bitrate_.Update(packet_length);
+  incoming_bitrate_.Update(packet_length, clock_->TimeInMilliseconds());
   receive_counters_.transmitted.AddPacket(packet_length, header);
   if (!in_order && retransmitted) {
     receive_counters_.retransmitted.AddPacket(packet_length, header);
@@ -300,12 +301,7 @@
 
 uint32_t StreamStatisticianImpl::BitrateReceived() const {
   rtc::CritScope cs(&stream_lock_);
-  return incoming_bitrate_.BitrateNow();
-}
-
-void StreamStatisticianImpl::ProcessBitrate() {
-  rtc::CritScope cs(&stream_lock_);
-  incoming_bitrate_.Process();
+  return incoming_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
 void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs,
@@ -376,7 +372,6 @@
 
 ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
     : clock_(clock),
-      last_rate_update_ms_(0),
       rtcp_stats_callback_(NULL),
       rtp_stats_callback_(NULL) {}
 
@@ -452,23 +447,6 @@
   }
 }
 
-void ReceiveStatisticsImpl::Process() {
-  rtc::CritScope cs(&receive_statistics_lock_);
-  for (StatisticianImplMap::iterator it = statisticians_.begin();
-       it != statisticians_.end(); ++it) {
-    it->second->ProcessBitrate();
-  }
-  last_rate_update_ms_ = clock_->TimeInMilliseconds();
-}
-
-int64_t ReceiveStatisticsImpl::TimeUntilNextProcess() {
-  rtc::CritScope cs(&receive_statistics_lock_);
-  int64_t time_since_last_update = clock_->TimeInMilliseconds() -
-      last_rate_update_ms_;
-  return std::max<int64_t>(
-      kStatisticsProcessIntervalMs - time_since_last_update, 0);
-}
-
 void ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback(
     RtcpStatisticsCallback* callback) {
   rtc::CritScope cs(&receive_statistics_lock_);
@@ -525,10 +503,6 @@
 void NullReceiveStatistics::SetMaxReorderingThreshold(
     int max_reordering_threshold) {}
 
-int64_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; }
-
-void NullReceiveStatistics::Process() {}
-
 void NullReceiveStatistics::RegisterRtcpStatisticsCallback(
     RtcpStatisticsCallback* callback) {}
 
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 3967967..913f3b5 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -17,7 +17,7 @@
 #include <map>
 
 #include "webrtc/base/criticalsection.h"
-#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
+#include "webrtc/base/rate_statistics.h"
 #include "webrtc/system_wrappers/include/ntp_time.h"
 
 namespace webrtc {
@@ -44,7 +44,6 @@
                       bool retransmitted);
   void FecPacketReceived(const RTPHeader& header, size_t packet_length);
   void SetMaxReorderingThreshold(int max_reordering_threshold);
-  void ProcessBitrate();
   virtual void LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const;
 
  private:
@@ -57,9 +56,9 @@
   void NotifyRtpCallback() LOCKS_EXCLUDED(stream_lock_);
   void NotifyRtcpCallback() LOCKS_EXCLUDED(stream_lock_);
 
-  Clock* clock_;
+  Clock* const clock_;
   rtc::CriticalSection stream_lock_;
-  Bitrate incoming_bitrate_;
+  RateStatistics incoming_bitrate_;
   uint32_t ssrc_;
   int max_reordering_threshold_;  // In number of packets or sequence numbers.
 
@@ -108,10 +107,6 @@
   StreamStatistician* GetStatistician(uint32_t ssrc) const override;
   void SetMaxReorderingThreshold(int max_reordering_threshold) override;
 
-  // Implement Module.
-  void Process() override;
-  int64_t TimeUntilNextProcess() override;
-
   void RegisterRtcpStatisticsCallback(
       RtcpStatisticsCallback* callback) override;
 
@@ -127,9 +122,8 @@
 
   typedef std::map<uint32_t, StreamStatisticianImpl*> StatisticianImplMap;
 
-  Clock* clock_;
+  Clock* const clock_;
   rtc::CriticalSection receive_statistics_lock_;
-  int64_t last_rate_update_ms_;
   StatisticianImplMap statisticians_;
 
   RtcpStatisticsCallback* rtcp_stats_callback_;
diff --git a/modules/rtp_rtcp/source/rtp_receiver_video.h b/modules/rtp_rtcp/source/rtp_receiver_video.h
index 486eced..a8aaf5d 100644
--- a/modules/rtp_rtcp/source/rtp_receiver_video.h
+++ b/modules/rtp_rtcp/source/rtp_receiver_video.h
@@ -13,7 +13,6 @@
 
 #include "webrtc/base/onetimeevent.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/typedefs.h"
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
index be8ab34..dbd919d 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.cc
@@ -63,7 +63,8 @@
       send_frame_count_observer(nullptr),
       send_side_delay_observer(nullptr),
       event_log(nullptr),
-      send_packet_observer(nullptr) {}
+      send_packet_observer(nullptr),
+      retransmission_rate_limiter(nullptr) {}
 
 RtpRtcp* RtpRtcp::CreateRtpRtcp(const RtpRtcp::Configuration& configuration) {
   if (configuration.clock) {
@@ -89,7 +90,8 @@
                   configuration.send_frame_count_observer,
                   configuration.send_side_delay_observer,
                   configuration.event_log,
-                  configuration.send_packet_observer),
+                  configuration.send_packet_observer,
+                  configuration.retransmission_rate_limiter),
       rtcp_sender_(configuration.audio,
                    configuration.clock,
                    configuration.receive_statistics,
@@ -820,10 +822,6 @@
   return rtp_sender_.RED(payload_type);
 }
 
-void ModuleRtpRtcpImpl::SetTargetSendBitrate(uint32_t bitrate_bps) {
-  rtp_sender_.SetTargetBitrate(bitrate_bps);
-}
-
 int32_t ModuleRtpRtcpImpl::SetKeyFrameRequestMethod(
     const KeyFrameRequestMethod method) {
   key_frame_req_method_ = method;
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl.h b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
index 369cdca..ff3f01a 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl.h
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl.h
@@ -285,8 +285,6 @@
   // Send a request for a keyframe.
   int32_t RequestKeyFrame() override;
 
-  void SetTargetSendBitrate(uint32_t bitrate_bps) override;
-
   void SetGenericFECStatus(bool enable,
                            uint8_t payload_type_red,
                            uint8_t payload_type_fec) override;
diff --git a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
index 98269cf..1e2cc61 100644
--- a/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_rtcp_impl_unittest.cc
@@ -15,6 +15,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
+#include "webrtc/base/rate_limiter.h"
 #include "webrtc/common_types.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@@ -37,6 +38,7 @@
 const uint8_t kBaseLayerTid = 0;
 const uint8_t kHigherLayerTid = 1;
 const uint16_t kSequenceNumber = 100;
+const int64_t kMaxRttMs = 1000;
 
 class RtcpRttStatsTestImpl : public RtcpRttStats {
  public:
@@ -99,7 +101,9 @@
 class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
  public:
   explicit RtpRtcpModule(SimulatedClock* clock)
-      : receive_statistics_(ReceiveStatistics::Create(clock)) {
+      : receive_statistics_(ReceiveStatistics::Create(clock)),
+        remote_ssrc_(0),
+        retransmission_rate_limiter_(clock, kMaxRttMs) {
     RtpRtcp::Configuration config;
     config.audio = false;
     config.clock = clock;
@@ -107,6 +111,7 @@
     config.receive_statistics = receive_statistics_.get();
     config.rtcp_packet_type_counter_observer = this;
     config.rtt_stats = &rtt_stats_;
+    config.retransmission_rate_limiter = &retransmission_rate_limiter_;
 
     impl_.reset(new ModuleRtpRtcpImpl(config));
     impl_->SetRTCPStatus(RtcpMode::kCompound);
@@ -121,6 +126,7 @@
   RtcpRttStatsTestImpl rtt_stats_;
   std::unique_ptr<ModuleRtpRtcpImpl> impl_;
   uint32_t remote_ssrc_;
+  RateLimiter retransmission_rate_limiter_;
 
   void SetRemoteSsrc(uint32_t ssrc) {
     remote_ssrc_ = ssrc;
diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc
index 4ee2524..25016e0 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -16,6 +16,7 @@
 
 #include "webrtc/base/checks.h"
 #include "webrtc/base/logging.h"
+#include "webrtc/base/rate_limiter.h"
 #include "webrtc/base/trace_event.h"
 #include "webrtc/base/timeutils.h"
 #include "webrtc/call.h"
@@ -33,6 +34,7 @@
 static const size_t kMaxPaddingLength = 224;
 static const int kSendSideDelayWindowMs = 1000;
 static const uint32_t kAbsSendTimeFraction = 18;
+static const int kBitrateStatisticsWindowMs = 1000;
 
 namespace {
 
@@ -63,47 +65,6 @@
 }
 }  // namespace
 
-RTPSender::BitrateAggregator::BitrateAggregator(
-    BitrateStatisticsObserver* bitrate_callback)
-    : callback_(bitrate_callback),
-      total_bitrate_observer_(*this),
-      retransmit_bitrate_observer_(*this),
-      ssrc_(0) {}
-
-void RTPSender::BitrateAggregator::OnStatsUpdated() const {
-  if (callback_) {
-    callback_->Notify(total_bitrate_observer_.statistics(),
-                      retransmit_bitrate_observer_.statistics(), ssrc_);
-  }
-}
-
-Bitrate::Observer* RTPSender::BitrateAggregator::total_bitrate_observer() {
-  return &total_bitrate_observer_;
-}
-Bitrate::Observer* RTPSender::BitrateAggregator::retransmit_bitrate_observer() {
-  return &retransmit_bitrate_observer_;
-}
-
-void RTPSender::BitrateAggregator::set_ssrc(uint32_t ssrc) {
-  ssrc_ = ssrc;
-}
-
-RTPSender::BitrateAggregator::BitrateObserver::BitrateObserver(
-    const BitrateAggregator& aggregator)
-    : aggregator_(aggregator) {}
-
-// Implements Bitrate::Observer.
-void RTPSender::BitrateAggregator::BitrateObserver::BitrateUpdated(
-    const BitrateStatistics& stats) {
-  statistics_ = stats;
-  aggregator_.OnStatsUpdated();
-}
-
-const BitrateStatistics&
-RTPSender::BitrateAggregator::BitrateObserver::statistics() const {
-  return statistics_;
-}
-
 RTPSender::RTPSender(
     bool audio,
     Clock* clock,
@@ -115,13 +76,12 @@
     FrameCountObserver* frame_count_observer,
     SendSideDelayObserver* send_side_delay_observer,
     RtcEventLog* event_log,
-    SendPacketObserver* send_packet_observer)
+    SendPacketObserver* send_packet_observer,
+    RateLimiter* retransmission_rate_limiter)
     : clock_(clock),
       // TODO(holmer): Remove this conversion?
       clock_delta_ms_(clock_->TimeInMilliseconds() - rtc::TimeMillis()),
       random_(clock_->TimeInMicroseconds()),
-      bitrates_(bitrate_callback),
-      total_bitrate_sent_(clock, bitrates_.total_bitrate_observer()),
       audio_configured_(audio),
       audio_(audio ? new RTPSenderAudio(clock, this) : nullptr),
       video_(audio ? nullptr : new RTPSenderVideo(clock, this)),
@@ -140,18 +100,18 @@
       rotation_(kVideoRotation_0),
       video_rotation_active_(false),
       transport_sequence_number_(0),
-      // NACK.
-      nack_byte_count_times_(),
-      nack_byte_count_(),
-      nack_bitrate_(clock, bitrates_.retransmit_bitrate_observer()),
       playout_delay_active_(false),
       packet_history_(clock),
       // Statistics
-      rtp_stats_callback_(NULL),
+      rtp_stats_callback_(nullptr),
+      total_bitrate_sent_(kBitrateStatisticsWindowMs,
+                          RateStatistics::kBpsScale),
+      nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
       frame_count_observer_(frame_count_observer),
       send_side_delay_observer_(send_side_delay_observer),
       event_log_(event_log),
       send_packet_observer_(send_packet_observer),
+      bitrate_callback_(bitrate_callback),
       // RTP variables
       start_timestamp_forced_(false),
       start_timestamp_(0),
@@ -166,9 +126,7 @@
       last_packet_marker_bit_(false),
       csrcs_(),
       rtx_(kRtxOff),
-      target_bitrate_(0) {
-  memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
-  memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
+      retransmission_rate_limiter_(retransmission_rate_limiter) {
   // We need to seed the random generator for BuildPaddingPacket() below.
   // TODO(holmer,tommi): Note that TimeInMilliseconds might return 0 on Mac
   // early on in the process.
@@ -178,7 +136,6 @@
   ssrc_rtx_ = ssrc_db_->CreateSSRC();
   RTC_DCHECK(ssrc_rtx_ != 0);
 
-  bitrates_.set_ssrc(ssrc_);
   // Random start, 16 bits. Can't be 0.
   sequence_number_rtx_ = random_.Rand(1, kMaxInitRtpSeqNumber);
   sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
@@ -208,18 +165,11 @@
   }
 }
 
-void RTPSender::SetTargetBitrate(uint32_t bitrate) {
-  rtc::CritScope cs(&target_bitrate_critsect_);
-  target_bitrate_ = bitrate;
-}
-
-uint32_t RTPSender::GetTargetBitrate() {
-  rtc::CritScope cs(&target_bitrate_critsect_);
-  return target_bitrate_;
-}
-
 uint16_t RTPSender::ActualSendBitrateKbit() const {
-  return (uint16_t)(total_bitrate_sent_.BitrateNow() / 1000);
+  rtc::CritScope cs(&statistics_crit_);
+  return static_cast<uint16_t>(
+      total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0) /
+      1000);
 }
 
 uint32_t RTPSender::VideoBitrateSent() const {
@@ -237,7 +187,8 @@
 }
 
 uint32_t RTPSender::NackOverheadRate() const {
-  return nack_bitrate_.BitrateLast();
+  rtc::CritScope cs(&statistics_crit_);
+  return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
 int32_t RTPSender::SetTransmissionTimeOffset(int32_t transmission_time_offset) {
@@ -754,6 +705,12 @@
     return 0;
   }
 
+  // Check if we're overusing retransmission bitrate.
+  // TODO(sprang): Add histograms for nack success or failure reasons.
+  RTC_DCHECK(retransmission_rate_limiter_);
+  if (!retransmission_rate_limiter_->TryUseRate(length))
+    return -1;
+
   if (paced_sender_) {
     RtpUtility::RtpHeaderParser rtp_parser(data_buffer, length);
     RTPHeader header;
@@ -824,44 +781,14 @@
   TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
                "RTPSender::OnReceivedNACK", "num_seqnum",
                nack_sequence_numbers.size(), "avg_rtt", avg_rtt);
-  const int64_t now = clock_->TimeInMilliseconds();
-  uint32_t bytes_re_sent = 0;
-  uint32_t target_bitrate = GetTargetBitrate();
-
-  // Enough bandwidth to send NACK?
-  if (!ProcessNACKBitRate(now)) {
-    LOG(LS_INFO) << "NACK bitrate reached. Skip sending NACK response. Target "
-                 << target_bitrate;
-    return;
-  }
-
-  for (std::list<uint16_t>::const_iterator it = nack_sequence_numbers.begin();
-      it != nack_sequence_numbers.end(); ++it) {
-    const int32_t bytes_sent = ReSendPacket(*it, 5 + avg_rtt);
-    if (bytes_sent > 0) {
-      bytes_re_sent += bytes_sent;
-    } else if (bytes_sent == 0) {
-      // The packet has previously been resent.
-      // Try resending next packet in the list.
-      continue;
-    } else {
+  for (uint16_t seq_no : nack_sequence_numbers) {
+    const int32_t bytes_sent = ReSendPacket(seq_no, 5 + avg_rtt);
+    if (bytes_sent < 0) {
       // Failed to send one Sequence number. Give up the rest in this nack.
-      LOG(LS_WARNING) << "Failed resending RTP packet " << *it
+      LOG(LS_WARNING) << "Failed resending RTP packet " << seq_no
                       << ", Discard rest of packets";
       break;
     }
-    // Delay bandwidth estimate (RTT * BW).
-    if (target_bitrate != 0 && avg_rtt) {
-      // kbits/s * ms = bits => bits/8 = bytes
-      size_t target_bytes =
-          (static_cast<size_t>(target_bitrate / 1000) * avg_rtt) >> 3;
-      if (bytes_re_sent > target_bytes) {
-        break;  // Ignore the rest of the packets in the list.
-      }
-    }
-  }
-  if (bytes_re_sent > 0) {
-    UpdateNACKBitRate(bytes_re_sent, now);
   }
 }
 
@@ -870,51 +797,6 @@
   playout_delay_oracle_.OnReceivedRtcpReportBlocks(report_blocks);
 }
 
-bool RTPSender::ProcessNACKBitRate(uint32_t now) {
-  uint32_t num = 0;
-  size_t byte_count = 0;
-  const uint32_t kAvgIntervalMs = 1000;
-  uint32_t target_bitrate = GetTargetBitrate();
-
-  rtc::CritScope lock(&send_critsect_);
-
-  if (target_bitrate == 0) {
-    return true;
-  }
-  for (num = 0; num < NACK_BYTECOUNT_SIZE; ++num) {
-    if ((now - nack_byte_count_times_[num]) > kAvgIntervalMs) {
-      // Don't use data older than 1sec.
-      break;
-    } else {
-      byte_count += nack_byte_count_[num];
-    }
-  }
-  uint32_t time_interval = kAvgIntervalMs;
-  if (num == NACK_BYTECOUNT_SIZE) {
-    // More than NACK_BYTECOUNT_SIZE nack messages has been received
-    // during the last msg_interval.
-    if (nack_byte_count_times_[num - 1] <= now) {
-      time_interval = now - nack_byte_count_times_[num - 1];
-    }
-  }
-  return (byte_count * 8) < (target_bitrate / 1000 * time_interval);
-}
-
-void RTPSender::UpdateNACKBitRate(uint32_t bytes, int64_t now) {
-  rtc::CritScope lock(&send_critsect_);
-  if (bytes == 0)
-    return;
-  nack_bitrate_.Update(bytes);
-  // Save bitrate statistics.
-  // Shift all but first time.
-  for (int i = NACK_BYTECOUNT_SIZE - 2; i >= 0; i--) {
-    nack_byte_count_[i + 1] = nack_byte_count_[i];
-    nack_byte_count_times_[i + 1] = nack_byte_count_times_[i];
-  }
-  nack_byte_count_[0] = bytes;
-  nack_byte_count_times_[0] = now;
-}
-
 // Called from pacer when we can send the packet.
 bool RTPSender::TimeToSendPacket(uint16_t sequence_number,
                                  int64_t capture_time_ms,
@@ -1009,6 +891,7 @@
   StreamDataCounters* counters;
   // Get ssrc before taking statistics_crit_ to avoid possible deadlock.
   uint32_t ssrc = is_rtx ? RtxSsrc() : SSRC();
+  int64_t now_ms = clock_->TimeInMilliseconds();
 
   rtc::CritScope lock(&statistics_crit_);
   if (is_rtx) {
@@ -1017,22 +900,23 @@
     counters = &rtp_stats_;
   }
 
-  total_bitrate_sent_.Update(packet_length);
+  total_bitrate_sent_.Update(packet_length, now_ms);
 
-  if (counters->first_packet_time_ms == -1) {
+  if (counters->first_packet_time_ms == -1)
     counters->first_packet_time_ms = clock_->TimeInMilliseconds();
-  }
-  if (IsFecPacket(buffer, header)) {
+
+  if (IsFecPacket(buffer, header))
     counters->fec.AddPacket(packet_length, header);
-  }
+
   if (is_retransmit) {
     counters->retransmitted.AddPacket(packet_length, header);
+    nack_bitrate_sent_.Update(packet_length, now_ms);
   }
+
   counters->transmitted.AddPacket(packet_length, header);
 
-  if (rtp_stats_callback_) {
+  if (rtp_stats_callback_)
     rtp_stats_callback_->DataCountersUpdated(*counters, ssrc);
-  }
 }
 
 bool RTPSender::IsFecPacket(const uint8_t* buffer,
@@ -1180,13 +1064,18 @@
 }
 
 void RTPSender::ProcessBitrate() {
-  rtc::CritScope lock(&send_critsect_);
-  total_bitrate_sent_.Process();
-  nack_bitrate_.Process();
-  if (audio_configured_) {
+  if (!bitrate_callback_)
     return;
+  int64_t now_ms = clock_->TimeInMilliseconds();
+  uint32_t ssrc;
+  {
+    rtc::CritScope lock(&send_critsect_);
+    ssrc = ssrc_;
   }
-  video_->ProcessBitrate();
+
+  rtc::CritScope lock(&statistics_crit_);
+  bitrate_callback_->Notify(total_bitrate_sent_.Rate(now_ms).value_or(0),
+                            nack_bitrate_sent_.Rate(now_ms).value_or(0), ssrc);
 }
 
 size_t RTPSender::RtpHeaderLength() const {
@@ -1746,7 +1635,6 @@
       ssrc_db_->ReturnSSRC(ssrc_);
       ssrc_ = ssrc_db_->CreateSSRC();
       RTC_DCHECK(ssrc_ != 0);
-      bitrates_.set_ssrc(ssrc_);
     }
     // Don't initialize seq number if SSRC passed externally.
     if (!sequence_number_forced_ && !ssrc_forced_) {
@@ -1797,7 +1685,6 @@
   }
   ssrc_ = ssrc_db_->CreateSSRC();
   RTC_DCHECK(ssrc_ != 0);
-  bitrates_.set_ssrc(ssrc_);
   return ssrc_;
 }
 
@@ -1812,7 +1699,6 @@
   ssrc_db_->ReturnSSRC(ssrc_);
   ssrc_db_->RegisterSSRC(ssrc);
   ssrc_ = ssrc;
-  bitrates_.set_ssrc(ssrc_);
   if (!sequence_number_forced_) {
     sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
   }
@@ -1961,7 +1847,8 @@
 }
 
 uint32_t RTPSender::BitrateSent() const {
-  return total_bitrate_sent_.BitrateLast();
+  rtc::CritScope cs(&statistics_crit_);
+  return total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
 void RTPSender::SetRtpState(const RtpState& rtp_state) {
diff --git a/modules/rtp_rtcp/source/rtp_sender.h b/modules/rtp_rtcp/source/rtp_sender.h
index ffbcb81..1d6203a 100644
--- a/modules/rtp_rtcp/source/rtp_sender.h
+++ b/modules/rtp_rtcp/source/rtp_sender.h
@@ -20,10 +20,10 @@
 #include "webrtc/base/constructormagic.h"
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/random.h"
+#include "webrtc/base/rate_statistics.h"
 #include "webrtc/base/thread_annotations.h"
 #include "webrtc/common_types.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
 #include "webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h"
@@ -34,6 +34,7 @@
 
 namespace webrtc {
 
+class RateLimiter;
 class RTPSenderAudio;
 class RTPSenderVideo;
 class RtcEventLog;
@@ -93,7 +94,8 @@
             FrameCountObserver* frame_count_observer,
             SendSideDelayObserver* send_side_delay_observer,
             RtcEventLog* event_log,
-            SendPacketObserver* send_packet_observer);
+            SendPacketObserver* send_packet_observer,
+            RateLimiter* nack_rate_limiter);
 
   virtual ~RTPSender();
 
@@ -105,9 +107,6 @@
   uint32_t FecOverheadRate() const;
   uint32_t NackOverheadRate() const;
 
-  void SetTargetBitrate(uint32_t bitrate);
-  uint32_t GetTargetBitrate();
-
   // Includes size of RTP and FEC headers.
   size_t MaxDataPayloadLength() const override;
 
@@ -227,8 +226,6 @@
 
   int32_t ReSendPacket(uint16_t packet_id, int64_t min_resend_time = 0);
 
-  bool ProcessNACKBitRate(uint32_t now);
-
   // Feedback to decide when to stop sending playout delay.
   void OnReceivedRtcpReportBlocks(const ReportBlockList& report_blocks);
 
@@ -340,8 +337,6 @@
                          uint16_t sequence_number,
                          const std::vector<uint32_t>& csrcs) const;
 
-  void UpdateNACKBitRate(uint32_t bytes, int64_t now);
-
   bool PrepareAndSendPacket(uint8_t* buffer,
                             size_t length,
                             int64_t capture_time_ms,
@@ -406,45 +401,10 @@
                       bool is_retransmit);
   bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const;
 
-  class BitrateAggregator {
-   public:
-    explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback);
-
-    void OnStatsUpdated() const;
-
-    Bitrate::Observer* total_bitrate_observer();
-    Bitrate::Observer* retransmit_bitrate_observer();
-    void set_ssrc(uint32_t ssrc);
-
-   private:
-    // We assume that these observers are called on the same thread, which is
-    // true for RtpSender as they are called on the Process thread.
-    class BitrateObserver : public Bitrate::Observer {
-     public:
-      explicit BitrateObserver(const BitrateAggregator& aggregator);
-
-      // Implements Bitrate::Observer.
-      void BitrateUpdated(const BitrateStatistics& stats) override;
-      const BitrateStatistics& statistics() const;
-
-     private:
-      BitrateStatistics statistics_;
-      const BitrateAggregator& aggregator_;
-    };
-
-    BitrateStatisticsObserver* const callback_;
-    BitrateObserver total_bitrate_observer_;
-    BitrateObserver retransmit_bitrate_observer_;
-    uint32_t ssrc_;
-  };
-
   Clock* const clock_;
   const int64_t clock_delta_ms_;
   Random random_ GUARDED_BY(send_critsect_);
 
-  BitrateAggregator bitrates_;
-  Bitrate total_bitrate_sent_;
-
   const bool audio_configured_;
   const std::unique_ptr<RTPSenderAudio> audio_;
   const std::unique_ptr<RTPSenderVideo> video_;
@@ -470,11 +430,6 @@
   bool video_rotation_active_;
   uint16_t transport_sequence_number_;
 
-  // NACK
-  uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE];
-  size_t nack_byte_count_[NACK_BYTECOUNT_SIZE];
-  Bitrate nack_bitrate_;
-
   // Tracks the current request for playout delay limits from application
   // and decides whether the current RTP frame should include the playout
   // delay extension on header.
@@ -490,10 +445,13 @@
   StreamDataCounters rtp_stats_ GUARDED_BY(statistics_crit_);
   StreamDataCounters rtx_rtp_stats_ GUARDED_BY(statistics_crit_);
   StreamDataCountersCallback* rtp_stats_callback_ GUARDED_BY(statistics_crit_);
+  RateStatistics total_bitrate_sent_ GUARDED_BY(statistics_crit_);
+  RateStatistics nack_bitrate_sent_ GUARDED_BY(statistics_crit_);
   FrameCountObserver* const frame_count_observer_;
   SendSideDelayObserver* const send_side_delay_observer_;
   RtcEventLog* const event_log_;
   SendPacketObserver* const send_packet_observer_;
+  BitrateStatisticsObserver* const bitrate_callback_;
 
   // RTP variables
   bool start_timestamp_forced_ GUARDED_BY(send_critsect_);
@@ -516,12 +474,7 @@
   // Mapping rtx_payload_type_map_[associated] = rtx.
   std::map<int8_t, int8_t> rtx_payload_type_map_ GUARDED_BY(send_critsect_);
 
-  // Note: Don't access this variable directly, always go through
-  // SetTargetBitrateKbps or GetTargetBitrateKbps. Also remember
-  // that by the time the function returns there is no guarantee
-  // that the target bitrate is still valid.
-  rtc::CriticalSection target_bitrate_critsect_;
-  uint32_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_);
+  RateLimiter* const retransmission_rate_limiter_;
 
   RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSender);
 };
diff --git a/modules/rtp_rtcp/source/rtp_sender_unittest.cc b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
index f0b6411..99cef00 100644
--- a/modules/rtp_rtcp/source/rtp_sender_unittest.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_unittest.cc
@@ -15,6 +15,7 @@
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 #include "webrtc/base/buffer.h"
+#include "webrtc/base/rate_limiter.h"
 #include "webrtc/call/mock/mock_rtc_event_log.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
@@ -133,11 +134,11 @@
       : fake_clock_(kStartTime),
         mock_rtc_event_log_(),
         mock_paced_sender_(),
+        retransmission_rate_limiter_(&fake_clock_, 1000),
         rtp_sender_(),
         payload_(kPayload),
         transport_(),
-        kMarkerBit(true) {
-  }
+        kMarkerBit(true) {}
 
   void SetUp() override { SetUpRtpSender(true); }
 
@@ -145,7 +146,8 @@
     rtp_sender_.reset(new RTPSender(
         false, &fake_clock_, &transport_, pacer ? &mock_paced_sender_ : nullptr,
         &seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
-        &mock_rtc_event_log_, &send_packet_observer_));
+        &mock_rtc_event_log_, &send_packet_observer_,
+        &retransmission_rate_limiter_));
     rtp_sender_->SetSequenceNumber(kSeqNum);
   }
 
@@ -154,6 +156,7 @@
   MockRtpPacketSender mock_paced_sender_;
   MockTransportSequenceNumberAllocator seq_num_allocator_;
   MockSendPacketObserver send_packet_observer_;
+  RateLimiter retransmission_rate_limiter_;
   std::unique_ptr<RTPSender> rtp_sender_;
   int payload_;
   LoopbackTransportTest transport_;
@@ -743,7 +746,6 @@
   EXPECT_EQ(
       0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
                                                  kAbsoluteSendTimeExtensionId));
-  rtp_sender_->SetTargetBitrate(300000);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   int rtp_length_int = rtp_sender_->BuildRTPheader(
       packet_, kPayload, kMarkerBit, kTimestamp, capture_time_ms);
@@ -797,7 +799,6 @@
   EXPECT_EQ(
       0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
                                                  kAbsoluteSendTimeExtensionId));
-  rtp_sender_->SetTargetBitrate(300000);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   int rtp_length_int = rtp_sender_->BuildRTPheader(
       packet_, kPayload, kMarkerBit, kTimestamp, capture_time_ms);
@@ -879,7 +880,6 @@
                                          kAbsoluteSendTimeExtensionId);
   webrtc::RTPHeader rtp_header;
 
-  rtp_sender_->SetTargetBitrate(300000);
   int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
   int rtp_length_int = rtp_sender_->BuildRTPheader(
       packet_, kPayload, kMarkerBit, timestamp, capture_time_ms);
@@ -1011,7 +1011,7 @@
   rtp_sender_.reset(new RTPSender(
       false, &fake_clock_, &transport_, &mock_paced_sender_,
       nullptr /* TransportSequenceNumberAllocator */, nullptr, nullptr, nullptr,
-      nullptr, nullptr, &send_packet_observer_));
+      nullptr, nullptr, &send_packet_observer_, nullptr));
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetStorePacketsStatus(true, 10);
 
@@ -1029,7 +1029,7 @@
   MockTransport transport;
   rtp_sender_.reset(new RTPSender(
       false, &fake_clock_, &transport, &mock_paced_sender_, nullptr, nullptr,
-      nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr));
+      nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr, nullptr));
 
   rtp_sender_->SetSequenceNumber(kSeqNum);
   rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload);
@@ -1054,7 +1054,6 @@
                                          kTransmissionTimeOffsetExtensionId);
   rtp_parser->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
                                          kAbsoluteSendTimeExtensionId);
-  rtp_sender_->SetTargetBitrate(300000);
   const size_t kNumPayloadSizes = 10;
   const size_t kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700,
                                                   750, 800, 850, 900, 950};
@@ -1176,7 +1175,7 @@
 
   rtp_sender_.reset(new RTPSender(
       false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr, nullptr,
-      nullptr, &callback, nullptr, nullptr, nullptr));
+      nullptr, &callback, nullptr, nullptr, nullptr, nullptr));
 
   char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
   const uint8_t payload_type = 127;
@@ -1213,30 +1212,39 @@
 TEST_F(RtpSenderTest, BitrateCallbacks) {
   class TestCallback : public BitrateStatisticsObserver {
    public:
-    TestCallback() : BitrateStatisticsObserver(), num_calls_(0), ssrc_(0) {}
+    TestCallback()
+        : BitrateStatisticsObserver(),
+          num_calls_(0),
+          ssrc_(0),
+          total_bitrate_(0),
+          retransmit_bitrate_(0) {}
     virtual ~TestCallback() {}
 
-    void Notify(const BitrateStatistics& total_stats,
-                const BitrateStatistics& retransmit_stats,
+    void Notify(uint32_t total_bitrate,
+                uint32_t retransmit_bitrate,
                 uint32_t ssrc) override {
       ++num_calls_;
       ssrc_ = ssrc;
-      total_stats_ = total_stats;
-      retransmit_stats_ = retransmit_stats;
+      total_bitrate_ = total_bitrate;
+      retransmit_bitrate_ = retransmit_bitrate;
     }
 
     uint32_t num_calls_;
     uint32_t ssrc_;
-    BitrateStatistics total_stats_;
-    BitrateStatistics retransmit_stats_;
+    uint32_t total_bitrate_;
+    uint32_t retransmit_bitrate_;
   } callback;
   rtp_sender_.reset(new RTPSender(false, &fake_clock_, &transport_, nullptr,
                                   nullptr, nullptr, &callback, nullptr, nullptr,
-                                  nullptr, nullptr));
+                                  nullptr, nullptr, nullptr));
 
-  // Simulate kNumPackets sent with kPacketInterval ms intervals.
-  const uint32_t kNumPackets = 15;
+  // Simulate kNumPackets sent with kPacketInterval ms intervals, with the
+  // number of packets selected so that we fill (but don't overflow) the one
+  // second averaging window.
+  const uint32_t kWindowSizeMs = 1000;
   const uint32_t kPacketInterval = 20;
+  const uint32_t kNumPackets =
+      (kWindowSizeMs - kPacketInterval) / kPacketInterval;
   // Overhead = 12 bytes RTP header + 1 byte generic header.
   const uint32_t kPacketOverhead = 13;
 
@@ -1250,7 +1258,6 @@
 
   // Initial process call so we get a new time window.
   rtp_sender_->ProcessBitrate();
-  uint64_t start_time = fake_clock_.CurrentNtpInMilliseconds();
 
   // Send a few frames.
   for (uint32_t i = 0; i < kNumPackets; ++i) {
@@ -1262,17 +1269,18 @@
 
   rtp_sender_->ProcessBitrate();
 
-  const uint32_t expected_packet_rate = 1000 / kPacketInterval;
-
   // We get one call for every stats updated, thus two calls since both the
   // stream stats and the retransmit stats are updated once.
   EXPECT_EQ(2u, callback.num_calls_);
   EXPECT_EQ(ssrc, callback.ssrc_);
-  EXPECT_EQ(start_time + (kNumPackets * kPacketInterval),
-            callback.total_stats_.timestamp_ms);
-  EXPECT_EQ(expected_packet_rate, callback.total_stats_.packet_rate);
-  EXPECT_EQ((kPacketOverhead + sizeof(payload)) * 8 * expected_packet_rate,
-            callback.total_stats_.bitrate_bps);
+  const uint32_t kTotalPacketSize = kPacketOverhead + sizeof(payload);
+  // Bitrate measured over delta between last and first timestamp, plus one.
+  const uint32_t kExpectedWindowMs = kNumPackets * kPacketInterval + 1;
+  const uint32_t kExpectedBitsAccumulated = kTotalPacketSize * kNumPackets * 8;
+  const uint32_t kExpectedRateBps =
+      (kExpectedBitsAccumulated * 1000 + (kExpectedWindowMs / 2)) /
+      kExpectedWindowMs;
+  EXPECT_EQ(kExpectedRateBps, callback.total_bitrate_);
 
   rtp_sender_.reset();
 }
@@ -1285,7 +1293,7 @@
     payload_ = kAudioPayload;
     rtp_sender_.reset(new RTPSender(true, &fake_clock_, &transport_, nullptr,
                                     nullptr, nullptr, nullptr, nullptr, nullptr,
-                                    nullptr, nullptr));
+                                    nullptr, nullptr, nullptr));
     rtp_sender_->SetSequenceNumber(kSeqNum);
   }
 };
@@ -1553,9 +1561,9 @@
   const int32_t kPacketSize = 1400;
   const int32_t kNumPackets = 30;
 
+  retransmission_rate_limiter_.SetMaxRate(kPacketSize * kNumPackets * 8);
+
   rtp_sender_->SetStorePacketsStatus(true, kNumPackets);
-  // Set bitrate (in kbps) to fit kNumPackets á kPacketSize bytes in one second.
-  rtp_sender_->SetTargetBitrate(kNumPackets * kPacketSize * 8);
   const uint16_t kStartSequenceNumber = rtp_sender_->SequenceNumber();
   std::list<uint16_t> sequence_numbers;
   for (int32_t i = 0; i < kNumPackets; ++i) {
@@ -1573,6 +1581,9 @@
   rtp_sender_->OnReceivedNACK(sequence_numbers, 0);
   EXPECT_EQ(kNumPackets * 2, transport_.packets_sent_);
 
+  // Must be at least 5ms in between retransmission attempts.
+  fake_clock_.AdvanceTimeMilliseconds(5);
+
   // Resending should not work, bandwidth exceeded.
   rtp_sender_->OnReceivedNACK(sequence_numbers, 0);
   EXPECT_EQ(kNumPackets * 2, transport_.packets_sent_);
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.cc b/modules/rtp_rtcp/source/rtp_sender_video.cc
index 3affb31..378ef13 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -31,6 +31,7 @@
 
 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender)
     : _rtpSender(*rtpSender),
+      clock_(clock),
       _videoType(kRtpVideoGeneric),
       _retransmissionSettings(kRetransmitBaseLayer),
       // Generic FEC
@@ -41,8 +42,8 @@
       delta_fec_params_(),
       key_fec_params_(),
       producer_fec_(&fec_),
-      _fecOverheadRate(clock, NULL),
-      _videoBitrate(clock, NULL) {
+      fec_bitrate_(1000, RateStatistics::kBpsScale),
+      video_bitrate_(1000, RateStatistics::kBpsScale) {
   memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
   memset(&key_fec_params_, 0, sizeof(key_fec_params_));
   delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
@@ -95,7 +96,9 @@
   if (_rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length,
                                capture_time_ms, storage,
                                RtpPacketSender::kLowPriority) == 0) {
-    _videoBitrate.Update(payload_length + rtp_header_length);
+    rtc::CritScope cs(&stats_crit_);
+    video_bitrate_.Update(payload_length + rtp_header_length,
+                          clock_->TimeInMilliseconds());
     TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
                          "Video::PacketNormal", "timestamp", capture_timestamp,
                          "seqnum", seq_num);
@@ -141,7 +144,8 @@
           red_packet->data(), red_packet->length() - rtp_header_length,
           rtp_header_length, capture_time_ms, media_packet_storage,
           RtpPacketSender::kLowPriority) == 0) {
-    _videoBitrate.Update(red_packet->length());
+    rtc::CritScope cs(&stats_crit_);
+    video_bitrate_.Update(red_packet->length(), clock_->TimeInMilliseconds());
     TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
                          "Video::PacketRed", "timestamp", capture_timestamp,
                          "seqnum", media_seq_num);
@@ -153,7 +157,8 @@
             fec_packet->data(), fec_packet->length() - rtp_header_length,
             rtp_header_length, capture_time_ms, fec_storage,
             RtpPacketSender::kLowPriority) == 0) {
-      _fecOverheadRate.Update(fec_packet->length());
+      rtc::CritScope cs(&stats_crit_);
+      fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
       TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
                            "Video::PacketFec", "timestamp", capture_timestamp,
                            "seqnum", next_fec_sequence_number);
@@ -337,17 +342,14 @@
   return 0;
 }
 
-void RTPSenderVideo::ProcessBitrate() {
-  _videoBitrate.Process();
-  _fecOverheadRate.Process();
-}
-
 uint32_t RTPSenderVideo::VideoBitrateSent() const {
-  return _videoBitrate.BitrateLast();
+  rtc::CritScope cs(&stats_crit_);
+  return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
 uint32_t RTPSenderVideo::FecOverheadRate() const {
-  return _fecOverheadRate.BitrateLast();
+  rtc::CritScope cs(&stats_crit_);
+  return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
 }
 
 int RTPSenderVideo::SelectiveRetransmissions() const {
diff --git a/modules/rtp_rtcp/source/rtp_sender_video.h b/modules/rtp_rtcp/source/rtp_sender_video.h
index 8307b83..7ce889b 100644
--- a/modules/rtp_rtcp/source/rtp_sender_video.h
+++ b/modules/rtp_rtcp/source/rtp_sender_video.h
@@ -15,10 +15,10 @@
 
 #include "webrtc/base/criticalsection.h"
 #include "webrtc/base/onetimeevent.h"
+#include "webrtc/base/rate_statistics.h"
 #include "webrtc/base/thread_annotations.h"
 #include "webrtc/common_types.h"
 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
-#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
 #include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
 #include "webrtc/modules/rtp_rtcp/source/producer_fec.h"
 #include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
@@ -68,8 +68,6 @@
   void SetFecParameters(const FecProtectionParams* delta_params,
                         const FecProtectionParams* key_params);
 
-  void ProcessBitrate();
-
   uint32_t VideoBitrateSent() const;
   uint32_t FecOverheadRate() const;
 
@@ -95,9 +93,10 @@
                             bool protect);
 
   RTPSenderInterface& _rtpSender;
+  Clock* const clock_;
 
   // Should never be held when calling out of this class.
-  const rtc::CriticalSection crit_;
+  rtc::CriticalSection crit_;
 
   RtpVideoCodecTypes _videoType;
   int32_t _retransmissionSettings GUARDED_BY(crit_);
@@ -111,11 +110,12 @@
   FecProtectionParams key_fec_params_ GUARDED_BY(crit_);
   ProducerFec producer_fec_ GUARDED_BY(crit_);
 
+  rtc::CriticalSection stats_crit_;
   // Bitrate used for FEC payload, RED headers, RTP headers for FEC packets
   // and any padding overhead.
-  Bitrate _fecOverheadRate;
-  // Bitrate used for video payload and RTP headers
-  Bitrate _videoBitrate;
+  RateStatistics fec_bitrate_ GUARDED_BY(stats_crit_);
+  // Bitrate used for video payload and RTP headers.
+  RateStatistics video_bitrate_ GUARDED_BY(stats_crit_);
   OneTimeEvent first_frame_sent_;
 };
 }  // namespace webrtc
diff --git a/video/end_to_end_tests.cc b/video/end_to_end_tests.cc
index 8e3105f..21a6654 100644
--- a/video/end_to_end_tests.cc
+++ b/video/end_to_end_tests.cc
@@ -26,6 +26,7 @@
 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
 #include "webrtc/modules/rtp_rtcp/source/rtcp_utility.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
 #include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
 #include "webrtc/modules/video_coding/codecs/vp9/include/vp9.h"
@@ -1527,7 +1528,8 @@
       : EndToEndTest(::webrtc::EndToEndTest::kDefaultTimeoutMs),
         feedback_enabled_(feedback_enabled),
         num_video_streams_(num_video_streams),
-        num_audio_streams_(num_audio_streams) {
+        num_audio_streams_(num_audio_streams),
+        receiver_call_(nullptr) {
     // Only one stream of each supported for now.
     EXPECT_LE(num_video_streams, 1u);
     EXPECT_LE(num_audio_streams, 1u);
@@ -2539,6 +2541,16 @@
 
    private:
     Action OnSendRtp(const uint8_t* packet, size_t length) override {
+      // Drop every 25th packet => 4% loss.
+      static const int kPacketLossFrac = 25;
+      RTPHeader header;
+      RtpUtility::RtpHeaderParser parser(packet, length);
+      if (parser.Parse(&header) &&
+          expected_send_ssrcs_.find(header.ssrc) !=
+              expected_send_ssrcs_.end() &&
+          header.sequenceNumber % kPacketLossFrac == 0) {
+        return DROP_PACKET;
+      }
       check_stats_event_.Set();
       return SEND_PACKET;
     }
@@ -2639,8 +2651,8 @@
       for (std::map<uint32_t, VideoSendStream::StreamStats>::const_iterator it =
                stats.substreams.begin();
            it != stats.substreams.end(); ++it) {
-        EXPECT_TRUE(expected_send_ssrcs_.find(it->first) !=
-                    expected_send_ssrcs_.end());
+        if (expected_send_ssrcs_.find(it->first) == expected_send_ssrcs_.end())
+          continue;  // Probably RTX.
 
         send_stats_filled_[CompoundKey("CapturedFrameRate", it->first)] |=
             stats.input_frame_rate != 0;
@@ -2658,10 +2670,14 @@
             stream_stats.rtp_stats.retransmitted.packets != 0 ||
             stream_stats.rtp_stats.transmitted.packets != 0;
 
-        send_stats_filled_[CompoundKey("BitrateStatisticsObserver",
+        send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Total",
                                        it->first)] |=
             stream_stats.total_bitrate_bps != 0;
 
+        send_stats_filled_[CompoundKey("BitrateStatisticsObserver.Retransmit",
+                                       it->first)] |=
+            stream_stats.retransmit_bitrate_bps != 0;
+
         send_stats_filled_[CompoundKey("FrameCountObserver", it->first)] |=
             stream_stats.frame_counts.delta_frames != 0 ||
             stream_stats.frame_counts.key_frames != 0;
@@ -2692,10 +2708,8 @@
     }
 
     bool AllStatsFilled(const std::map<std::string, bool>& stats_map) {
-      for (std::map<std::string, bool>::const_iterator it = stats_map.begin();
-           it != stats_map.end();
-           ++it) {
-        if (!it->second)
+      for (const auto& stat : stats_map) {
+        if (!stat.second)
           return false;
       }
       return true;
@@ -2718,9 +2732,18 @@
         VideoSendStream::Config* send_config,
         std::vector<VideoReceiveStream::Config>* receive_configs,
         VideoEncoderConfig* encoder_config) override {
+      // Set low rates to avoid waiting for rampup.
+      for (size_t i = 0; i < encoder_config->streams.size(); ++i) {
+        encoder_config->streams[i].min_bitrate_bps = 10000;
+        encoder_config->streams[i].target_bitrate_bps = 15000;
+        encoder_config->streams[i].max_bitrate_bps = 20000;
+      }
       send_config->pre_encode_callback = this;  // Used to inject delay.
       expected_cname_ = send_config->rtp.c_name = "SomeCName";
 
+      send_config->rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+      send_config->rtp.rtx.payload_type = kSendRtxPayloadType;
+
       const std::vector<uint32_t>& ssrcs = send_config->rtp.ssrcs;
       for (size_t i = 0; i < ssrcs.size(); ++i) {
         expected_send_ssrcs_.insert(ssrcs[i]);
@@ -2728,7 +2751,17 @@
             (*receive_configs)[i].rtp.remote_ssrc);
         (*receive_configs)[i].render_delay_ms = kExpectedRenderDelayMs;
         (*receive_configs)[i].renderer = &receive_stream_renderer_;
+        (*receive_configs)[i].rtp.nack.rtp_history_ms = kNackRtpHistoryMs;
+
+        (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].ssrc =
+            kSendRtxSsrcs[i];
+        (*receive_configs)[i].rtp.rtx[kFakeVideoSendPayloadType].payload_type =
+            kSendRtxPayloadType;
       }
+
+      for (size_t i = 0; i < kNumSsrcs; ++i)
+        send_config->rtp.rtx.ssrcs.push_back(kSendRtxSsrcs[i]);
+
       // Use a delayed encoder to make sure we see CpuOveruseMetrics stats that
       // are non-zero.
       send_config->encoder_settings.encoder = &encoder_;
diff --git a/video/payload_router.cc b/video/payload_router.cc
index 2143902..798325a 100644
--- a/video/payload_router.cc
+++ b/video/payload_router.cc
@@ -167,25 +167,6 @@
       encoded_image._length, fragmentation, &rtp_video_header);
 }
 
-void PayloadRouter::SetTargetSendBitrate(uint32_t bitrate_bps) {
-  rtc::CritScope lock(&crit_);
-  RTC_DCHECK_LE(streams_.size(), rtp_modules_.size());
-
-  // TODO(sprang): Rebase https://codereview.webrtc.org/1913073002/ on top of
-  // this.
-  int bitrate_remainder = bitrate_bps;
-  for (size_t i = 0; i < streams_.size() && bitrate_remainder > 0; ++i) {
-    int stream_bitrate = 0;
-    if (streams_[i].max_bitrate_bps > bitrate_remainder) {
-      stream_bitrate = bitrate_remainder;
-    } else {
-      stream_bitrate = streams_[i].max_bitrate_bps;
-    }
-    bitrate_remainder -= stream_bitrate;
-    rtp_modules_[i]->SetTargetSendBitrate(stream_bitrate);
-  }
-}
-
 size_t PayloadRouter::MaxPayloadLength() const {
   size_t min_payload_length = DefaultMaxPayloadLength();
   rtc::CritScope lock(&crit_);
diff --git a/video/payload_router.h b/video/payload_router.h
index ce65bae..9c66bd0 100644
--- a/video/payload_router.h
+++ b/video/payload_router.h
@@ -50,9 +50,6 @@
                   const CodecSpecificInfo* codec_specific_info,
                   const RTPFragmentationHeader* fragmentation) override;
 
-  // Configures current target bitrate.
-  void SetTargetSendBitrate(uint32_t bitrate_bps);
-
   // Returns the maximum allowed data payload length, given the configured MTU
   // and RTP headers.
   size_t MaxPayloadLength() const;
diff --git a/video/payload_router_unittest.cc b/video/payload_router_unittest.cc
index 5b66121..62dba29 100644
--- a/video/payload_router_unittest.cc
+++ b/video/payload_router_unittest.cc
@@ -186,25 +186,4 @@
       .WillOnce(Return(kTestMinPayloadLength));
   EXPECT_EQ(kTestMinPayloadLength, payload_router.MaxPayloadLength());
 }
-
-TEST(PayloadRouterTest, SetTargetSendBitrates) {
-  NiceMock<MockRtpRtcp> rtp_1;
-  NiceMock<MockRtpRtcp> rtp_2;
-  std::vector<RtpRtcp*> modules;
-  modules.push_back(&rtp_1);
-  modules.push_back(&rtp_2);
-  PayloadRouter payload_router(modules, 42);
-  std::vector<VideoStream> streams(2);
-  streams[0].max_bitrate_bps = 10000;
-  streams[1].max_bitrate_bps = 100000;
-  payload_router.SetSendStreams(streams);
-
-  const uint32_t bitrate_1 = 10000;
-  const uint32_t bitrate_2 = 76543;
-  EXPECT_CALL(rtp_1, SetTargetSendBitrate(bitrate_1))
-      .Times(1);
-  EXPECT_CALL(rtp_2, SetTargetSendBitrate(bitrate_2))
-      .Times(1);
-  payload_router.SetTargetSendBitrate(bitrate_1 + bitrate_2);
-}
 }  // namespace webrtc
diff --git a/video/rtp_stream_receiver.cc b/video/rtp_stream_receiver.cc
index 90e449c..4caf55a 100644
--- a/video/rtp_stream_receiver.cc
+++ b/video/rtp_stream_receiver.cc
@@ -58,6 +58,7 @@
   configuration.send_packet_observer = nullptr;
   configuration.bandwidth_callback = nullptr;
   configuration.transport_feedback_callback = nullptr;
+  configuration.retransmission_rate_limiter = nullptr;
 
   std::unique_ptr<RtpRtcp> rtp_rtcp(RtpRtcp::CreateRtpRtcp(configuration));
   rtp_rtcp->SetSendingStatus(false);
@@ -185,12 +186,10 @@
   // Stats callback for CNAME changes.
   rtp_rtcp_->RegisterRtcpStatisticsCallback(receive_stats_proxy);
 
-  process_thread_->RegisterModule(rtp_receive_statistics_.get());
   process_thread_->RegisterModule(rtp_rtcp_.get());
 }
 
 RtpStreamReceiver::~RtpStreamReceiver() {
-  process_thread_->DeRegisterModule(rtp_receive_statistics_.get());
   process_thread_->DeRegisterModule(rtp_rtcp_.get());
 
   packet_router_->RemoveRtpModule(rtp_rtcp_.get());
diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc
index 6815eb3..8852de1 100644
--- a/video/send_statistics_proxy.cc
+++ b/video/send_statistics_proxy.cc
@@ -564,16 +564,16 @@
     uma_container_->first_rtp_stats_time_ms_ = clock_->TimeInMilliseconds();
 }
 
-void SendStatisticsProxy::Notify(const BitrateStatistics& total_stats,
-                                 const BitrateStatistics& retransmit_stats,
+void SendStatisticsProxy::Notify(uint32_t total_bitrate_bps,
+                                 uint32_t retransmit_bitrate_bps,
                                  uint32_t ssrc) {
   rtc::CritScope lock(&crit_);
   VideoSendStream::StreamStats* stats = GetStatsEntry(ssrc);
   if (!stats)
     return;
 
-  stats->total_bitrate_bps = total_stats.bitrate_bps;
-  stats->retransmit_bitrate_bps = retransmit_stats.bitrate_bps;
+  stats->total_bitrate_bps = total_bitrate_bps;
+  stats->retransmit_bitrate_bps = retransmit_bitrate_bps;
 }
 
 void SendStatisticsProxy::FrameCountUpdated(const FrameCounts& frame_counts,
diff --git a/video/send_statistics_proxy.h b/video/send_statistics_proxy.h
index fa8b3ec..2c9225f 100644
--- a/video/send_statistics_proxy.h
+++ b/video/send_statistics_proxy.h
@@ -85,8 +85,8 @@
                            uint32_t ssrc) override;
 
   // From BitrateStatisticsObserver.
-  void Notify(const BitrateStatistics& total_stats,
-              const BitrateStatistics& retransmit_stats,
+  void Notify(uint32_t total_bitrate_bps,
+              uint32_t retransmit_bitrate_bps,
               uint32_t ssrc) override;
 
   // From FrameCountObserver.
diff --git a/video/send_statistics_proxy_unittest.cc b/video/send_statistics_proxy_unittest.cc
index 2bf038d..ad51f2a 100644
--- a/video/send_statistics_proxy_unittest.cc
+++ b/video/send_statistics_proxy_unittest.cc
@@ -226,24 +226,24 @@
 TEST_F(SendStatisticsProxyTest, Bitrate) {
   BitrateStatisticsObserver* observer = statistics_proxy_.get();
   for (const auto& ssrc : config_.rtp.ssrcs) {
-    BitrateStatistics total;
-    BitrateStatistics retransmit;
+    uint32_t total;
+    uint32_t retransmit;
     // Use ssrc as bitrate_bps to get a unique value for each stream.
-    total.bitrate_bps = ssrc;
-    retransmit.bitrate_bps = ssrc + 1;
+    total = ssrc;
+    retransmit = ssrc + 1;
     observer->Notify(total, retransmit, ssrc);
-    expected_.substreams[ssrc].total_bitrate_bps = total.bitrate_bps;
-    expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit.bitrate_bps;
+    expected_.substreams[ssrc].total_bitrate_bps = total;
+    expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
   }
   for (const auto& ssrc : config_.rtp.rtx.ssrcs) {
-    BitrateStatistics total;
-    BitrateStatistics retransmit;
+    uint32_t total;
+    uint32_t retransmit;
     // Use ssrc as bitrate_bps to get a unique value for each stream.
-    total.bitrate_bps = ssrc;
-    retransmit.bitrate_bps = ssrc + 1;
+    total = ssrc;
+    retransmit = ssrc + 1;
     observer->Notify(total, retransmit, ssrc);
-    expected_.substreams[ssrc].total_bitrate_bps = total.bitrate_bps;
-    expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit.bitrate_bps;
+    expected_.substreams[ssrc].total_bitrate_bps = total;
+    expected_.substreams[ssrc].retransmit_bitrate_bps = retransmit;
   }
 
   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
@@ -397,8 +397,8 @@
   rtcp_callback->StatisticsUpdated(rtcp_stats, excluded_ssrc);
 
   // From BitrateStatisticsObserver.
-  BitrateStatistics total;
-  BitrateStatistics retransmit;
+  uint32_t total = 0;
+  uint32_t retransmit = 0;
   BitrateStatisticsObserver* bitrate_observer = statistics_proxy_.get();
   bitrate_observer->Notify(total, retransmit, excluded_ssrc);
 
@@ -484,8 +484,7 @@
 }
 
 TEST_F(SendStatisticsProxyTest, ClearsBitratesFromInactiveSsrcs) {
-  BitrateStatistics bitrate;
-  bitrate.bitrate_bps = 42;
+  uint32_t bitrate = 42;
   BitrateStatisticsObserver* observer = statistics_proxy_.get();
   observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[0]);
   observer->Notify(bitrate, bitrate, config_.rtp.ssrcs[1]);
@@ -493,9 +492,9 @@
   statistics_proxy_->OnInactiveSsrc(config_.rtp.ssrcs[1]);
 
   VideoSendStream::Stats stats = statistics_proxy_->GetStats();
-  EXPECT_EQ(static_cast<int>(bitrate.bitrate_bps),
+  EXPECT_EQ(static_cast<int>(bitrate),
             stats.substreams[config_.rtp.ssrcs[0]].total_bitrate_bps);
-  EXPECT_EQ(static_cast<int>(bitrate.bitrate_bps),
+  EXPECT_EQ(static_cast<int>(bitrate),
             stats.substreams[config_.rtp.ssrcs[0]].retransmit_bitrate_bps);
   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].total_bitrate_bps);
   EXPECT_EQ(0, stats.substreams[config_.rtp.ssrcs[1]].retransmit_bitrate_bps);
diff --git a/video/video_send_stream.cc b/video/video_send_stream.cc
index cbc3e76..940e1cc 100644
--- a/video/video_send_stream.cc
+++ b/video/video_send_stream.cc
@@ -52,6 +52,7 @@
     SendStatisticsProxy* stats_proxy,
     SendDelayStats* send_delay_stats,
     RtcEventLog* event_log,
+    RateLimiter* retransmission_rate_limiter,
     size_t num_modules) {
   RTC_DCHECK_GT(num_modules, 0u);
   RtpRtcp::Configuration configuration;
@@ -73,6 +74,7 @@
   configuration.send_side_delay_observer = stats_proxy;
   configuration.send_packet_observer = send_delay_stats;
   configuration.event_log = event_log;
+  configuration.retransmission_rate_limiter = retransmission_rate_limiter;
 
   std::vector<RtpRtcp*> modules;
   for (size_t i = 0; i < num_modules; ++i) {
@@ -428,6 +430,7 @@
           &stats_proxy_,
           send_delay_stats,
           event_log,
+          congestion_controller_->GetRetransmissionRateLimiter(),
           config_.rtp.ssrcs.size())),
       payload_router_(rtp_rtcp_modules_, config.encoder_settings.payload_type),
       input_(&encoder_wakeup_event_,
@@ -883,7 +886,6 @@
 uint32_t VideoSendStream::OnBitrateUpdated(uint32_t bitrate_bps,
                                            uint8_t fraction_loss,
                                            int64_t rtt) {
-  payload_router_.SetTargetSendBitrate(bitrate_bps);
   // Get the encoder target rate. It is the estimated network rate -
   // protection overhead.
   uint32_t encoder_target_rate_bps =
diff --git a/webrtc_tests.gypi b/webrtc_tests.gypi
index 56ae1cc..f1217eb 100644
--- a/webrtc_tests.gypi
+++ b/webrtc_tests.gypi
@@ -63,6 +63,7 @@
         'base/proxy_unittest.cc',
         'base/proxydetect_unittest.cc',
         'base/random_unittest.cc',
+        'base/rate_limiter_unittest.cc',
         'base/rate_statistics_unittest.cc',
         'base/ratelimiter_unittest.cc',
         'base/ratetracker_unittest.cc',