Override stream settings in a separate function

Bug: webrtc:351644568, b/352504711
Change-Id: I706d5a85b83603613693f63c5d3faa9946e90afc
No-Try: True
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/357440
Commit-Queue: Sergey Silkin <ssilkin@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42655}
diff --git a/video/config/encoder_stream_factory.cc b/video/config/encoder_stream_factory.cc
index 96931e1..d80f0d1 100644
--- a/video/config/encoder_stream_factory.cc
+++ b/video/config/encoder_stream_factory.cc
@@ -127,6 +127,123 @@
   return ((size >> base2_exponent) << base2_exponent);
 }
 
+// Override bitrate limits and other stream settings with values from
+// `encoder_config.simulcast_layers` which come from `RtpEncodingParameters`.
+void OverrideStreamSettings(
+    const webrtc::VideoEncoderConfig& encoder_config,
+    const absl::optional<webrtc::DataRate>& experimental_min_bitrate,
+    std::vector<webrtc::VideoStream>& layers) {
+  RTC_DCHECK_LE(layers.size(), encoder_config.simulcast_layers.size());
+
+  // Allow an experiment to override the minimum bitrate for the lowest
+  // spatial layer. The experiment's configuration has the lowest priority.
+  layers[0].min_bitrate_bps = experimental_min_bitrate
+                                  .value_or(webrtc::DataRate::BitsPerSec(
+                                      webrtc::kDefaultMinVideoBitrateBps))
+                                  .bps<int>();
+
+  const bool temporal_layers_supported =
+      IsTemporalLayersSupported(encoder_config.codec_type);
+
+  for (size_t i = 0; i < layers.size(); ++i) {
+    const webrtc::VideoStream& overrides = encoder_config.simulcast_layers[i];
+    webrtc::VideoStream& layer = layers[i];
+    layer.active = overrides.active;
+    layer.scalability_mode = overrides.scalability_mode;
+    layer.requested_resolution = overrides.requested_resolution;
+    // Update with configured num temporal layers if supported by codec.
+    if (overrides.num_temporal_layers > 0 && temporal_layers_supported) {
+      layer.num_temporal_layers = *overrides.num_temporal_layers;
+    }
+    if (overrides.max_framerate > 0) {
+      layer.max_framerate = overrides.max_framerate;
+    }
+    // Update simulcast bitrates with configured min and max bitrate.
+    if (overrides.min_bitrate_bps > 0) {
+      layer.min_bitrate_bps = overrides.min_bitrate_bps;
+    }
+    if (overrides.max_bitrate_bps > 0) {
+      layer.max_bitrate_bps = overrides.max_bitrate_bps;
+    }
+    if (overrides.target_bitrate_bps > 0) {
+      layer.target_bitrate_bps = overrides.target_bitrate_bps;
+    }
+    if (overrides.min_bitrate_bps > 0 && overrides.max_bitrate_bps > 0) {
+      // Min and max bitrate are configured.
+      // Set target to 3/4 of the max bitrate (or to max if below min).
+      if (overrides.target_bitrate_bps <= 0)
+        layer.target_bitrate_bps = layer.max_bitrate_bps * 3 / 4;
+      if (layer.target_bitrate_bps < layer.min_bitrate_bps)
+        layer.target_bitrate_bps = layer.max_bitrate_bps;
+    } else if (overrides.min_bitrate_bps > 0) {
+      // Only min bitrate is configured, make sure target/max are above min.
+      layer.target_bitrate_bps =
+          std::max(layer.target_bitrate_bps, layer.min_bitrate_bps);
+      layer.max_bitrate_bps =
+          std::max(layer.max_bitrate_bps, layer.min_bitrate_bps);
+    } else if (overrides.max_bitrate_bps > 0) {
+      // Only max bitrate is configured, make sure min/target are below max.
+      // Keep target bitrate if it is set explicitly in encoding config.
+      // Otherwise set target bitrate to 3/4 of the max bitrate
+      // or the one calculated from GetSimulcastConfig() which is larger.
+      layer.min_bitrate_bps =
+          std::min(layer.min_bitrate_bps, layer.max_bitrate_bps);
+      if (overrides.target_bitrate_bps <= 0) {
+        layer.target_bitrate_bps =
+            std::max(layer.target_bitrate_bps, layer.max_bitrate_bps * 3 / 4);
+      }
+      layer.target_bitrate_bps =
+          std::clamp(layer.target_bitrate_bps, layer.min_bitrate_bps,
+                     layer.max_bitrate_bps);
+    }
+
+    if (overrides.max_qp > 0) {
+      layer.max_qp = overrides.max_qp;
+    } else if (encoder_config.max_qp > 0) {
+      layer.max_qp = encoder_config.max_qp;
+    } else {
+      layer.max_qp = GetDefaultMaxQp(encoder_config.codec_type);
+    }
+  }
+
+  bool is_highest_layer_max_bitrate_configured =
+      encoder_config.simulcast_layers[layers.size() - 1].max_bitrate_bps > 0;
+  bool is_screencast = encoder_config.content_type ==
+                       webrtc::VideoEncoderConfig::ContentType::kScreen;
+  if (!is_screencast && !is_highest_layer_max_bitrate_configured &&
+      encoder_config.max_bitrate_bps > 0) {
+    // No application-configured maximum for the largest layer.
+    // If there is bitrate leftover, give it to the largest layer.
+    BoostMaxSimulcastLayer(
+        webrtc::DataRate::BitsPerSec(encoder_config.max_bitrate_bps), &layers);
+  }
+
+  // Sort the layers by max_bitrate_bps, they might not always be from
+  // smallest to biggest
+  std::vector<size_t> index(layers.size());
+  std::iota(index.begin(), index.end(), 0);
+  absl::c_stable_sort(index, [&layers](size_t a, size_t b) {
+    return layers[a].max_bitrate_bps < layers[b].max_bitrate_bps;
+  });
+
+  if (!layers[index[0]].active) {
+    // Adjust min bitrate of the first active layer to allow it to go as low as
+    // the lowest (now inactive) layer could.
+    // Otherwise, if e.g. a single HD stream is active, it would have 600kbps
+    // min bitrate, which would always be allocated to the stream.
+    // This would lead to congested network, dropped frames and overall bad
+    // experience.
+
+    const int min_configured_bitrate = layers[index[0]].min_bitrate_bps;
+    for (size_t i = 0; i < layers.size(); ++i) {
+      if (layers[index[i]].active) {
+        layers[index[i]].min_bitrate_bps = min_configured_bitrate;
+        break;
+      }
+    }
+  }
+}
+
 }  // namespace
 
 EncoderStreamFactory::EncoderStreamFactory(
@@ -334,132 +451,18 @@
     int height,
     const webrtc::VideoEncoderConfig& encoder_config,
     const absl::optional<webrtc::DataRate>& experimental_min_bitrate) const {
-  bool is_screencast = encoder_config.content_type ==
-                       webrtc::VideoEncoderConfig::ContentType::kScreen;
-  const bool is_legacy_screencast =
-      webrtc::SimulcastUtility::IsConferenceModeScreenshare(encoder_config);
-
   std::vector<webrtc::Resolution> resolutions =
       GetStreamResolutions(trials, width, height, encoder_config);
 
-  const bool temporal_layers_supported =
-      IsTemporalLayersSupported(encoder_config.codec_type);
   // Use legacy simulcast screenshare if conference mode is explicitly enabled
   // or use the regular simulcast configuration path which is generic.
   std::vector<webrtc::VideoStream> layers = GetSimulcastConfig(
-      resolutions, is_legacy_screencast, temporal_layers_supported, trials,
+      resolutions,
+      webrtc::SimulcastUtility::IsConferenceModeScreenshare(encoder_config),
+      IsTemporalLayersSupported(encoder_config.codec_type), trials,
       encoder_config.codec_type);
-  // Allow an experiment to override the minimum bitrate for the lowest
-  // spatial layer. The experiment's configuration has the lowest priority.
-  layers[0].min_bitrate_bps = experimental_min_bitrate
-                                  .value_or(webrtc::DataRate::BitsPerSec(
-                                      webrtc::kDefaultMinVideoBitrateBps))
-                                  .bps<int>();
 
-  // Update the active simulcast layers and configured bitrates.
-  for (size_t i = 0; i < layers.size(); ++i) {
-    layers[i].active = encoder_config.simulcast_layers[i].active;
-    layers[i].scalability_mode =
-        encoder_config.simulcast_layers[i].scalability_mode;
-    layers[i].requested_resolution =
-        encoder_config.simulcast_layers[i].requested_resolution;
-    // Update with configured num temporal layers if supported by codec.
-    if (encoder_config.simulcast_layers[i].num_temporal_layers &&
-        temporal_layers_supported) {
-      layers[i].num_temporal_layers =
-          *encoder_config.simulcast_layers[i].num_temporal_layers;
-    }
-    if (encoder_config.simulcast_layers[i].max_framerate > 0) {
-      layers[i].max_framerate =
-          encoder_config.simulcast_layers[i].max_framerate;
-    }
-    // Update simulcast bitrates with configured min and max bitrate.
-    if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
-      layers[i].min_bitrate_bps =
-          encoder_config.simulcast_layers[i].min_bitrate_bps;
-    }
-    if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
-      layers[i].max_bitrate_bps =
-          encoder_config.simulcast_layers[i].max_bitrate_bps;
-    }
-    if (encoder_config.simulcast_layers[i].target_bitrate_bps > 0) {
-      layers[i].target_bitrate_bps =
-          encoder_config.simulcast_layers[i].target_bitrate_bps;
-    }
-    if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0 &&
-        encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
-      // Min and max bitrate are configured.
-      // Set target to 3/4 of the max bitrate (or to max if below min).
-      if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0)
-        layers[i].target_bitrate_bps = layers[i].max_bitrate_bps * 3 / 4;
-      if (layers[i].target_bitrate_bps < layers[i].min_bitrate_bps)
-        layers[i].target_bitrate_bps = layers[i].max_bitrate_bps;
-    } else if (encoder_config.simulcast_layers[i].min_bitrate_bps > 0) {
-      // Only min bitrate is configured, make sure target/max are above min.
-      layers[i].target_bitrate_bps =
-          std::max(layers[i].target_bitrate_bps, layers[i].min_bitrate_bps);
-      layers[i].max_bitrate_bps =
-          std::max(layers[i].max_bitrate_bps, layers[i].min_bitrate_bps);
-    } else if (encoder_config.simulcast_layers[i].max_bitrate_bps > 0) {
-      // Only max bitrate is configured, make sure min/target are below max.
-      // Keep target bitrate if it is set explicitly in encoding config.
-      // Otherwise set target bitrate to 3/4 of the max bitrate
-      // or the one calculated from GetSimulcastConfig() which is larger.
-      layers[i].min_bitrate_bps =
-          std::min(layers[i].min_bitrate_bps, layers[i].max_bitrate_bps);
-      if (encoder_config.simulcast_layers[i].target_bitrate_bps <= 0) {
-        layers[i].target_bitrate_bps = std::max(
-            layers[i].target_bitrate_bps, layers[i].max_bitrate_bps * 3 / 4);
-      }
-      layers[i].target_bitrate_bps = std::max(
-          std::min(layers[i].target_bitrate_bps, layers[i].max_bitrate_bps),
-          layers[i].min_bitrate_bps);
-    }
-
-    if (encoder_config.simulcast_layers[i].max_qp > 0) {
-      layers[i].max_qp = encoder_config.simulcast_layers[i].max_qp;
-    } else if (encoder_config.max_qp > 0) {
-      layers[i].max_qp = encoder_config.max_qp;
-    } else {
-      layers[i].max_qp = GetDefaultMaxQp(encoder_config.codec_type);
-    }
-  }
-
-  bool is_highest_layer_max_bitrate_configured =
-      encoder_config.simulcast_layers[layers.size() - 1].max_bitrate_bps > 0;
-
-  if (!is_screencast && !is_highest_layer_max_bitrate_configured &&
-      encoder_config.max_bitrate_bps > 0) {
-    // No application-configured maximum for the largest layer.
-    // If there is bitrate leftover, give it to the largest layer.
-    BoostMaxSimulcastLayer(
-        webrtc::DataRate::BitsPerSec(encoder_config.max_bitrate_bps), &layers);
-  }
-
-  // Sort the layers by max_bitrate_bps, they might not always be from
-  // smallest to biggest
-  std::vector<size_t> index(layers.size());
-  std::iota(index.begin(), index.end(), 0);
-  std::stable_sort(index.begin(), index.end(), [&layers](size_t a, size_t b) {
-    return layers[a].max_bitrate_bps < layers[b].max_bitrate_bps;
-  });
-
-  if (!layers[index[0]].active) {
-    // Adjust min bitrate of the first active layer to allow it to go as low as
-    // the lowest (now inactive) layer could.
-    // Otherwise, if e.g. a single HD stream is active, it would have 600kbps
-    // min bitrate, which would always be allocated to the stream.
-    // This would lead to congested network, dropped frames and overall bad
-    // experience.
-
-    const int min_configured_bitrate = layers[index[0]].min_bitrate_bps;
-    for (size_t i = 0; i < layers.size(); ++i) {
-      if (layers[index[i]].active) {
-        layers[index[i]].min_bitrate_bps = min_configured_bitrate;
-        break;
-      }
-    }
-  }
+  OverrideStreamSettings(encoder_config, experimental_min_bitrate, layers);
 
   return layers;
 }