[Cast Streaming] improve video bitrate calculation

This patch improves the algorithm for adjusting the video bitrate
in response to frame drops. This is in response to UMA based analysis
indicating that we could do a better job handling the bitrate when
performance is poor.

Googlers may view the analysis document at:
go/openscreen-frame-drops

Bug: 1423486
Change-Id: I45f644ec98f6c319f2b506e7e7c913055ca251f8
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4873873
Commit-Queue: Jordan Bayles <jophba@chromium.org>
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1199850}
diff --git a/components/mirroring/service/openscreen_session_host.cc b/components/mirroring/service/openscreen_session_host.cc
index e5601e3..12c61be5 100644
--- a/components/mirroring/service/openscreen_session_host.cc
+++ b/components/mirroring/service/openscreen_session_host.cc
@@ -991,9 +991,9 @@
 }
 
 void OpenscreenSessionHost::UpdateBandwidthEstimate() {
-  int bandwidth_estimate = forced_bandwidth_estimate_for_testing_ > 0
-                               ? forced_bandwidth_estimate_for_testing_
-                               : session_->GetEstimatedNetworkBandwidth();
+  const int bandwidth_estimate = forced_bandwidth_estimate_for_testing_ > 0
+                                     ? forced_bandwidth_estimate_for_testing_
+                                     : session_->GetEstimatedNetworkBandwidth();
 
   // Nothing to do yet.
   if (bandwidth_estimate <= 0) {
diff --git a/media/cast/sender/video_bitrate_suggester.cc b/media/cast/sender/video_bitrate_suggester.cc
index ad7b4b7..09ba1d3 100644
--- a/media/cast/sender/video_bitrate_suggester.cc
+++ b/media/cast/sender/video_bitrate_suggester.cc
@@ -59,23 +59,22 @@
   }
 
   // We don't want to change the bitrate too frequently in order to give
-  // things time to adjust, so only adjust every 100 frames (about 3 seconds
-  // at 30FPS).
-  constexpr int kWindowSize = 100;
+  // things time to adjust, so only adjust roughly once a second.
+  constexpr int kWindowSize = 30;
   if (number_of_frames_requested_ == kWindowSize) {
-    constexpr int kBitrateSteps = 8;
     DCHECK_GE(max_bitrate_, min_bitrate_);
-    const int adjustment = (max_bitrate_ - min_bitrate_) / kBitrateSteps;
+
+    // We want to be more conservative about increasing the frame rate than
+    // decreasing it.
+    constexpr double kIncrease = 1.1;
+    constexpr double kDecrease = 0.8;
 
     // Generally speaking we shouldn't be dropping any frames, so even one is
     // a bad sign.
-    if (number_of_frames_dropped_ > 0) {
-      suggested_max_bitrate_ =
-          std::max(min_bitrate_, suggested_max_bitrate_ - adjustment);
-    } else {
-      suggested_max_bitrate_ =
-          std::min(max_bitrate_, suggested_max_bitrate_ + adjustment);
-    }
+    suggested_max_bitrate_ =
+        (number_of_frames_dropped_ > 0)
+            ? std::max<int>(min_bitrate_, suggested_max_bitrate_ * kDecrease)
+            : std::min<int>(max_bitrate_, suggested_max_bitrate_ * kIncrease);
 
     // Reset the recorded frame drops to start a new window.
     number_of_frames_requested_ = 0;
diff --git a/media/cast/sender/video_bitrate_suggester_unittest.cc b/media/cast/sender/video_bitrate_suggester_unittest.cc
index 1e37986..ad47306 100644
--- a/media/cast/sender/video_bitrate_suggester_unittest.cc
+++ b/media/cast/sender/video_bitrate_suggester_unittest.cc
@@ -86,19 +86,19 @@
   // After a period with multiple frame drops, this should go down.
   RecordShouldDropNextFrame(true);
   RecordShouldDropNextFrame(true);
-  for (int i = 0; i < 99; ++i) {
+  for (int i = 0; i < 29; ++i) {
     RecordShouldDropNextFrame(false);
   }
 
   // It should now go down.
-  EXPECT_EQ(4412500, video_bitrate_suggester().GetSuggestedBitrate());
+  EXPECT_EQ(4000000, video_bitrate_suggester().GetSuggestedBitrate());
 
   // It should continue to go down to the minimum as long as frames are being
   // dropped.
-  int last_suggestion = 4412500;
-  for (int i = 0; i < 7; ++i) {
+  int last_suggestion = 4685120;
+  for (int i = 0; i < 12; ++i) {
     RecordShouldDropNextFrame(true);
-    for (int j = 0; j < 99; ++j) {
+    for (int j = 0; j < 29; ++j) {
       RecordShouldDropNextFrame(false);
     }
 
@@ -113,8 +113,8 @@
 
   // It should increase once we stop dropping frames.
   last_suggestion = 300000;
-  for (int i = 0; i < 8; ++i) {
-    for (int j = 0; j < 100; ++j) {
+  for (int i = 0; i < 30; ++i) {
+    for (int j = 0; j < 30; ++j) {
       RecordShouldDropNextFrame(false);
     }
     const int suggestion = video_bitrate_suggester().GetSuggestedBitrate();