Enable congestion window pushback to reduce bitrate by only drop video frames.

With current congestion window pushback, when congestion window is filling up, it will reduce bitrate directly and encoder may reduce encode quality, resolution, or framerate to adapt to the allocated bitrate, the behavior is depending on the degradation preference.
This change enable congestion window to only drop frames to reduce bitrate (when needed) instead of reduce general bitrate allocation.

Bug: webrtc:11334
Change-Id: I9cf5c20a0858c4d07d006942abe72aa5e1f7cb38
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168059
Commit-Queue: Ying Wang <yinwa@webrtc.org>
Reviewed-by: Karl Wiberg <kwiberg@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30483}
diff --git a/api/call/bitrate_allocation.h b/api/call/bitrate_allocation.h
index 24530c9..13c7f74 100644
--- a/api/call/bitrate_allocation.h
+++ b/api/call/bitrate_allocation.h
@@ -34,6 +34,10 @@
   TimeDelta round_trip_time = TimeDelta::PlusInfinity();
   // |bwe_period| is deprecated, use |stable_target_bitrate| allocation instead.
   TimeDelta bwe_period = TimeDelta::PlusInfinity();
+  // Congestion window pushback bitrate reduction fraction. Used in
+  // VideoStreamEncoder to reduce the bitrate by the given fraction
+  // by dropping frames.
+  double cwnd_reduce_ratio = 0;
 };
 
 }  // namespace webrtc
diff --git a/api/transport/network_types.h b/api/transport/network_types.h
index f658b34..ec37a22 100644
--- a/api/transport/network_types.h
+++ b/api/transport/network_types.h
@@ -218,6 +218,7 @@
   NetworkEstimate network_estimate;
   DataRate target_rate = DataRate::Zero();
   DataRate stable_target_rate = DataRate::Zero();
+  double cwnd_reduce_ratio = 0;
 };
 
 // Contains updates of network controller comand state. Using optionals to
diff --git a/api/video/video_stream_encoder_interface.h b/api/video/video_stream_encoder_interface.h
index d2a90bb..253fb04 100644
--- a/api/video/video_stream_encoder_interface.h
+++ b/api/video/video_stream_encoder_interface.h
@@ -95,7 +95,8 @@
                                 DataRate stable_target_bitrate,
                                 DataRate link_allocation,
                                 uint8_t fraction_lost,
-                                int64_t round_trip_time_ms) = 0;
+                                int64_t round_trip_time_ms,
+                                double cwnd_reduce_ratio) = 0;
 
   // Register observer for the bitrate allocation between the temporal
   // and spatial layers.
diff --git a/api/video/video_stream_encoder_observer.h b/api/video/video_stream_encoder_observer.h
index 49531ae..0d639f3 100644
--- a/api/video/video_stream_encoder_observer.h
+++ b/api/video/video_stream_encoder_observer.h
@@ -59,7 +59,8 @@
     kSource,
     kEncoderQueue,
     kEncoder,
-    kMediaOptimization
+    kMediaOptimization,
+    kCongestionWindow
   };
 
   ~VideoStreamEncoderObserver() override = default;
diff --git a/call/bitrate_allocator.cc b/call/bitrate_allocator.cc
index 7d9e5cb..6880422 100644
--- a/call/bitrate_allocator.cc
+++ b/call/bitrate_allocator.cc
@@ -409,6 +409,7 @@
     update.packet_loss_ratio = last_fraction_loss_ / 256.0;
     update.round_trip_time = TimeDelta::ms(last_rtt_);
     update.bwe_period = TimeDelta::ms(last_bwe_period_ms_);
+    update.cwnd_reduce_ratio = msg.cwnd_reduce_ratio;
     uint32_t protection_bitrate = config.observer->OnBitrateUpdated(update);
 
     if (allocated_bitrate == 0 && config.allocated_bitrate_bps > 0) {
diff --git a/call/video_send_stream.h b/call/video_send_stream.h
index 39abdfc..85d8019 100644
--- a/call/video_send_stream.h
+++ b/call/video_send_stream.h
@@ -81,6 +81,7 @@
     uint32_t frames_dropped_by_capturer = 0;
     uint32_t frames_dropped_by_encoder_queue = 0;
     uint32_t frames_dropped_by_rate_limiter = 0;
+    uint32_t frames_dropped_by_congestion_window = 0;
     uint32_t frames_dropped_by_encoder = 0;
     absl::optional<uint64_t> qp_sum;
     // Bitrate the encoder is currently configured to use due to bandwidth
diff --git a/modules/congestion_controller/goog_cc/congestion_window_pushback_controller_unittest.cc b/modules/congestion_controller/goog_cc/congestion_window_pushback_controller_unittest.cc
index 426d9e1..37b7233 100644
--- a/modules/congestion_controller/goog_cc/congestion_window_pushback_controller_unittest.cc
+++ b/modules/congestion_controller/goog_cc/congestion_window_pushback_controller_unittest.cc
@@ -89,5 +89,17 @@
   EXPECT_GT(80000u, bitrate_bps);
 }
 
+TEST_F(CongestionWindowPushbackControllerTest, PushbackDropFrame) {
+  test::ScopedFieldTrials trials("WebRTC-CongestionWindow/DropFrame:true/");
+  cwnd_controller_.reset(
+      new CongestionWindowPushbackController(&field_trial_config_));
+  cwnd_controller_->UpdateOutstandingData(1e8);  // Large number
+  cwnd_controller_->SetDataWindow(DataSize::bytes(50000));
+
+  uint32_t bitrate_bps = 80000;
+  bitrate_bps = cwnd_controller_->UpdateTargetBitrate(bitrate_bps);
+  EXPECT_GT(80000u, bitrate_bps);
+}
+
 }  // namespace test
 }  // namespace webrtc
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
index 852c957..fb3305e 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc
@@ -600,6 +600,7 @@
   BWE_TEST_LOGGING_PLOT(1, "Target_bitrate_kbps", at_time.ms(),
                         loss_based_target_rate.kbps());
 
+  double cwnd_reduce_ratio = 0.0;
   if (congestion_window_pushback_controller_) {
     int64_t pushback_rate =
         congestion_window_pushback_controller_->UpdateTargetBitrate(
@@ -607,6 +608,11 @@
     pushback_rate = std::max<int64_t>(bandwidth_estimation_->GetMinBitrate(),
                                       pushback_rate);
     pushback_target_rate = DataRate::bps(pushback_rate);
+    if (rate_control_settings_.UseCongestionWindowDropFrameOnly()) {
+      cwnd_reduce_ratio = static_cast<double>(loss_based_target_rate.bps() -
+                                              pushback_target_rate.bps()) /
+                          loss_based_target_rate.bps();
+    }
   }
 
   if ((loss_based_target_rate != last_loss_based_target_rate_) ||
@@ -624,7 +630,12 @@
 
     TargetTransferRate target_rate_msg;
     target_rate_msg.at_time = at_time;
-    target_rate_msg.target_rate = pushback_target_rate;
+    if (rate_control_settings_.UseCongestionWindowDropFrameOnly()) {
+      target_rate_msg.target_rate = loss_based_target_rate;
+      target_rate_msg.cwnd_reduce_ratio = cwnd_reduce_ratio;
+    } else {
+      target_rate_msg.target_rate = pushback_target_rate;
+    }
     if (loss_based_stable_rate_) {
       target_rate_msg.stable_target_rate =
           std::min(bandwidth_estimation_->GetEstimatedLinkCapacity(),
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index 09aec43..3ce9a77 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -289,6 +289,40 @@
   EXPECT_LT(client->target_rate().kbps(), 40);
 }
 
+// Test congestion window pushback on network delay happens.
+TEST_F(GoogCcNetworkControllerTest,
+       CongestionWindowPushbackDropFrameOnNetworkDelay) {
+  auto factory = CreateFeedbackOnlyFactory();
+  ScopedFieldTrials trial(
+      "WebRTC-CongestionWindow/QueueSize:800,MinBitrate:30000,DropFrame:true/");
+  Scenario s("googcc_unit/cwnd_on_delay", false);
+  auto send_net =
+      s.CreateMutableSimulationNode([=](NetworkSimulationConfig* c) {
+        c->bandwidth = DataRate::kbps(1000);
+        c->delay = TimeDelta::ms(100);
+      });
+  auto ret_net = s.CreateSimulationNode(
+      [](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); });
+  CallClientConfig config;
+  config.transport.cc_factory = &factory;
+  // Start high so bandwidth drop has max effect.
+  config.transport.rates.start_rate = DataRate::kbps(300);
+  config.transport.rates.max_rate = DataRate::kbps(2000);
+  config.transport.rates.min_rate = DataRate::kbps(10);
+
+  auto* client = CreateVideoSendingClient(&s, std::move(config),
+                                          {send_net->node()}, {ret_net});
+
+  s.RunFor(TimeDelta::seconds(10));
+  send_net->PauseTransmissionUntil(s.Now() + TimeDelta::seconds(10));
+  s.RunFor(TimeDelta::seconds(3));
+
+  // As the dropframe is set, after 3 seconds without feedback from any sent
+  // packets, we expect that the target rate is not reduced by congestion
+  // window.
+  EXPECT_GT(client->target_rate().kbps(), 300);
+}
+
 TEST_F(GoogCcNetworkControllerTest, OnNetworkRouteChanged) {
   NetworkControlUpdate update;
   DataRate new_bitrate = DataRate::bps(200000);
diff --git a/rtc_base/experiments/rate_control_settings.cc b/rtc_base/experiments/rate_control_settings.cc
index bf623bd..ce77c9e 100644
--- a/rtc_base/experiments/rate_control_settings.cc
+++ b/rtc_base/experiments/rate_control_settings.cc
@@ -63,7 +63,8 @@
 std::unique_ptr<StructParametersParser> CongestionWindowConfig::Parser() {
   return StructParametersParser::Create("QueueSize", &queue_size_ms,  //
                                         "MinBitrate", &min_bitrate_bps,
-                                        "InitWin", &initial_data_window);
+                                        "InitWin", &initial_data_window,
+                                        "DropFrame", &drop_frame_only);
 }
 
 // static
@@ -142,6 +143,10 @@
          congestion_window_config_.min_bitrate_bps;
 }
 
+bool RateControlSettings::UseCongestionWindowDropFrameOnly() const {
+  return congestion_window_config_.drop_frame_only;
+}
+
 uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps()
     const {
   return congestion_window_config_.min_bitrate_bps.value_or(
diff --git a/rtc_base/experiments/rate_control_settings.h b/rtc_base/experiments/rate_control_settings.h
index 3f1d8de..6898bf6 100644
--- a/rtc_base/experiments/rate_control_settings.h
+++ b/rtc_base/experiments/rate_control_settings.h
@@ -25,6 +25,7 @@
   absl::optional<int> queue_size_ms;
   absl::optional<int> min_bitrate_bps;
   absl::optional<DataSize> initial_data_window;
+  bool drop_frame_only = false;
   std::unique_ptr<StructParametersParser> Parser();
   static CongestionWindowConfig Parse(absl::string_view config);
 };
@@ -66,6 +67,7 @@
   bool UseCongestionWindow() const;
   int64_t GetCongestionWindowAdditionalTimeMs() const;
   bool UseCongestionWindowPushback() const;
+  bool UseCongestionWindowDropFrameOnly() const;
   uint32_t CongestionWindowMinPushbackTargetBitrateBps() const;
   absl::optional<DataSize> CongestionWindowInitialDataWindow() const;
 
diff --git a/video/send_statistics_proxy.cc b/video/send_statistics_proxy.cc
index a4f1754..094baa3 100644
--- a/video/send_statistics_proxy.cc
+++ b/video/send_statistics_proxy.cc
@@ -652,9 +652,11 @@
   RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "DroppedFrames.Encoder",
                              current_stats.frames_dropped_by_encoder);
   log_stream << uma_prefix_ << "DroppedFrames.Ratelimiter "
-             << current_stats.frames_dropped_by_rate_limiter;
+             << current_stats.frames_dropped_by_rate_limiter << "\n";
   RTC_HISTOGRAMS_COUNTS_1000(kIndex, uma_prefix_ + "DroppedFrames.Ratelimiter",
                              current_stats.frames_dropped_by_rate_limiter);
+  log_stream << uma_prefix_ << "DroppedFrames.CongestionWindow "
+             << current_stats.frames_dropped_by_congestion_window;
 
   RTC_LOG(LS_INFO) << log_stream.str();
 }
@@ -1042,6 +1044,9 @@
     case DropReason::kMediaOptimization:
       ++stats_.frames_dropped_by_rate_limiter;
       break;
+    case DropReason::kCongestionWindow:
+      ++stats_.frames_dropped_by_congestion_window;
+      break;
   }
 }
 
diff --git a/video/test/mock_video_stream_encoder.h b/video/test/mock_video_stream_encoder.h
index 494419d..8e42968 100644
--- a/video/test/mock_video_stream_encoder.h
+++ b/video/test/mock_video_stream_encoder.h
@@ -24,8 +24,8 @@
   MOCK_METHOD1(SetStartBitrate, void(int));
   MOCK_METHOD0(SendKeyFrame, void());
   MOCK_METHOD1(OnLossNotification, void(const VideoEncoder::LossNotification&));
-  MOCK_METHOD5(OnBitrateUpdated,
-               void(DataRate, DataRate, DataRate, uint8_t, int64_t));
+  MOCK_METHOD6(OnBitrateUpdated,
+               void(DataRate, DataRate, DataRate, uint8_t, int64_t, double));
   MOCK_METHOD1(OnFrame, void(const VideoFrame&));
   MOCK_METHOD1(SetBitrateAllocationObserver,
                void(VideoBitrateAllocationObserver*));
diff --git a/video/video_send_stream_impl.cc b/video/video_send_stream_impl.cc
index 97f3bb7..9ecb36a 100644
--- a/video/video_send_stream_impl.cc
+++ b/video/video_send_stream_impl.cc
@@ -387,7 +387,7 @@
   bitrate_allocator_->RemoveObserver(this);
   check_encoder_activity_task_.Stop();
   video_stream_encoder_->OnBitrateUpdated(DataRate::Zero(), DataRate::Zero(),
-                                          DataRate::Zero(), 0, 0);
+                                          DataRate::Zero(), 0, 0, 0);
   stats_proxy_->OnSetEncoderTargetRate(0);
 }
 
@@ -646,7 +646,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       encoder_target_rate, encoder_stable_target_rate, link_allocation,
       rtc::dchecked_cast<uint8_t>(update.packet_loss_ratio * 256),
-      update.round_trip_time.ms());
+      update.round_trip_time.ms(), update.cwnd_reduce_ratio);
   stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
   return protection_bitrate_bps;
 }
diff --git a/video/video_send_stream_impl_unittest.cc b/video/video_send_stream_impl_unittest.cc
index 1c44cc8..06cad22 100644
--- a/video/video_send_stream_impl_unittest.cc
+++ b/video/video_send_stream_impl_unittest.cc
@@ -706,7 +706,7 @@
         EXPECT_CALL(
             video_stream_encoder_,
             OnBitrateUpdated(network_constrained_rate, network_constrained_rate,
-                             network_constrained_rate, 0, _));
+                             network_constrained_rate, 0, _, 0));
         static_cast<BitrateAllocatorObserver*>(vss_impl.get())
             ->OnBitrateUpdated(update);
 
@@ -723,7 +723,7 @@
             .WillOnce(Return(rate_with_headroom.bps()));
         EXPECT_CALL(video_stream_encoder_,
                     OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
-                                     rate_with_headroom, 0, _));
+                                     rate_with_headroom, 0, _, 0));
         static_cast<BitrateAllocatorObserver*>(vss_impl.get())
             ->OnBitrateUpdated(update);
 
@@ -740,7 +740,7 @@
             rate_with_headroom - DataRate::bps(protection_bitrate_bps);
         EXPECT_CALL(video_stream_encoder_,
                     OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
-                                     headroom_minus_protection, 0, _));
+                                     headroom_minus_protection, 0, _, 0));
         static_cast<BitrateAllocatorObserver*>(vss_impl.get())
             ->OnBitrateUpdated(update);
 
@@ -753,14 +753,14 @@
             .WillOnce(Return(rate_with_headroom.bps()));
         EXPECT_CALL(video_stream_encoder_,
                     OnBitrateUpdated(qvga_max_bitrate, qvga_max_bitrate,
-                                     qvga_max_bitrate, 0, _));
+                                     qvga_max_bitrate, 0, _, 0));
         static_cast<BitrateAllocatorObserver*>(vss_impl.get())
             ->OnBitrateUpdated(update);
 
         // Set rates to zero on stop.
         EXPECT_CALL(video_stream_encoder_,
                     OnBitrateUpdated(DataRate::Zero(), DataRate::Zero(),
-                                     DataRate::Zero(), 0, 0));
+                                     DataRate::Zero(), 0, 0, 0));
         vss_impl->Stop();
       },
       RTC_FROM_HERE);
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index 1ae4856..4079ab5 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -273,7 +273,8 @@
                              clock_->TimeInMilliseconds()),
       last_frame_log_ms_(clock_->TimeInMilliseconds()),
       captured_frame_count_(0),
-      dropped_frame_count_(0),
+      dropped_frame_cwnd_pushback_count_(0),
+      dropped_frame_encoder_block_count_(0),
       pending_frame_post_time_us_(0),
       accumulated_update_rect_{0, 0, 0, 0},
       accumulated_update_rect_is_valid_(true),
@@ -285,6 +286,7 @@
       force_disable_frame_dropper_(false),
       input_framerate_(kFrameRateAvergingWindowSizeMs, 1000),
       pending_frame_drops_(0),
+      cwnd_frame_counter_(0),
       next_frame_types_(1, VideoFrameType::kVideoFrameDelta),
       frame_encode_metadata_writer_(this),
       experiment_groups_(GetExperimentGroups()),
@@ -823,26 +825,40 @@
             posted_frames_waiting_for_encode_.fetch_sub(1);
         RTC_DCHECK_GT(posted_frames_waiting_for_encode, 0);
         CheckForAnimatedContent(incoming_frame, post_time_us);
-        if (posted_frames_waiting_for_encode == 1) {
+        bool cwnd_frame_drop =
+            cwnd_frame_drop_interval_ &&
+            (cwnd_frame_counter_++ % cwnd_frame_drop_interval_.value() == 0);
+        if (posted_frames_waiting_for_encode == 1 && !cwnd_frame_drop) {
           MaybeEncodeVideoFrame(incoming_frame, post_time_us);
         } else {
-          // There is a newer frame in flight. Do not encode this frame.
-          RTC_LOG(LS_VERBOSE)
-              << "Incoming frame dropped due to that the encoder is blocked.";
-          ++dropped_frame_count_;
-          encoder_stats_observer_->OnFrameDropped(
-              VideoStreamEncoderObserver::DropReason::kEncoderQueue);
+          if (cwnd_frame_drop) {
+            // Frame drop by congestion window pusback. Do not encode this
+            // frame.
+            ++dropped_frame_cwnd_pushback_count_;
+            encoder_stats_observer_->OnFrameDropped(
+                VideoStreamEncoderObserver::DropReason::kCongestionWindow);
+          } else {
+            // There is a newer frame in flight. Do not encode this frame.
+            RTC_LOG(LS_VERBOSE)
+                << "Incoming frame dropped due to that the encoder is blocked.";
+            ++dropped_frame_encoder_block_count_;
+            encoder_stats_observer_->OnFrameDropped(
+                VideoStreamEncoderObserver::DropReason::kEncoderQueue);
+          }
           accumulated_update_rect_.Union(incoming_frame.update_rect());
           accumulated_update_rect_is_valid_ &= incoming_frame.has_update_rect();
         }
         if (log_stats) {
           RTC_LOG(LS_INFO) << "Number of frames: captured "
                            << captured_frame_count_
+                           << ", dropped (due to congestion window pushback) "
+                           << dropped_frame_cwnd_pushback_count_
                            << ", dropped (due to encoder blocked) "
-                           << dropped_frame_count_ << ", interval_ms "
-                           << kFrameLogIntervalMs;
+                           << dropped_frame_encoder_block_count_
+                           << ", interval_ms " << kFrameLogIntervalMs;
           captured_frame_count_ = 0;
-          dropped_frame_count_ = 0;
+          dropped_frame_cwnd_pushback_count_ = 0;
+          dropped_frame_encoder_block_count_ = 0;
         }
       });
 }
@@ -1484,18 +1500,49 @@
   });
 }
 
+DataRate VideoStreamEncoder::UpdateTargetBitrate(DataRate target_bitrate,
+                                                 double cwnd_reduce_ratio) {
+  RTC_DCHECK_RUN_ON(&encoder_queue_);
+  DataRate updated_target_bitrate = target_bitrate;
+
+  // Drop frames when congestion window pushback ratio is larger than 1
+  // percent and target bitrate is larger than codec min bitrate.
+  // When target_bitrate is 0 means codec is paused, skip frame dropping.
+  if (cwnd_reduce_ratio > 0.01 && target_bitrate.bps() > 0 &&
+      target_bitrate.bps() > send_codec_.minBitrate * 1000) {
+    int reduce_bitrate_bps = std::min(
+        static_cast<int>(target_bitrate.bps() * cwnd_reduce_ratio),
+        static_cast<int>(target_bitrate.bps() - send_codec_.minBitrate * 1000));
+    if (reduce_bitrate_bps > 0) {
+      // At maximum the congestion window can drop 1/2 frames.
+      cwnd_frame_drop_interval_ = std::max(
+          2, static_cast<int>(target_bitrate.bps() / reduce_bitrate_bps));
+      // Reduce target bitrate accordingly.
+      updated_target_bitrate =
+          target_bitrate - (target_bitrate / cwnd_frame_drop_interval_.value());
+      return updated_target_bitrate;
+    }
+  }
+  cwnd_frame_drop_interval_.reset();
+  return updated_target_bitrate;
+}
+
 void VideoStreamEncoder::OnBitrateUpdated(DataRate target_bitrate,
                                           DataRate stable_target_bitrate,
                                           DataRate link_allocation,
                                           uint8_t fraction_lost,
-                                          int64_t round_trip_time_ms) {
+                                          int64_t round_trip_time_ms,
+                                          double cwnd_reduce_ratio) {
   RTC_DCHECK_GE(link_allocation, target_bitrate);
   if (!encoder_queue_.IsCurrent()) {
     encoder_queue_.PostTask([this, target_bitrate, stable_target_bitrate,
-                             link_allocation, fraction_lost,
-                             round_trip_time_ms] {
-      OnBitrateUpdated(target_bitrate, stable_target_bitrate, link_allocation,
-                       fraction_lost, round_trip_time_ms);
+                             link_allocation, fraction_lost, round_trip_time_ms,
+                             cwnd_reduce_ratio] {
+      DataRate updated_target_bitrate =
+          UpdateTargetBitrate(target_bitrate, cwnd_reduce_ratio);
+      OnBitrateUpdated(updated_target_bitrate, stable_target_bitrate,
+                       link_allocation, fraction_lost, round_trip_time_ms,
+                       cwnd_reduce_ratio);
     });
     return;
   }
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index fee1067..0390d7f 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -110,7 +110,11 @@
                         DataRate stable_target_bitrate,
                         DataRate target_headroom,
                         uint8_t fraction_lost,
-                        int64_t round_trip_time_ms) override;
+                        int64_t round_trip_time_ms,
+                        double cwnd_reduce_ratio) override;
+
+  DataRate UpdateTargetBitrate(DataRate target_bitrate,
+                               double cwnd_reduce_ratio);
 
  protected:
   // Used for testing. For example the |ScalingObserverInterface| methods must
@@ -269,7 +273,8 @@
 
   int64_t last_frame_log_ms_ RTC_GUARDED_BY(incoming_frame_race_checker_);
   int captured_frame_count_ RTC_GUARDED_BY(&encoder_queue_);
-  int dropped_frame_count_ RTC_GUARDED_BY(&encoder_queue_);
+  int dropped_frame_cwnd_pushback_count_ RTC_GUARDED_BY(&encoder_queue_);
+  int dropped_frame_encoder_block_count_ RTC_GUARDED_BY(&encoder_queue_);
   absl::optional<VideoFrame> pending_frame_ RTC_GUARDED_BY(&encoder_queue_);
   int64_t pending_frame_post_time_us_ RTC_GUARDED_BY(&encoder_queue_);
 
@@ -317,6 +322,12 @@
   // the worker thread.
   std::atomic<int> pending_frame_drops_;
 
+  // Congestion window frame drop ratio (drop 1 in every
+  // cwnd_frame_drop_interval_ frames).
+  absl::optional<int> cwnd_frame_drop_interval_ RTC_GUARDED_BY(&encoder_queue_);
+  // Frame counter for congestion window frame drop.
+  int cwnd_frame_counter_ RTC_GUARDED_BY(&encoder_queue_);
+
   std::unique_ptr<EncoderBitrateAdjuster> bitrate_adjuster_
       RTC_GUARDED_BY(&encoder_queue_);
 
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index 472027b..d7cf579 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -547,7 +547,7 @@
         .Times(1);
     video_stream_encoder_->OnBitrateUpdated(
         DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-        DataRate::bps(kTargetBitrateBps), 0, 0);
+        DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
     video_source_.IncomingCapturedFrame(
         CreateFrame(1, codec_width_, codec_height_));
@@ -1157,7 +1157,7 @@
 TEST_F(VideoStreamEncoderTest, EncodeOneFrame) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   rtc::Event frame_destroyed_event;
   video_source_.IncomingCapturedFrame(CreateFrame(1, &frame_destroyed_event));
   WaitForEncodedFrame(1);
@@ -1177,7 +1177,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // The pending frame should be received.
   WaitForEncodedFrame(2);
@@ -1190,12 +1190,12 @@
 TEST_F(VideoStreamEncoderTest, DropsFramesWhenRateSetToZero) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
 
   video_stream_encoder_->OnBitrateUpdated(DataRate::bps(0), DataRate::bps(0),
-                                          DataRate::bps(0), 0, 0);
+                                          DataRate::bps(0), 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
   // be sent when the encoder is resumed.
@@ -1204,7 +1204,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   WaitForEncodedFrame(3);
   video_source_.IncomingCapturedFrame(CreateFrame(4, nullptr));
   WaitForEncodedFrame(4);
@@ -1214,7 +1214,7 @@
 TEST_F(VideoStreamEncoderTest, DropsFramesWithSameOrOldNtpTimestamp) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
 
@@ -1229,7 +1229,7 @@
 TEST_F(VideoStreamEncoderTest, DropsFrameAfterStop) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
@@ -1244,7 +1244,7 @@
 TEST_F(VideoStreamEncoderTest, DropsPendingFramesOnSlowEncode) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   fake_encoder_.BlockNextEncode();
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -1262,7 +1262,7 @@
 TEST_F(VideoStreamEncoderTest, DropFrameWithFailedI420Conversion) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   rtc::Event frame_destroyed_event;
   video_source_.IncomingCapturedFrame(
@@ -1283,7 +1283,7 @@
   // Capture a frame at codec_width_/codec_height_.
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
   WaitForEncodedFrame(1);
   // The encoder will have been configured once.
@@ -1301,11 +1301,34 @@
   video_stream_encoder_->Stop();
 }
 
+TEST_F(VideoStreamEncoderTest, DropsFramesWhenCongestionWindowPushbackSet) {
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
+  video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
+  WaitForEncodedFrame(1);
+
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0.5);
+  // The congestion window pushback is set to 0.5, which will drop 1/2 of
+  // frames. Adding two frames means that the first frame will be dropped and
+  // the second frame will be sent to the encoder.
+  video_source_.IncomingCapturedFrame(CreateFrame(2, nullptr));
+  video_source_.IncomingCapturedFrame(CreateFrame(3, nullptr));
+  WaitForEncodedFrame(3);
+  video_source_.IncomingCapturedFrame(CreateFrame(4, nullptr));
+  video_source_.IncomingCapturedFrame(CreateFrame(5, nullptr));
+  WaitForEncodedFrame(5);
+  EXPECT_EQ(2u, stats_proxy_->GetStats().frames_dropped_by_congestion_window);
+  video_stream_encoder_->Stop();
+}
+
 TEST_F(VideoStreamEncoderTest,
        ConfigureEncoderTriggersOnEncoderConfigurationChanged) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   EXPECT_EQ(0, sink_.number_of_reconfigurations());
 
   // Capture a frame and wait for it to synchronize with the encoder thread.
@@ -1333,7 +1356,7 @@
 TEST_F(VideoStreamEncoderTest, FrameResolutionChangeReconfigureEncoder) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Capture a frame and wait for it to synchronize with the encoder thread.
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -1360,7 +1383,7 @@
        EncoderInstanceDestroyedBeforeAnotherInstanceCreated) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Capture a frame and wait for it to synchronize with the encoder thread.
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -1383,7 +1406,7 @@
 TEST_F(VideoStreamEncoderTest, BitrateLimitsChangeReconfigureRateAllocator) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   VideoEncoderConfig video_encoder_config;
   test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
@@ -1429,7 +1452,7 @@
        IntersectionOfEncoderAndAppBitrateLimitsUsedWhenBothProvided) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const uint32_t kMinEncBitrateKbps = 100;
   const uint32_t kMaxEncBitrateKbps = 1000;
@@ -1476,7 +1499,7 @@
        EncoderAndAppLimitsDontIntersectEncoderLimitsIgnored) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const uint32_t kMinAppBitrateKbps = 100;
   const uint32_t kMaxAppBitrateKbps = 200;
@@ -1511,7 +1534,7 @@
        EncoderRecommendedMaxAndMinBitratesUsedForGivenResolution) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const VideoEncoder::ResolutionBitrateLimits encoder_bitrate_limits_270p(
       480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
@@ -1580,7 +1603,7 @@
 TEST_F(VideoStreamEncoderTest, EncoderRecommendedMaxBitrateCapsTargetBitrate) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   VideoEncoderConfig video_encoder_config;
   test::FillEncoderConfiguration(kVideoCodecVP8, 1, &video_encoder_config);
@@ -1645,7 +1668,7 @@
   fake_encoder_.SetRequestedResolutionAlignment(kRequestedResolutionAlignment);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // On the 1st frame, we should have initialized the encoder and
   // asked for its resolution requirements.
@@ -1678,7 +1701,7 @@
   // Enable BALANCED preference, no initial limitation.
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_stream_encoder_->SetSource(&video_source_,
                                    webrtc::DegradationPreference::BALANCED);
   VerifyNoLimitation(video_source_.sink_wants());
@@ -1763,7 +1786,7 @@
 TEST_F(VideoStreamEncoderTest, SinkWantsStoredByDegradationPreference) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   VerifyNoLimitation(video_source_.sink_wants());
 
   const int kFrameWidth = 1280;
@@ -1876,7 +1899,7 @@
 TEST_F(VideoStreamEncoderTest, StatsTracksQualityAdaptationStats) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1911,7 +1934,7 @@
 TEST_F(VideoStreamEncoderTest, StatsTracksCpuAdaptationStats) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -1946,7 +1969,7 @@
 TEST_F(VideoStreamEncoderTest, SwitchingSourceKeepsCpuAdaptation) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -2016,7 +2039,7 @@
 TEST_F(VideoStreamEncoderTest, SwitchingSourceKeepsQualityAdaptation) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -2078,7 +2101,7 @@
        QualityAdaptationStatsAreResetWhenScalerIsDisabled) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -2135,7 +2158,7 @@
        StatsTracksCpuAdaptationStatsWhenSwitchingSource) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kWidth = 1280;
   const int kHeight = 720;
@@ -2273,7 +2296,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Expect no scaling to begin with.
   VerifyNoLimitation(video_source_.sink_wants());
@@ -2323,7 +2346,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   test::FrameForwarder source;
@@ -2357,7 +2380,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   test::FrameForwarder source;
@@ -2399,7 +2422,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   test::FrameForwarder source;
@@ -2427,7 +2450,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_RESOLUTION preference, no initial limitation.
   test::FrameForwarder source;
@@ -2454,7 +2477,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   test::FrameForwarder source;
@@ -2483,7 +2506,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable DISABLED preference, no initial limitation.
   test::FrameForwarder source;
@@ -2513,7 +2536,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2552,7 +2575,7 @@
   const int kInputFps = 30;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   VideoSendStream::Stats stats = stats_proxy_->GetStats();
   stats.input_frame_rate = kInputFps;
@@ -2599,7 +2622,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable adapter, expected input resolutions when downscaling:
   // 1280x720 -> 960x540 -> 640x360 -> 480x270 -> 320x180 (kMinPixelsPerFrame)
@@ -2636,7 +2659,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2696,7 +2719,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2757,7 +2780,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps),
       DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps),
-      DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps), 0, 0);
+      DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2774,7 +2797,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps),
       DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps),
-      DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps), 0, 0);
+      DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps), 0, 0, 0);
   video_stream_encoder_->TriggerQualityLow();
 
   // Insert 720p frame. It should be downscaled and encoded.
@@ -2791,7 +2814,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps),
       DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps),
-      DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps), 0, 0);
+      DataRate::bps(kEncoderBitrateLimits720p.min_start_bitrate_bps), 0, 0, 0);
 
   // Trigger adapt up. Higher resolution should be requested.
   video_stream_encoder_->TriggerQualityHigh();
@@ -2808,7 +2831,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps),
       DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps),
-      DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps), 0, 0);
+      DataRate::bps(kEncoderBitrateLimits540p.min_start_bitrate_bps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -2844,9 +2867,9 @@
   }
 
   void OnBitrateUpdated(int bitrate_bps) {
-    video_stream_encoder_->OnBitrateUpdated(DataRate::bps(bitrate_bps),
-                                            DataRate::bps(bitrate_bps),
-                                            DataRate::bps(bitrate_bps), 0, 0);
+    video_stream_encoder_->OnBitrateUpdated(
+        DataRate::bps(bitrate_bps), DataRate::bps(bitrate_bps),
+        DataRate::bps(bitrate_bps), 0, 0, 0);
   }
 
   void InsertFrame() {
@@ -3132,7 +3155,7 @@
   const int kHeight = 720;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -3271,7 +3294,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   for (int i = 1; i <= SendStatisticsProxy::kMinRequiredMetricsSamples; ++i) {
     video_source_.IncomingCapturedFrame(CreateFrame(i, kWidth, kHeight));
@@ -3299,7 +3322,7 @@
        CpuLimitedHistogramIsNotReportedForDisabledDegradation) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   const int kWidth = 640;
   const int kHeight = 360;
 
@@ -3333,7 +3356,7 @@
       .Times(1);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kLowTargetBitrateBps), DataRate::bps(kLowTargetBitrateBps),
-      DataRate::bps(kLowTargetBitrateBps), 0, 0);
+      DataRate::bps(kLowTargetBitrateBps), 0, 0, 0);
 
   video_source_.IncomingCapturedFrame(
       CreateFrame(rtc::TimeMillis(), codec_width_, codec_height_));
@@ -3441,7 +3464,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   test::FrameForwarder source;
   video_stream_encoder_->SetSource(
       &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
@@ -3503,7 +3526,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   test::FrameForwarder source;
   video_stream_encoder_->SetSource(
       &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
@@ -3568,7 +3591,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   test::FrameForwarder source;
   video_stream_encoder_->SetSource(
       &source, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
@@ -3616,7 +3639,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTooLowBitrateForFrameSizeBps),
       DataRate::bps(kTooLowBitrateForFrameSizeBps),
-      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0);
+      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
   const int kWidth = 640;
   const int kHeight = 360;
 
@@ -3648,7 +3671,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTooLowBitrateForFrameSizeBps),
       DataRate::bps(kTooLowBitrateForFrameSizeBps),
-      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0);
+      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
   const int kWidth = 640;
   const int kHeight = 360;
 
@@ -3674,7 +3697,7 @@
   const int kHeight = 360;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kLowTargetBitrateBps), DataRate::bps(kLowTargetBitrateBps),
-      DataRate::bps(kLowTargetBitrateBps), 0, 0);
+      DataRate::bps(kLowTargetBitrateBps), 0, 0, 0);
 
   // Set degradation preference.
   video_stream_encoder_->SetSource(
@@ -3700,7 +3723,7 @@
                                           kMaxPayloadLength);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kLowTargetBitrateBps), DataRate::bps(kLowTargetBitrateBps),
-      DataRate::bps(kLowTargetBitrateBps), 0, 0);
+      DataRate::bps(kLowTargetBitrateBps), 0, 0, 0);
 
   // Force quality scaler reconfiguration by resetting the source.
   video_stream_encoder_->SetSource(&video_source_,
@@ -3727,7 +3750,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(1, kWidth, kHeight));
   // Frame should not be dropped.
   WaitForEncodedFrame(1);
@@ -3735,7 +3758,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kNotTooLowBitrateForFrameSizeBps),
       DataRate::bps(kNotTooLowBitrateForFrameSizeBps),
-      DataRate::bps(kNotTooLowBitrateForFrameSizeBps), 0, 0);
+      DataRate::bps(kNotTooLowBitrateForFrameSizeBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(2, kWidth, kHeight));
   // Frame should not be dropped.
   WaitForEncodedFrame(2);
@@ -3743,7 +3766,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTooLowBitrateForFrameSizeBps),
       DataRate::bps(kTooLowBitrateForFrameSizeBps),
-      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0);
+      DataRate::bps(kTooLowBitrateForFrameSizeBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(CreateFrame(3, kWidth, kHeight));
   // Expect to drop this frame, the wait should time out.
   ExpectDroppedFrame();
@@ -3771,9 +3794,9 @@
 
   // Start at low bitrate.
   const int kLowBitrateBps = 200000;
-  video_stream_encoder_->OnBitrateUpdated(DataRate::bps(kLowBitrateBps),
-                                          DataRate::bps(kLowBitrateBps),
-                                          DataRate::bps(kLowBitrateBps), 0, 0);
+  video_stream_encoder_->OnBitrateUpdated(
+      DataRate::bps(kLowBitrateBps), DataRate::bps(kLowBitrateBps),
+      DataRate::bps(kLowBitrateBps), 0, 0, 0);
 
   // Expect first frame to be dropped and resolution to be limited.
   const int kWidth = 1280;
@@ -3788,7 +3811,7 @@
   video_stream_encoder_->OnBitrateUpdated(DataRate::bps(config.max_bitrate_bps),
                                           DataRate::bps(config.max_bitrate_bps),
                                           DataRate::bps(config.max_bitrate_bps),
-                                          0, 0);
+                                          0, 0, 0);
 
   // Insert frames and advance |min_duration_ms|.
   for (size_t i = 1; i <= 10; i++) {
@@ -3822,7 +3845,7 @@
   const int kTooSmallHeight = 10;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable MAINTAIN_FRAMERATE preference, no initial limitation.
   test::FrameForwarder source;
@@ -3849,7 +3872,7 @@
   const int kFpsLimit = 7;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   test::FrameForwarder source;
@@ -3884,7 +3907,7 @@
   fake_encoder_.ForceInitEncodeFailure(true);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   ResetEncoder("VP8", 2, 1, 1, false);
   const int kFrameWidth = 1280;
   const int kFrameHeight = 720;
@@ -3899,7 +3922,7 @@
        AdaptsResolutionOnOveruse_MaintainFramerateMode) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   const int kFrameWidth = 1280;
   const int kFrameHeight = 720;
@@ -3934,7 +3957,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_stream_encoder_->SetSource(
       &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
   video_source_.set_adaptation_enabled(true);
@@ -4037,7 +4060,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_stream_encoder_->SetSource(
       &video_source_, webrtc::DegradationPreference::MAINTAIN_RESOLUTION);
   video_source_.set_adaptation_enabled(true);
@@ -4077,7 +4100,7 @@
   int64_t timestamp_ms = kFrameIntervalMs;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -4259,7 +4282,7 @@
   int64_t timestamp_ms = kFrameIntervalMs;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -4374,7 +4397,7 @@
   int64_t timestamp_ms = kFrameIntervalMs;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Enable BALANCED preference, no initial limitation.
   AdaptingFrameForwarder source;
@@ -4464,7 +4487,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   // Trigger reconfigure encoder (without resetting the entire instance).
   VideoEncoderConfig video_encoder_config;
   video_encoder_config.codec_type = kVideoCodecVP8;
@@ -4499,7 +4522,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
   max_framerate_ = kLowFps;
@@ -4515,7 +4538,7 @@
   // Make sure encoder is updated with new target.
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(
       CreateFrame(timestamp_ms, kFrameWidth, kFrameHeight));
   WaitForEncodedFrame(timestamp_ms);
@@ -4554,7 +4577,7 @@
   video_stream_encoder_->SetBitrateAllocationObserver(&bitrate_observer);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_stream_encoder_->WaitUntilTaskQueueIsIdle();
 
   // Insert a first video frame, causes another bitrate update.
@@ -4566,7 +4589,7 @@
 
   // Next, simulate video suspension due to pacer queue overrun.
   video_stream_encoder_->OnBitrateUpdated(DataRate::bps(0), DataRate::bps(0),
-                                          DataRate::bps(0), 0, 1);
+                                          DataRate::bps(0), 0, 1, 0);
 
   // Skip ahead until a new periodic parameter update should have occured.
   timestamp_ms += kProcessIntervalMs;
@@ -4588,7 +4611,7 @@
   const CpuOveruseOptions default_options;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(
       CreateFrame(1, kFrameWidth, kFrameHeight));
   WaitForEncodedFrame(1);
@@ -4612,7 +4635,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_source_.IncomingCapturedFrame(
       CreateFrame(1, kFrameWidth, kFrameHeight));
   WaitForEncodedFrame(1);
@@ -4634,7 +4657,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
   max_framerate_ = kFps;
@@ -4671,7 +4694,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps + 1000),
       DataRate::bps(kTargetBitrateBps + 1000),
-      DataRate::bps(kTargetBitrateBps + 1000), 0, 0);
+      DataRate::bps(kTargetBitrateBps + 1000), 0, 0, 0);
   num_dropped = 0;
   for (int i = 0; i < kNumFramesInRun; ++i) {
     video_source_.IncomingCapturedFrame(
@@ -4685,7 +4708,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Target framerate should be still be near the expected target, despite
   // the frame drops.
@@ -4709,7 +4732,7 @@
   max_framerate_ = kActualInputFps;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Insert 3 seconds of video, with an input fps lower than configured max.
   for (int i = 0; i < kActualInputFps * 3; ++i) {
@@ -4729,7 +4752,7 @@
   VideoFrame::UpdateRect rect;
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   fake_encoder_.BlockNextEncode();
   video_source_.IncomingCapturedFrame(
@@ -4774,7 +4797,7 @@
 TEST_F(VideoStreamEncoderTest, SetsFrameTypes) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // First frame is always keyframe.
   video_source_.IncomingCapturedFrame(CreateFrame(1, nullptr));
@@ -4807,7 +4830,7 @@
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kSimulcastTargetBitrateBps),
       DataRate::bps(kSimulcastTargetBitrateBps),
-      DataRate::bps(kSimulcastTargetBitrateBps), 0, 0);
+      DataRate::bps(kSimulcastTargetBitrateBps), 0, 0, 0);
   // Wait for all three layers before triggering event.
   sink_.SetNumExpectedLayers(3);
 
@@ -4849,7 +4872,7 @@
   ResetEncoder("VP8", 1, 1, 1, false);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   // Call encoder directly, simulating internal source where encoded frame
   // callback in VideoStreamEncoder is called despite no OnFrame().
@@ -4887,7 +4910,7 @@
   ResetEncoder("VP8", 1, 1, 1, false);
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
 
   int64_t timestamp = 1;
   EncodedImage image;
@@ -4979,7 +5002,7 @@
 
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_stream_encoder_->WaitUntilTaskQueueIsIdle();
 
   // Insert a first video frame. It should be dropped because of downscale in
@@ -5022,7 +5045,8 @@
       /*stable_target_bitrate=*/DataRate::kbps(300),
       /*link_allocation=*/DataRate::kbps(300),
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
 
   // Insert a first video frame so that encoder gets configured.
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
@@ -5040,7 +5064,8 @@
       /*stable_target_bitrate=*/target_rate,
       /*link_allocation=*/target_rate,
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
   video_stream_encoder_->WaitUntilTaskQueueIsIdle();
 
   // Target bitrate and bandwidth allocation should both be capped at min_rate.
@@ -5056,7 +5081,7 @@
 TEST_F(VideoStreamEncoderTest, EncoderRatesPropagatedOnReconfigure) {
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   // Capture a frame and wait for it to synchronize with the encoder thread.
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
   video_source_.IncomingCapturedFrame(CreateFrame(timestamp_ms, nullptr));
@@ -5130,7 +5155,8 @@
       /*stable_target_bitrate=*/DataRate::kbps(kDontCare),
       /*link_allocation=*/DataRate::kbps(kDontCare),
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
 
   video_stream_encoder_->Stop();
 }
@@ -5161,7 +5187,8 @@
       /*stable_target_bitrate=*/DataRate::kbps(kSufficientBitrateToNotDrop),
       /*link_allocation=*/DataRate::kbps(kSufficientBitrateToNotDrop),
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
 
   // Send one frame to trigger ReconfigureEncoder.
   video_source_.IncomingCapturedFrame(CreateFrame(1, kHighRes, kHighRes));
@@ -5191,7 +5218,8 @@
       /*stable_target_bitrate=*/rate,
       /*link_allocation=*/rate,
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
 
   // Insert a first video frame so that encoder gets configured.
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
@@ -5208,7 +5236,8 @@
       /*stable_target_bitrate=*/new_stable_rate,
       /*link_allocation=*/rate,
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
   video_stream_encoder_->WaitUntilTaskQueueIsIdle();
   EXPECT_EQ(2, fake_encoder_.GetNumSetRates());
   video_stream_encoder_->Stop();
@@ -5226,7 +5255,8 @@
       /*stable_target_bitrate=*/rate,
       /*link_allocation=*/rate,
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
 
   // Insert a first video frame so that encoder gets configured.
   int64_t timestamp_ms = fake_clock_.TimeNanos() / rtc::kNumNanosecsPerMillisec;
@@ -5244,7 +5274,8 @@
       /*stable_target_bitrate=*/new_stable_rate,
       /*link_allocation=*/rate,
       /*fraction_lost=*/0,
-      /*rtt_ms=*/0);
+      /*rtt_ms=*/0,
+      /*cwnd_reduce_ratio=*/0);
   video_stream_encoder_->WaitUntilTaskQueueIsIdle();
   EXPECT_EQ(1, fake_encoder_.GetNumSetRates());
   video_stream_encoder_->Stop();
@@ -5267,7 +5298,7 @@
   // BALANCED degradation preference is required for this feature.
   video_stream_encoder_->OnBitrateUpdated(
       DataRate::bps(kTargetBitrateBps), DataRate::bps(kTargetBitrateBps),
-      DataRate::bps(kTargetBitrateBps), 0, 0);
+      DataRate::bps(kTargetBitrateBps), 0, 0, 0);
   video_stream_encoder_->SetSource(&video_source_,
                                    webrtc::DegradationPreference::BALANCED);
   VerifyNoLimitation(video_source_.sink_wants());