Update VideoStreamEncoder to use new VideoEncoder::SetRates() method.

This CL wires up the new SetRates() method of the video encoders, and
refactors a few things in the process:

Most notably, the VideoStreamEncoderInterface is update so that the
|target_headroom| parameter is replaced with |link_allocation|, meaning
that instead of indicating bitrate capacity in excess of the target
bitrate, it indicates to total network capacity allocated for the
stream including the target bitrate. This matches the VideoEncoder API.

The VideoEncoder::RateControlParameters struct gets a few new helper
methods.

In VideoStreamEncoder, instead of adding more fields to the
|last_observed_bitrate*| family, uses an optional struct that
inherits from VideoEncoder::RateControlParameters.

Bug: webrtc:10481
Change-Id: Iee3965531142ae9b964ed86c0d51db59b1cdd61c
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/131123
Commit-Queue: Erik Språng <sprang@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#27487}
diff --git a/api/video/video_stream_encoder_interface.h b/api/video/video_stream_encoder_interface.h
index b6fed6b..5463118 100644
--- a/api/video/video_stream_encoder_interface.h
+++ b/api/video/video_stream_encoder_interface.h
@@ -78,10 +78,13 @@
   // Request a key frame. Used for signalling from the remote receiver.
   virtual void SendKeyFrame() = 0;
 
-  // Set the currently estimated network properties. A |bitrate_bps|
+  // Set the currently estimated network properties. A |target_bitrate|
   // of zero pauses the encoder.
+  // |link_allocation| is the bandwidth available for this video stream on the
+  // network link. It is always at least |target_bitrate| but may be higher
+  // if we are not network constrained.
   virtual void OnBitrateUpdated(DataRate target_bitrate,
-                                DataRate target_headroom,
+                                DataRate link_allocation,
                                 uint8_t fraction_lost,
                                 int64_t round_trip_time_ms) = 0;
 
diff --git a/api/video_codecs/video_encoder.cc b/api/video_codecs/video_encoder.cc
index 46496c7..66ba9e4 100644
--- a/api/video_codecs/video_encoder.cc
+++ b/api/video_codecs/video_encoder.cc
@@ -101,6 +101,21 @@
 
 VideoEncoder::EncoderInfo::~EncoderInfo() = default;
 
+VideoEncoder::RateControlParameters::RateControlParameters()
+    : bitrate(VideoBitrateAllocation()),
+      framerate_fps(0.0),
+      bandwidth_allocation(DataRate::Zero()) {}
+
+VideoEncoder::RateControlParameters::RateControlParameters(
+    const VideoBitrateAllocation& bitrate,
+    double framerate_fps,
+    DataRate bandwidth_allocation)
+    : bitrate(bitrate),
+      framerate_fps(framerate_fps),
+      bandwidth_allocation(bandwidth_allocation) {}
+
+VideoEncoder::RateControlParameters::~RateControlParameters() = default;
+
 int32_t VideoEncoder::SetRates(uint32_t bitrate, uint32_t framerate) {
   RTC_NOTREACHED() << "SetRate(uint32_t, uint32_t) is deprecated.";
   return -1;
diff --git a/api/video_codecs/video_encoder.h b/api/video_codecs/video_encoder.h
index 0546c7d..eb9d750 100644
--- a/api/video_codecs/video_encoder.h
+++ b/api/video_codecs/video_encoder.h
@@ -194,6 +194,12 @@
   };
 
   struct RateControlParameters {
+    RateControlParameters();
+    RateControlParameters(const VideoBitrateAllocation& bitrate,
+                          double framerate_fps,
+                          DataRate bandwidth_allocation);
+    virtual ~RateControlParameters();
+
     // Target bitrate, per spatial/temporal layer.
     // A target bitrate of 0bps indicates a layer should not be encoded at all.
     VideoBitrateAllocation bitrate;
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index 643d30a..1c291e7 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -649,17 +649,18 @@
   encoder_target_rate_bps_ = rtp_video_sender_->GetPayloadBitrateBps();
   const uint32_t protection_bitrate_bps =
       rtp_video_sender_->GetProtectionBitrateBps();
-  DataRate headroom = DataRate::Zero();
-  if (encoder_target_rate_bps_ >
-      encoder_max_bitrate_bps_ + protection_bitrate_bps) {
-    headroom =
-        DataRate::bps(encoder_target_rate_bps_ -
-                      (encoder_max_bitrate_bps_ + protection_bitrate_bps));
+  DataRate link_allocation = DataRate::Zero();
+  if (encoder_target_rate_bps_ > protection_bitrate_bps) {
+    link_allocation =
+        DataRate::bps(encoder_target_rate_bps_ - protection_bitrate_bps);
   }
   encoder_target_rate_bps_ =
       std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
+
+  DataRate encoder_target_rate = DataRate::bps(encoder_target_rate_bps_);
+  link_allocation = std::max(encoder_target_rate, link_allocation);
   video_stream_encoder_->OnBitrateUpdated(
-      DataRate::bps(encoder_target_rate_bps_), headroom,
+      encoder_target_rate, link_allocation,
       rtc::dchecked_cast<uint8_t>(update.packet_loss_ratio * 256),
       update.round_trip_time.ms());
   stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc
index e8eab84..cc45476 100644
--- a/video/video_send_stream_impl_unittest.cc
+++ b/video/video_send_stream_impl_unittest.cc
@@ -656,12 +656,14 @@
                                  update.round_trip_time.ms(), _));
     EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
         .WillOnce(Return(network_constrained_rate.bps()));
-    EXPECT_CALL(
-        video_stream_encoder_,
-        OnBitrateUpdated(network_constrained_rate, DataRate::Zero(), 0, _));
+    EXPECT_CALL(video_stream_encoder_,
+                OnBitrateUpdated(network_constrained_rate,
+                                 network_constrained_rate, 0, _));
     static_cast<BitrateAllocatorObserver*>(vss_impl.get())
         ->OnBitrateUpdated(update);
 
+    // Test allocation where the link allocation is larger than the target,
+    // meaning we have some headroom on the link.
     const DataRate qvga_max_bitrate =
         DataRate::bps(qvga_stream.max_bitrate_bps);
     const DataRate headroom = DataRate::bps(50000);
@@ -672,7 +674,7 @@
     EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
         .WillOnce(Return(rate_with_headroom.bps()));
     EXPECT_CALL(video_stream_encoder_,
-                OnBitrateUpdated(qvga_max_bitrate, headroom, 0, _));
+                OnBitrateUpdated(qvga_max_bitrate, rate_with_headroom, 0, _));
     update.target_bitrate = rate_with_headroom;
     update.link_capacity = rate_with_headroom;
     static_cast<BitrateAllocatorObserver*>(vss_impl.get())
@@ -690,14 +692,15 @@
     EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
         .WillOnce(Return(rate_with_headroom.bps()));
     const DataRate headroom_minus_protection =
-        headroom - DataRate::bps(protection_bitrate_bps);
+        rate_with_headroom - DataRate::bps(protection_bitrate_bps);
     EXPECT_CALL(
         video_stream_encoder_,
         OnBitrateUpdated(qvga_max_bitrate, headroom_minus_protection, 0, _));
     static_cast<BitrateAllocatorObserver*>(vss_impl.get())
         ->OnBitrateUpdated(update);
 
-    // Protection bitrate exceeds headroom, make sure it is capped to 0.
+    // Protection bitrate exceeds head room, link allocation should be capped to
+    // target bitrate.
     EXPECT_CALL(rtp_video_sender_, GetProtectionBitrateBps())
         .WillOnce(Return(headroom.bps() + 1000));
     EXPECT_CALL(rtp_video_sender_,
@@ -706,7 +709,7 @@
     EXPECT_CALL(rtp_video_sender_, GetPayloadBitrateBps())
         .WillOnce(Return(rate_with_headroom.bps()));
     EXPECT_CALL(video_stream_encoder_,
-                OnBitrateUpdated(qvga_max_bitrate, DataRate::Zero(), 0, _));
+                OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate, 0, _));
     static_cast<BitrateAllocatorObserver*>(vss_impl.get())
         ->OnBitrateUpdated(update);
 
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index d9bae1a..badfd81 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -444,6 +444,31 @@
   RTC_DISALLOW_COPY_AND_ASSIGN(VideoSourceProxy);
 };
 
+VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings()
+    : VideoEncoder::RateControlParameters(), encoder_target(DataRate::Zero()) {}
+
+VideoStreamEncoder::EncoderRateSettings::EncoderRateSettings(
+    const VideoBitrateAllocation& bitrate,
+    double framerate_fps,
+    DataRate bandwidth_allocation,
+    DataRate encoder_target)
+    : VideoEncoder::RateControlParameters(bitrate,
+                                          framerate_fps,
+                                          bandwidth_allocation),
+      encoder_target(encoder_target) {}
+
+bool VideoStreamEncoder::EncoderRateSettings::operator==(
+    const EncoderRateSettings& rhs) const {
+  return bitrate == rhs.bitrate && framerate_fps == rhs.framerate_fps &&
+         bandwidth_allocation == rhs.bandwidth_allocation &&
+         encoder_target == rhs.encoder_target;
+}
+
+bool VideoStreamEncoder::EncoderRateSettings::operator!=(
+    const EncoderRateSettings& rhs) const {
+  return !(*this == rhs);
+}
+
 VideoStreamEncoder::VideoStreamEncoder(
     Clock* clock,
     uint32_t number_of_cores,
@@ -471,7 +496,6 @@
       crop_height_(0),
       encoder_start_bitrate_bps_(0),
       max_data_payload_length_(0),
-      last_observed_bitrate_bps_(0),
       encoder_paused_and_dropped_frame_(false),
       clock_(clock),
       degradation_preference_(DegradationPreference::DISABLED),
@@ -485,7 +509,6 @@
       pending_frame_post_time_us_(0),
       accumulated_update_rect_{0, 0, 0, 0},
       bitrate_observer_(nullptr),
-      last_framerate_fps_(0),
       force_disable_frame_dropper_(false),
       input_framerate_(kFrameRateAvergingWindowSizeMs, 1000),
       pending_frame_drops_(0),
@@ -805,13 +828,12 @@
     bitrate_adjuster_->OnEncoderInfo(info);
   }
 
-  if (rate_allocator_ && last_observed_bitrate_bps_ > 0) {
+  if (rate_allocator_ && last_encoder_rate_settings_) {
     // We have a new rate allocator instance and already configured target
-    // bitrate. Update the rate allocation and notify observsers.
-    const uint32_t framerate_fps = GetInputFramerateFps();
-    SetEncoderRates(GetBitrateAllocationAndNotifyObserver(
-                        last_observed_bitrate_bps_, framerate_fps),
-                    framerate_fps);
+    // bitrate. Update the rate allocation and notify observers.
+    last_encoder_rate_settings_->framerate_fps = GetInputFramerateFps();
+    SetEncoderRates(
+        UpdateBitrateAllocationAndNotifyObserver(*last_encoder_rate_settings_));
   }
 
   encoder_stats_observer_->OnEncoderReconfigured(encoder_config_, streams);
@@ -968,8 +990,9 @@
   // Pause video if paused by caller or as long as the network is down or the
   // pacer queue has grown too large in buffered mode.
   // If the pacer queue has grown too large or the network is down,
-  // last_observed_bitrate_bps_ will be 0.
-  return last_observed_bitrate_bps_ == 0;
+  // |last_encoder_rate_settings_->encoder_target| will be 0.
+  return !last_encoder_rate_settings_ ||
+         last_encoder_rate_settings_->encoder_target == DataRate::Zero();
 }
 
 void VideoStreamEncoder::TraceFrameDropStart() {
@@ -990,19 +1013,19 @@
   encoder_paused_and_dropped_frame_ = false;
 }
 
-VideoBitrateAllocation
-VideoStreamEncoder::GetBitrateAllocationAndNotifyObserver(
-    const uint32_t target_bitrate_bps,
-    uint32_t framerate_fps) {
+VideoStreamEncoder::EncoderRateSettings
+VideoStreamEncoder::UpdateBitrateAllocationAndNotifyObserver(
+    const EncoderRateSettings& rate_settings) {
+  VideoBitrateAllocation new_allocation;
   // Only call allocators if bitrate > 0 (ie, not suspended), otherwise they
   // might cap the bitrate to the min bitrate configured.
-  VideoBitrateAllocation bitrate_allocation;
-  if (rate_allocator_ && target_bitrate_bps > 0) {
-    bitrate_allocation =
-        rate_allocator_->GetAllocation(target_bitrate_bps, framerate_fps);
+  if (rate_allocator_ && rate_settings.encoder_target > DataRate::Zero()) {
+    new_allocation = rate_allocator_->GetAllocation(
+        rate_settings.encoder_target.bps(),
+        static_cast<uint32_t>(rate_settings.framerate_fps + 0.5));
   }
 
-  if (bitrate_observer_ && bitrate_allocation.get_sum_bps() > 0) {
+  if (bitrate_observer_ && new_allocation.get_sum_bps() > 0) {
     if (encoder_ && encoder_initialized_) {
       // Avoid too old encoder_info_.
       const int64_t kMaxDiffMs = 100;
@@ -1012,23 +1035,28 @@
       // Update allocation according to info from encoder.
       bitrate_observer_->OnBitrateAllocationUpdated(
           UpdateAllocationFromEncoderInfo(
-              bitrate_allocation,
+              new_allocation,
               updated_recently ? encoder_info_ : encoder_->GetEncoderInfo()));
     } else {
-      bitrate_observer_->OnBitrateAllocationUpdated(bitrate_allocation);
+      bitrate_observer_->OnBitrateAllocationUpdated(new_allocation);
     }
   }
 
   if (bitrate_adjuster_) {
     VideoBitrateAllocation adjusted_allocation =
-        bitrate_adjuster_->AdjustRateAllocation(bitrate_allocation,
-                                                framerate_fps);
-    RTC_LOG(LS_VERBOSE) << "Adjusting allocation, fps = " << framerate_fps
-                        << ", from " << bitrate_allocation.ToString() << ", to "
+        bitrate_adjuster_->AdjustRateAllocation(
+            new_allocation,
+            static_cast<int>(rate_settings.framerate_fps + 0.5));
+    RTC_LOG(LS_VERBOSE) << "Adjusting allocation, fps = "
+                        << rate_settings.framerate_fps << ", from "
+                        << new_allocation.ToString() << ", to "
                         << adjusted_allocation.ToString();
-    return adjusted_allocation;
+    new_allocation = adjusted_allocation;
   }
-  return bitrate_allocation;
+
+  return EncoderRateSettings(new_allocation, rate_settings.framerate_fps,
+                             rate_settings.bandwidth_allocation,
+                             rate_settings.encoder_target);
 }
 
 uint32_t VideoStreamEncoder::GetInputFramerateFps() {
@@ -1042,8 +1070,14 @@
 }
 
 void VideoStreamEncoder::SetEncoderRates(
-    const VideoBitrateAllocation& bitrate_allocation,
-    uint32_t framerate_fps) {
+    const EncoderRateSettings& rate_settings) {
+  RTC_DCHECK_GT(rate_settings.framerate_fps, 0.0);
+  const bool settings_changes = !last_encoder_rate_settings_ ||
+                                rate_settings != *last_encoder_rate_settings_;
+  if (settings_changes) {
+    last_encoder_rate_settings_ = rate_settings;
+  }
+
   if (!encoder_) {
     return;
   }
@@ -1056,25 +1090,16 @@
   // bitrate.
   // TODO(perkj): Make sure all known encoder implementations handle zero
   // target bitrate and remove this check.
-  if (!HasInternalSource() && bitrate_allocation.get_sum_bps() == 0) {
+  if (!HasInternalSource() && rate_settings.bitrate.get_sum_bps() == 0) {
     return;
   }
 
-  RTC_DCHECK_GT(framerate_fps, 0);
-  if (bitrate_allocation != last_bitrate_allocation_ ||
-      framerate_fps != last_framerate_fps_) {
-    int res = encoder_->SetRateAllocation(bitrate_allocation, framerate_fps);
-    if (res != 0) {
-      RTC_LOG(LS_WARNING) << "Error set encoder rate (total bitrate bps = "
-                          << bitrate_allocation.get_sum_bps()
-                          << ", framerate = " << framerate_fps << "): " << res;
-    }
-
-    frame_encoder_timer_.OnSetRates(bitrate_allocation, framerate_fps);
+  if (settings_changes) {
+    encoder_->SetRates(rate_settings);
+    frame_encoder_timer_.OnSetRates(
+        rate_settings.bitrate,
+        static_cast<uint32_t>(rate_settings.framerate_fps + 0.5));
   }
-
-  last_bitrate_allocation_ = bitrate_allocation;
-  last_framerate_fps_ = framerate_fps;
 }
 
 void VideoStreamEncoder::MaybeEncodeVideoFrame(const VideoFrame& video_frame,
@@ -1116,9 +1141,16 @@
   } else if (!last_parameters_update_ms_ ||
              now_ms - *last_parameters_update_ms_ >=
                  vcm::VCMProcessTimer::kDefaultProcessIntervalMs) {
-    SetEncoderRates(GetBitrateAllocationAndNotifyObserver(
-                        last_observed_bitrate_bps_, framerate_fps),
-                    framerate_fps);
+    if (last_encoder_rate_settings_) {
+      // Clone rate settings before update, so that SetEncoderRates() will
+      // actually detect the change between the input and
+      // |last_encoder_rate_setings_|, triggering the call to SetRate() on the
+      // encoder.
+      EncoderRateSettings new_rate_settings = *last_encoder_rate_settings_;
+      new_rate_settings.framerate_fps = static_cast<double>(framerate_fps);
+      SetEncoderRates(
+          UpdateBitrateAllocationAndNotifyObserver(new_rate_settings));
+    }
     last_parameters_update_ms_.emplace(now_ms);
   }
 
@@ -1179,9 +1211,13 @@
       !encoder_info_.has_trusted_rate_controller;
   frame_dropper_.Enable(frame_dropping_enabled);
   if (frame_dropping_enabled && frame_dropper_.DropFrame()) {
-    RTC_LOG(LS_VERBOSE) << "Drop Frame: "
-                        << "target bitrate " << last_observed_bitrate_bps_
-                        << ", input frame rate " << framerate_fps;
+    RTC_LOG(LS_VERBOSE)
+        << "Drop Frame: "
+        << "target bitrate "
+        << (last_encoder_rate_settings_
+                ? last_encoder_rate_settings_->encoder_target.bps()
+                : 0)
+        << ", input frame rate " << framerate_fps;
     OnDroppedFrame(
         EncodedImageCallback::DropReason::kDroppedByMediaOptimizations);
     accumulated_update_rect_.Union(video_frame.update_rect());
@@ -1463,13 +1499,14 @@
 }
 
 void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,
-                                          DataRate target_headroom,
+                                          DataRate link_allocation,
                                           uint8_t fraction_lost,
                                           int64_t round_trip_time_ms) {
+  RTC_DCHECK(link_allocation >= target_bitrate);
   if (!encoder_queue_.IsCurrent()) {
-    encoder_queue_.PostTask([this, target_bitrate, target_headroom,
+    encoder_queue_.PostTask([this, target_bitrate, link_allocation,
                              fraction_lost, round_trip_time_ms] {
-      OnBitrateUpdated(target_bitrate, target_headroom, fraction_lost,
+      OnBitrateUpdated(target_bitrate, link_allocation, fraction_lost,
                        round_trip_time_ms);
     });
     return;
@@ -1478,7 +1515,7 @@
   RTC_DCHECK(sink_) << "sink_ must be set before the encoder is active.";
 
   RTC_LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate " << target_bitrate.bps()
-                      << " headroom = " << target_headroom.bps()
+                      << " link allocation bitrate = " << link_allocation.bps()
                       << " packet loss " << static_cast<int>(fraction_lost)
                       << " rtt " << round_trip_time_ms;
   // On significant changes to BWE at the start of the call,
@@ -1502,16 +1539,17 @@
 
   uint32_t framerate_fps = GetInputFramerateFps();
   frame_dropper_.SetRates((target_bitrate.bps() + 500) / 1000, framerate_fps);
-  SetEncoderRates(GetBitrateAllocationAndNotifyObserver(target_bitrate.bps(),
-                                                        framerate_fps),
-                  framerate_fps);
+  const bool video_is_suspended = target_bitrate == DataRate::Zero();
+  const bool video_suspension_changed = video_is_suspended != EncoderPaused();
+
+  EncoderRateSettings new_rate_settings{VideoBitrateAllocation(),
+                                        static_cast<double>(framerate_fps),
+                                        link_allocation, target_bitrate};
+  SetEncoderRates(UpdateBitrateAllocationAndNotifyObserver(new_rate_settings));
 
   encoder_start_bitrate_bps_ = target_bitrate.bps() != 0
                                    ? target_bitrate.bps()
                                    : encoder_start_bitrate_bps_;
-  bool video_is_suspended = target_bitrate == DataRate::Zero();
-  bool video_suspension_changed = video_is_suspended != EncoderPaused();
-  last_observed_bitrate_bps_ = target_bitrate.bps();
 
   if (video_suspension_changed) {
     RTC_LOG(LS_INFO) << "Video suspend state changed to: "
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index 41e865c..094cbcc 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -109,6 +109,24 @@
     int pixel_count() const { return width * height; }
   };
 
+  struct EncoderRateSettings : public VideoEncoder::RateControlParameters {
+    EncoderRateSettings();
+    EncoderRateSettings(const VideoBitrateAllocation& bitrate,
+                        double framerate_fps,
+                        DataRate bandwidth_allocation,
+                        DataRate encoder_target);
+    bool operator==(const EncoderRateSettings& rhs) const;
+    bool operator!=(const EncoderRateSettings& rhs) const;
+
+    // This is the scalar target bitrate before the VideoBitrateAllocator, i.e.
+    // the |target_bitrate| argument of the OnBitrateUpdated() method. This is
+    // needed because the bitrate allocator may truncate the total bitrate and a
+    // later call to the same allocator instance, e.g.
+    // |using last_encoder_rate_setings_->bitrate.get_sum_bps()|, may trick it
+    // into thinking the available bitrate has decreased since the last call.
+    DataRate encoder_target;
+  };
+
   void ConfigureEncoderOnTaskQueue(VideoEncoderConfig config,
                                    size_t max_data_payload_length);
   void ReconfigureEncoder() RTC_RUN_ON(&encoder_queue_);
@@ -140,12 +158,15 @@
   void TraceFrameDropStart();
   void TraceFrameDropEnd();
 
-  VideoBitrateAllocation GetBitrateAllocationAndNotifyObserver(
-      const uint32_t target_bitrate_bps,
-      uint32_t framerate_fps) RTC_RUN_ON(&encoder_queue_);
+  // Returns a copy of |rate_settings| with the |bitrate| field updated using
+  // the current VideoBitrateAllocator, and notifies any listeners of the new
+  // allocation.
+  EncoderRateSettings UpdateBitrateAllocationAndNotifyObserver(
+      const EncoderRateSettings& rate_settings) RTC_RUN_ON(&encoder_queue_);
+
   uint32_t GetInputFramerateFps() RTC_RUN_ON(&encoder_queue_);
-  void SetEncoderRates(const VideoBitrateAllocation& bitrate_allocation,
-                       uint32_t framerate_fps) RTC_RUN_ON(&encoder_queue_);
+  void SetEncoderRates(const EncoderRateSettings& rate_settings)
+      RTC_RUN_ON(&encoder_queue_);
 
   // Class holding adaptation information.
   class AdaptCounter final {
@@ -242,7 +263,8 @@
   int crop_height_ RTC_GUARDED_BY(&encoder_queue_);
   uint32_t encoder_start_bitrate_bps_ RTC_GUARDED_BY(&encoder_queue_);
   size_t max_data_payload_length_ RTC_GUARDED_BY(&encoder_queue_);
-  uint32_t last_observed_bitrate_bps_ RTC_GUARDED_BY(&encoder_queue_);
+  absl::optional<EncoderRateSettings> last_encoder_rate_settings_
+      RTC_GUARDED_BY(&encoder_queue_);
   bool encoder_paused_and_dropped_frame_ RTC_GUARDED_BY(&encoder_queue_);
   Clock* const clock_;
   // Counters used for deciding if the video resolution or framerate is
@@ -294,9 +316,6 @@
 
   VideoEncoder::EncoderInfo encoder_info_ RTC_GUARDED_BY(&encoder_queue_);
   VideoEncoderFactory::CodecInfo codec_info_ RTC_GUARDED_BY(&encoder_queue_);
-  VideoBitrateAllocation last_bitrate_allocation_
-      RTC_GUARDED_BY(&encoder_queue_);
-  uint32_t last_framerate_fps_ RTC_GUARDED_BY(&encoder_queue_);
   VideoCodec send_codec_ RTC_GUARDED_BY(&encoder_queue_);
 
   FrameDropper frame_dropper_ RTC_GUARDED_BY(&encoder_queue_);
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 278e566..71e8063 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -415,7 +415,8 @@
     EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
         .Times(1);
     video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                            DataRate::Zero(), 0, 0);
+                                            DataRate::bps(kTargetBitrateBps), 0,
+                                            0);
 
     video_source_.IncomingCapturedFrame(
         CreateFrame(1, codec_width_, codec_height_));
@@ -912,8 +913,8 @@
 };
 
 TEST_F(VideoStreamEncoderTest, EncodeOneFrame) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   rtc::Event frame_destroyed_event;
   video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
   WaitForEncodedFrame(1);
@@ -931,8 +932,8 @@
   video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
   EXPECT_TRUE(frame_destroyed_event.Wait(kDefaultTimeoutMs));
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // The pending frame should be received.
   WaitForEncodedFrame(2);
@@ -943,12 +944,12 @@
 }
 
 TEST_F(VideoStreamEncoderTest, DropsFramesWhenRateSetToZero) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(0), DataRate::Zero(), 0,
+  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(0), DataRate::bps(0), 0,
                                           0);
   // The encoder will cache up to one frame for a short duration. Adding two
   // frames means that the first frame will be dropped and the second frame will
@@ -956,8 +957,8 @@
   video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
   video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   WaitForEncodedFrame(3);
   video_source_.IncomingCapturedFrame(CreateFrame(4, nullptr));
   WaitForEncodedFrame(4);
@@ -965,8 +966,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
 
@@ -979,8 +980,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, DropsFrameAfterStop) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
@@ -993,8 +994,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, DropsPendingFramesOnSlowEncode) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   fake_encoder_.BlockNextEncode();
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -1011,8 +1012,8 @@
 
 TEST_F(VideoStreamEncoderTest,
        ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   EXPECT_EQ(0, sink_.number_of_reconfigurations());
 
   // Capture a frame and wait for it to synchronize with the encoder thread.
@@ -1038,8 +1039,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, FrameResolutionChangeReconfigureEncoder) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Capture a frame and wait for it to synchronize with the encoder thread.
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -1090,8 +1091,8 @@
   video_source_.set_adaptation_enabled(true);
 
   // Enable BALANCED preference, no initial limitation.
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_stream_encoder_->SetSource(&video_source_,
                                    webrtc::DegradationPreference::BALANCED);
   VerifyNoLimitation(video_source_.sink_wants());
@@ -1173,8 +1174,8 @@
   video_stream_encoder_->Stop();
 }
 TEST_F(VideoStreamEncoderTest, SinkWantsStoredByDegradationPreference) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   VerifyNoLimitation(video_source_.sink_wants());
 
   const int kFrameWidth = 1280;
@@ -1262,8 +1263,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, StatsTracksQualityAdaptationStats) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1296,8 +1297,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, StatsTracksCpuAdaptationStats) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1330,8 +1331,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1399,8 +1400,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1460,8 +1461,8 @@
 
 TEST_F(VideoStreamEncoderTest,
        QualityAdaptationStatsAreResetWhenScalerIsDisabled) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1516,8 +1517,8 @@
 
 TEST_F(VideoStreamEncoderTest,
        StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1653,8 +1654,8 @@
        ScalingUpAndDownDoesNothingWithMaintainResolution) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Expect no scaling to begin with.
   VerifyNoLimitation(video_source_.sink_wants());
@@ -1702,8 +1703,8 @@
        SkipsSameAdaptDownRequest_MaintainFramerateMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   test::FrameForwarder source;
@@ -1735,8 +1736,8 @@
 TEST_F(VideoStreamEncoderTest, SkipsSameOrLargerAdaptDownRequest_BalancedMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   test::FrameForwarder source;
@@ -1776,8 +1777,8 @@
        NoChangeForInitialNormalUsage_MaintainFramerateMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   test::FrameForwarder source;
@@ -1803,8 +1804,8 @@
        NoChangeForInitialNormalUsage_MaintainResolutionMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_RESOLUTION preference, no initial limitation.
   test::FrameForwarder source;
@@ -1829,8 +1830,8 @@
 TEST_F(VideoStreamEncoderTest, NoChangeForInitialNormalUsage_BalancedMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   test::FrameForwarder source;
@@ -1857,8 +1858,8 @@
 TEST_F(VideoStreamEncoderTest, NoChangeForInitialNormalUsage_DisabledMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable DISABLED preference, no initial limitation.
   test::FrameForwarder source;
@@ -1886,8 +1887,8 @@
        AdaptsResolutionForLowQuality_MaintainFramerateMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -1924,8 +1925,8 @@
   const int kWidth = 1280;
   const int kHeight = 720;
   const int kInputFps = 30;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   VideoSendStream::Stats stats = stats_proxy_->GetStats();
   stats.input_frame_rate = kInputFps;
@@ -1966,8 +1967,8 @@
   const int kHeight = 720;
   const size_t kNumFrames = 10;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable adapter, expected input resolutions when downscaling:
   // 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (kMinPixelsPerFrame)
@@ -2002,8 +2003,8 @@
        AdaptsResolutionUpAndDownTwiceOnOveruse_MaintainFramerateMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2061,8 +2062,8 @@
        AdaptsResolutionUpAndDownTwiceForLowQuality_BalancedMode_NoFpsLimit) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2120,8 +2121,8 @@
        AdaptsResolutionOnOveruseAndLowQuality_MaintainFramerateMode) {
   const int kWidth = 1280;
   const int kHeight = 720;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2258,8 +2259,8 @@
   const int kWidth = 640;
   const int kHeight = 360;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
     video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
@@ -2285,8 +2286,8 @@
 
 TEST_F(VideoStreamEncoderTest,
        CpuLimitedHistogramIsNotReportedForDisabledDegradation) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   const int kWidth = 640;
   const int kHeight = 360;
 
@@ -2318,7 +2319,8 @@
   EXPECT_CALL(bitrate_observer, OnBitrateAllocationUpdated(expected_bitrate))
       .Times(1);
   video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kLowTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+                                          DataRate::bps(kLowTargetBitrateBps),
+                                          0, 0);
 
   video_source_.IncomingCapturedFrame(
       CreateFrame(rtc::TimeMillis(), codec_width_, codec_height_));
@@ -2420,8 +2422,8 @@
   const int kFrameHeight = 720;
   const int kFramerate = 24;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   test::FrameForwarder source;
   video_stream_encoder_->SetSource(
       &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
@@ -2481,8 +2483,8 @@
   const int kLowFramerate = 15;
   const int kHighFramerate = 25;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   test::FrameForwarder source;
   video_stream_encoder_->SetSource(
       &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
@@ -2545,8 +2547,8 @@
   const int kFrameHeight = 720;
   const int kFramerate = 24;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   test::FrameForwarder source;
   video_stream_encoder_->SetSource(
       &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
@@ -2592,7 +2594,8 @@
 TEST_F(VideoStreamEncoderTest, DropsFramesAndScalesWhenBitrateIsTooLow) {
   const int kTooLowBitrateForFrameSizeBps = 10000;
   video_stream_encoder_->OnBitrateUpdated(
-      DataRate::bps(kTooLowBitrateForFrameSizeBps), DataRate::Zero(), 0, 0);
+      DataRate::bps(kTooLowBitrateForFrameSizeBps),
+      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0);
   const int kWidth = 640;
   const int kHeight = 360;
 
@@ -2622,7 +2625,8 @@
        NumberOfDroppedFramesLimitedWhenBitrateIsTooLow) {
   const int kTooLowBitrateForFrameSizeBps = 10000;
   video_stream_encoder_->OnBitrateUpdated(
-      DataRate::bps(kTooLowBitrateForFrameSizeBps), DataRate::Zero(), 0, 0);
+      DataRate::bps(kTooLowBitrateForFrameSizeBps),
+      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0);
   const int kWidth = 640;
   const int kHeight = 360;
 
@@ -2647,7 +2651,8 @@
   const int kWidth = 640;
   const int kHeight = 360;
   video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kLowTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+                                          DataRate::bps(kLowTargetBitrateBps),
+                                          0, 0);
 
   // Set degradation preference.
   video_stream_encoder_->SetSource(
@@ -2672,7 +2677,8 @@
   video_stream_encoder_->ConfigureEncoder(std::move(video_encoder_config),
                                           kMaxPayloadLength);
   video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kLowTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+                                          DataRate::bps(kLowTargetBitrateBps),
+                                          0, 0);
 
   // Force quality scaler reconfiguration by resetting the source.
   video_stream_encoder_->SetSource(&video_source_,
@@ -2695,14 +2701,15 @@
   const int kWidth = 640;
   const int kHeight = 360;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
   // Frame should not be dropped.
   WaitForEncodedFrame(1);
 
   video_stream_encoder_->OnBitrateUpdated(
-      DataRate::bps(kTooLowBitrateForFrameSizeBps), DataRate::Zero(), 0, 0);
+      DataRate::bps(kTooLowBitrateForFrameSizeBps),
+      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
   // Expect to drop this frame, the wait should time out.
   ExpectDroppedFrame();
@@ -2716,8 +2723,8 @@
        ResolutionNotAdaptedForTooSmallFrame_MaintainFramerateMode) {
   const int kTooSmallWidth = 10;
   const int kTooSmallHeight = 10;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   test::FrameForwarder source;
@@ -2742,8 +2749,8 @@
   const int kTooSmallWidth = 10;
   const int kTooSmallHeight = 10;
   const int kFpsLimit = 7;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   test::FrameForwarder source;
@@ -2776,8 +2783,8 @@
 
 TEST_F(VideoStreamEncoderTest, FailingInitEncodeDoesntCauseCrash) {
   fake_encoder_.ForceInitEncodeFailure(true);
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   ResetEncoder("VP8", 2, 1, 1, false);
   const int kFrameWidth = 1280;
   const int kFrameHeight = 720;
@@ -2790,8 +2797,8 @@
 // TODO(sprang): Extend this with fps throttling and any "balanced" extensions.
 TEST_F(VideoStreamEncoderTest,
        AdaptsResolutionOnOveruse_MaintainFramerateMode) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   const int kFrameWidth = 1280;
   const int kFrameHeight = 720;
@@ -2824,8 +2831,8 @@
   const int kFrameWidth = 1280;
   const int kFrameHeight = 720;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_stream_encoder_->SetSource(
       &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
   video_source_.set_adaptation_enabled(true);
@@ -2926,8 +2933,8 @@
   // disable frame dropping and make testing easier.
   ResetEncoder("VP8", 1, 2, 1, true);
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_stream_encoder_->SetSource(
       &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
   video_source_.set_adaptation_enabled(true);
@@ -2966,8 +2973,8 @@
   const int kHeight = 720;
   const int64_t kFrameIntervalMs = 150;
   int64_t timestamp_ms = kFrameIntervalMs;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -3147,8 +3154,8 @@
   const int kHeight = 720;
   const int64_t kFrameIntervalMs = 150;
   int64_t timestamp_ms = kFrameIntervalMs;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -3261,8 +3268,8 @@
   const int kFpsLimit = 15;
   const int64_t kFrameIntervalMs = 150;
   int64_t timestamp_ms = kFrameIntervalMs;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -3380,8 +3387,8 @@
   const int kAdaptedFrameHeight = 808;
   const int kFramerate = 24;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   // Trigger reconfigure encoder (without resetting the entire instance).
   VideoEncoderConfig video_encoder_config;
   video_encoder_config.codec_type = kVideoCodecVP8;
@@ -3414,8 +3421,8 @@
   const int kLowFps = 2;
   const int kHighFps = 30;
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
   max_framerate_ = kLowFps;
@@ -3429,8 +3436,8 @@
   }
 
   // Make sure encoder is updated with new target.
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_source_.IncomingCapturedFrame(
       CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
   WaitForEncodedFrame(timestamp_ms);
@@ -3468,8 +3475,8 @@
 
   MockBitrateObserver bitrate_observer;
   video_stream_encoder_->SetBitrateAllocationObserver(&bitrate_observer);
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_stream_encoder_->WaitUntilTaskQueueIsIdle();
 
   // Insert a first video frame, causes another bitrate update.
@@ -3480,7 +3487,7 @@
   WaitForEncodedFrame(timestamp_ms);
 
   // Next, simulate video suspension due to pacer queue overrun.
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(0), DataRate::Zero(), 0,
+  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(0), DataRate::bps(0), 0,
                                           1);
 
   // Skip ahead until a new periodic parameter update should have occured.
@@ -3503,8 +3510,8 @@
   const int kFrameWidth = 1280;
   const int kFrameHeight = 720;
   const CpuOveruseOptions default_options;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_source_.IncomingCapturedFrame(
       CreateFrame(1, kFrameWidth, kFrameHeight));
   WaitForEncodedFrame(1);
@@ -3526,8 +3533,8 @@
   hardware_options.high_encode_usage_threshold_percent = 200;
   fake_encoder_.SetIsHardwareAccelerated(true);
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
   video_source_.IncomingCapturedFrame(
       CreateFrame(1, kFrameWidth, kFrameHeight));
   WaitForEncodedFrame(1);
@@ -3547,8 +3554,8 @@
   const int kTargetBitrateBps = 120000;
   const int kNumFramesInRun = kFps * 5;  // Runs of five seconds.
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
   max_framerate_ = kFps;
@@ -3583,7 +3590,8 @@
   }
   fake_encoder_.SimulateOvershoot(overshoot_factor);
   video_stream_encoder_->OnBitrateUpdated(
-      DataRate::bps(kTargetBitrateBps + 1000), DataRate::Zero(), 0, 0);
+      DataRate::bps(kTargetBitrateBps + 1000),
+      DataRate::bps(kTargetBitrateBps + 1000), 0, 0);
   num_dropped = 0;
   for (int i = 0; i < kNumFramesInRun; ++i) {
     video_source_.IncomingCapturedFrame(
@@ -3595,8 +3603,8 @@
     timestamp_ms += 1000 / kFps;
   }
 
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Target framerate should be still be near the expected target, despite
   // the frame drops.
@@ -3618,8 +3626,8 @@
 
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
   max_framerate_ = kActualInputFps;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Insert 3 seconds of video, with an input fps lower than configured max.
   for (int i = 0; i < kActualInputFps * 3; ++i) {
@@ -3637,8 +3645,8 @@
 
 TEST_F(VideoStreamEncoderTest, AccumulatesUpdateRectOnDroppedFrames) {
   VideoFrame::UpdateRect rect;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   fake_encoder_.BlockNextEncode();
   video_source_.IncomingCapturedFrame(
@@ -3681,8 +3689,8 @@
 }
 
 TEST_F(VideoStreamEncoderTest, SetsFrameTypes) {
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // First frame is always keyframe.
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -3713,7 +3721,8 @@
   // Setup simulcast with three streams.
   ResetEncoder("VP8", 3, 1, 1, false);
   video_stream_encoder_->OnBitrateUpdated(
-      DataRate::bps(kSimulcastTargetBitrateBps), DataRate::Zero(), 0, 0);
+      DataRate::bps(kSimulcastTargetBitrateBps),
+      DataRate::bps(kSimulcastTargetBitrateBps), 0, 0);
   // Wait for all three layers before triggering event.
   sink_.SetNumExpectedLayers(3);
 
@@ -3750,8 +3759,8 @@
   // Configure internal source factory and setup test again.
   encoder_factory_.SetHasInternalSource(true);
   ResetEncoder("VP8", 1, 1, 1, false);
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   // Call encoder directly, simulating internal source where encoded frame
   // callback in VideoStreamEncoder is called despite no OnFrame().
@@ -3787,8 +3796,8 @@
   // Configure internal source factory and setup test again.
   encoder_factory_.SetHasInternalSource(true);
   ResetEncoder("VP8", 1, 1, 1, false);
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kTargetBitrateBps),
-                                          DataRate::Zero(), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps), 0, 0);
 
   int64_t timestamp = 1;
   EncodedImage image;