Add field trial for allowing cropped resolution when limiting max layers.
E.g. 480x270: max_layers:2
480x268: max_layers:1 -> 2.
Bug: none
Change-Id: Ieb86bc7b04e639d81e73d80aa0940b4c320e4de4
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/201730
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33030}
diff --git a/media/engine/simulcast.cc b/media/engine/simulcast.cc
index f74d4ad..375572f 100644
--- a/media/engine/simulcast.cc
+++ b/media/engine/simulcast.cc
@@ -23,6 +23,7 @@
#include "modules/video_coding/utility/simulcast_rate_allocator.h"
#include "rtc_base/arraysize.h"
#include "rtc_base/checks.h"
+#include "rtc_base/experiments/field_trial_parser.h"
#include "rtc_base/experiments/min_video_bitrate_experiment.h"
#include "rtc_base/experiments/normalize_simulcast_size_experiment.h"
#include "rtc_base/experiments/rate_control_settings.h"
@@ -61,7 +62,7 @@
int width;
int height;
// The maximum number of simulcast layers can be used for
- // resolutions at |widthxheigh| for legacy applications.
+ // resolutions at |widthxheight| for legacy applications.
size_t max_layers;
// The maximum bitrate for encoding stream at |widthxheight|, when we are
// not sending the next higher spatial stream.
@@ -162,7 +163,10 @@
return ((size >> base2_exponent) << base2_exponent);
}
-SimulcastFormat InterpolateSimulcastFormat(int width, int height) {
+SimulcastFormat InterpolateSimulcastFormat(
+ int width,
+ int height,
+ absl::optional<double> max_roundup_rate) {
const int index = FindSimulcastFormatIndex(width, height);
if (index == 0)
return kSimulcastFormats[index];
@@ -174,7 +178,10 @@
const float rate = (total_pixels_up - total_pixels) /
static_cast<float>(total_pixels_up - total_pixels_down);
- size_t max_layers = kSimulcastFormats[index].max_layers;
+ // Use upper resolution if |rate| is below the configured threshold.
+ size_t max_layers = (max_roundup_rate && rate < max_roundup_rate.value())
+ ? kSimulcastFormats[index - 1].max_layers
+ : kSimulcastFormats[index].max_layers;
webrtc::DataRate max_bitrate =
Interpolate(kSimulcastFormats[index - 1].max_bitrate,
kSimulcastFormats[index].max_bitrate, rate);
@@ -188,6 +195,10 @@
return {width, height, max_layers, max_bitrate, target_bitrate, min_bitrate};
}
+SimulcastFormat InterpolateSimulcastFormat(int width, int height) {
+ return InterpolateSimulcastFormat(width, height, absl::nullopt);
+}
+
webrtc::DataRate FindSimulcastMaxBitrate(int width, int height) {
return InterpolateSimulcastFormat(width, height).max_bitrate;
}
@@ -235,9 +246,18 @@
const webrtc::WebRtcKeyValueConfig& trials) {
if (!absl::StartsWith(trials.Lookup(kUseLegacySimulcastLayerLimitFieldTrial),
"Disabled")) {
+ // Max layers from one higher resolution in kSimulcastFormats will be used
+ // if the ratio (pixels_up - pixels) / (pixels_up - pixels_down) is less
+ // than configured |max_ratio|. pixels_down is the selected index in
+ // kSimulcastFormats based on pixels.
+ webrtc::FieldTrialOptional<double> max_ratio("max_ratio");
+ webrtc::ParseFieldTrial({&max_ratio},
+ trials.Lookup("WebRTC-SimulcastLayerLimitRoundUp"));
+
size_t adaptive_layer_count = std::max(
need_layers,
- kSimulcastFormats[FindSimulcastFormatIndex(width, height)].max_layers);
+ InterpolateSimulcastFormat(width, height, max_ratio.GetOptional())
+ .max_layers);
if (layer_count > adaptive_layer_count) {
RTC_LOG(LS_WARNING) << "Reducing simulcast layer count from "
<< layer_count << " to " << adaptive_layer_count;
diff --git a/media/engine/simulcast_unittest.cc b/media/engine/simulcast_unittest.cc
index 27b1574..193f8c0 100644
--- a/media/engine/simulcast_unittest.cc
+++ b/media/engine/simulcast_unittest.cc
@@ -378,4 +378,66 @@
}
}
+TEST(SimulcastTest, MaxLayers) {
+ FieldTrialBasedConfig trials;
+ const size_t kMinLayers = 1;
+ const int kMaxLayers = 3;
+
+ std::vector<VideoStream> streams;
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(3u, streams.size());
+ // <960x540: 2 layers
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 539,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(2u, streams.size());
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(2u, streams.size());
+ // <480x270: 1 layer
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 269,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(1u, streams.size());
+}
+
+TEST(SimulcastTest, MaxLayersWithFieldTrial) {
+ test::ScopedFieldTrials field_trials(
+ "WebRTC-SimulcastLayerLimitRoundUp/max_ratio:0.1/");
+ FieldTrialBasedConfig trials;
+ const size_t kMinLayers = 1;
+ const int kMaxLayers = 3;
+
+ std::vector<VideoStream> streams;
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 540,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(3u, streams.size());
+ // Lowest cropped height where max layers from higher resolution is used.
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 512,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(3u, streams.size());
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 960, 510,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(2u, streams.size());
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 270,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(2u, streams.size());
+ // Lowest cropped height where max layers from higher resolution is used.
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 256,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(2u, streams.size());
+ streams = cricket::GetSimulcastConfig(kMinLayers, kMaxLayers, 480, 254,
+ kBitratePriority, kQpMax, !kScreenshare,
+ true, trials);
+ EXPECT_EQ(1u, streams.size());
+}
+
} // namespace webrtc