Use default ResolutionBitrateLimits for simulcast with one active stream if not configured
Bug: none
Change-Id: I049dd0924adc43ce249a8eda63cdcb13da42b030
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/208541
Reviewed-by: Sergey Silkin <ssilkin@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33343}
diff --git a/rtc_base/experiments/encoder_info_settings.cc b/rtc_base/experiments/encoder_info_settings.cc
index a952c05..e0a186e 100644
--- a/rtc_base/experiments/encoder_info_settings.cc
+++ b/rtc_base/experiments/encoder_info_settings.cc
@@ -32,6 +32,25 @@
} // namespace
+// Default bitrate limits for simulcast with one active stream:
+// {frame_size_pixels, min_start_bitrate_bps, min_bitrate_bps, max_bitrate_bps}.
+std::vector<VideoEncoder::ResolutionBitrateLimits>
+EncoderInfoSettings::GetDefaultSinglecastBitrateLimits() {
+ return {{320 * 180, 0, 30000, 300000},
+ {480 * 270, 200000, 30000, 500000},
+ {640 * 360, 300000, 30000, 800000},
+ {960 * 540, 500000, 30000, 1500000},
+ {1280 * 720, 900000, 30000, 2500000}};
+}
+
+absl::optional<VideoEncoder::ResolutionBitrateLimits>
+EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
+ int frame_size_pixels) {
+ VideoEncoder::EncoderInfo info;
+ info.resolution_bitrate_limits = GetDefaultSinglecastBitrateLimits();
+ return info.GetEncoderBitrateLimitsForResolution(frame_size_pixels);
+}
+
EncoderInfoSettings::EncoderInfoSettings(std::string name)
: requested_resolution_alignment_("requested_resolution_alignment"),
apply_alignment_to_all_simulcast_layers_(
diff --git a/rtc_base/experiments/encoder_info_settings.h b/rtc_base/experiments/encoder_info_settings.h
index 16ee9f9..64bc88c 100644
--- a/rtc_base/experiments/encoder_info_settings.h
+++ b/rtc_base/experiments/encoder_info_settings.h
@@ -41,6 +41,11 @@
return resolution_bitrate_limits_;
}
+ static std::vector<VideoEncoder::ResolutionBitrateLimits>
+ GetDefaultSinglecastBitrateLimits();
+ static absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ GetDefaultSinglecastBitrateLimitsForResolution(int frame_size_pixels);
+
protected:
explicit EncoderInfoSettings(std::string name);
diff --git a/video/BUILD.gn b/video/BUILD.gn
index 1c92f36..f296f44 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -308,6 +308,7 @@
"../rtc_base:timeutils",
"../rtc_base/experiments:alr_experiment",
"../rtc_base/experiments:balanced_degradation_settings",
+ "../rtc_base/experiments:encoder_info_settings",
"../rtc_base/experiments:field_trial_parser",
"../rtc_base/experiments:quality_rampup_experiment",
"../rtc_base/experiments:quality_scaler_settings",
@@ -712,6 +713,7 @@
"../rtc_base:task_queue_for_test",
"../rtc_base:threading",
"../rtc_base/experiments:alr_experiment",
+ "../rtc_base/experiments:encoder_info_settings",
"../rtc_base/synchronization:mutex",
"../rtc_base/task_utils:to_queued_task",
"../system_wrappers",
diff --git a/video/quality_scaling_tests.cc b/video/quality_scaling_tests.cc
index f1b6567..6130e83 100644
--- a/video/quality_scaling_tests.cc
+++ b/video/quality_scaling_tests.cc
@@ -15,6 +15,7 @@
#include "modules/video_coding/codecs/h264/include/h264.h"
#include "modules/video_coding/codecs/vp8/include/vp8.h"
#include "modules/video_coding/codecs/vp9/include/vp9.h"
+#include "rtc_base/experiments/encoder_info_settings.h"
#include "test/call_test.h"
#include "test/field_trial.h"
#include "test/frame_generator_capturer.h"
@@ -24,7 +25,7 @@
constexpr int kWidth = 1280;
constexpr int kHeight = 720;
constexpr int kLowStartBps = 100000;
-constexpr int kHighStartBps = 600000;
+constexpr int kHighStartBps = 1000000;
constexpr size_t kTimeoutMs = 10000; // Some tests are expected to time out.
void SetEncoderSpecific(VideoEncoderConfig* encoder_config,
@@ -56,6 +57,10 @@
const std::string kPrefix = "WebRTC-Video-QualityScaling/Enabled-";
const std::string kEnd = ",0,0,0.9995,0.9999,1/";
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ kSinglecastLimits720p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
+ 1280 * 720);
};
void QualityScalingTest::RunTest(const std::string& payload_name,
@@ -210,10 +215,41 @@
// qp_low:1, qp_high:127 -> kNormalQp
test::ScopedFieldTrials field_trials(kPrefix + "1,127,0,0,0,0" + kEnd);
- RunTest("VP8", {false, false, true}, kLowStartBps,
+ RunTest("VP8", {false, false, true},
+ kSinglecastLimits720p->min_start_bitrate_bps - 1,
/*automatic_resize=*/true, /*expect_adaptation=*/true);
}
+TEST_F(QualityScalingTest, NoAdaptDownForLowStartBitrateIfBitrateEnough_Vp8) {
+ // qp_low:1, qp_high:127 -> kNormalQp
+ test::ScopedFieldTrials field_trials(kPrefix + "1,127,0,0,0,0" + kEnd);
+
+ RunTest("VP8", {false, false, true},
+ kSinglecastLimits720p->min_start_bitrate_bps,
+ /*automatic_resize=*/true, /*expect_adaptation=*/false);
+}
+
+TEST_F(QualityScalingTest,
+ NoAdaptDownForLowStartBitrateIfDefaultLimitsDisabled_Vp8) {
+ // qp_low:1, qp_high:127 -> kNormalQp
+ test::ScopedFieldTrials field_trials(
+ kPrefix + "1,127,0,0,0,0" + kEnd +
+ "WebRTC-DefaultBitrateLimitsKillSwitch/Enabled/");
+
+ RunTest("VP8", {false, false, true},
+ kSinglecastLimits720p->min_start_bitrate_bps - 1,
+ /*automatic_resize=*/true, /*expect_adaptation=*/false);
+}
+
+TEST_F(QualityScalingTest,
+ NoAdaptDownForLowStartBitrate_OneStreamSinglecastLimitsNotUsed_Vp8) {
+ // qp_low:1, qp_high:127 -> kNormalQp
+ test::ScopedFieldTrials field_trials(kPrefix + "1,127,0,0,0,0" + kEnd);
+
+ RunTest("VP8", {true}, kSinglecastLimits720p->min_start_bitrate_bps - 1,
+ /*automatic_resize=*/true, /*expect_adaptation=*/false);
+}
+
TEST_F(QualityScalingTest, NoAdaptDownForHighQp_LowestStreamActive_Vp8) {
// qp_low:1, qp_high:1 -> kHighQp
test::ScopedFieldTrials field_trials(kPrefix + "1,1,0,0,0,0" + kEnd);
diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc
index ae58725..cc6f365 100644
--- a/video/video_stream_encoder.cc
+++ b/video/video_stream_encoder.cc
@@ -38,6 +38,7 @@
#include "rtc_base/constructor_magic.h"
#include "rtc_base/event.h"
#include "rtc_base/experiments/alr_experiment.h"
+#include "rtc_base/experiments/encoder_info_settings.h"
#include "rtc_base/experiments/rate_control_settings.h"
#include "rtc_base/location.h"
#include "rtc_base/logging.h"
@@ -339,6 +340,22 @@
return layers_allocation;
}
+VideoEncoder::EncoderInfo GetEncoderInfoWithBitrateLimitUpdate(
+ const VideoEncoder::EncoderInfo& info,
+ const VideoEncoderConfig& encoder_config,
+ bool default_limits_allowed) {
+ if (!default_limits_allowed || !info.resolution_bitrate_limits.empty() ||
+ encoder_config.simulcast_layers.size() <= 1) {
+ return info;
+ }
+ // Bitrate limits are not configured and more than one layer is used, use
+ // the default limits (bitrate limits are not used for simulcast).
+ VideoEncoder::EncoderInfo new_info = info;
+ new_info.resolution_bitrate_limits =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimits();
+ return new_info;
+}
+
int NumActiveStreams(const std::vector<VideoStream>& streams) {
int num_active = 0;
for (const auto& stream : streams) {
@@ -606,6 +623,8 @@
degradation_preference_manager_.get()),
video_source_sink_controller_(/*sink=*/this,
/*source=*/nullptr),
+ default_limits_allowed_(
+ !field_trial::IsEnabled("WebRTC-DefaultBitrateLimitsKillSwitch")),
encoder_queue_(task_queue_factory->CreateTaskQueue(
"EncoderQueue",
TaskQueueFactory::Priority::NORMAL)) {
@@ -919,13 +938,14 @@
<< ", max=" << encoder_config_.max_bitrate_bps
<< "). The app bitrate limits will be used.";
}
- } else {
- ApplyEncoderBitrateLimitsIfSingleActiveStream(
- encoder_->GetEncoderInfo(), encoder_config_.simulcast_layers,
- &streams);
}
}
+ ApplyEncoderBitrateLimitsIfSingleActiveStream(
+ GetEncoderInfoWithBitrateLimitUpdate(
+ encoder_->GetEncoderInfo(), encoder_config_, default_limits_allowed_),
+ encoder_config_.simulcast_layers, &streams);
+
VideoCodec codec;
if (!VideoCodecInitializer::SetupCodec(encoder_config_, streams, &codec)) {
RTC_LOG(LS_ERROR) << "Failed to create encoder configuration.";
@@ -936,10 +956,10 @@
// thus some cropping might be needed.
crop_width_ = last_frame_info_->width - codec.width;
crop_height_ = last_frame_info_->height - codec.height;
- if (encoder_bitrate_limits_) {
- ApplyVp9BitrateLimits(encoder_->GetEncoderInfo(), encoder_config_,
- &codec);
- }
+ ApplyVp9BitrateLimits(GetEncoderInfoWithBitrateLimitUpdate(
+ encoder_->GetEncoderInfo(), encoder_config_,
+ default_limits_allowed_),
+ encoder_config_, &codec);
}
char log_stream_buf[4 * 1024];
@@ -1177,8 +1197,10 @@
}
void VideoStreamEncoder::OnEncoderSettingsChanged() {
- EncoderSettings encoder_settings(encoder_->GetEncoderInfo(),
- encoder_config_.Copy(), send_codec_);
+ EncoderSettings encoder_settings(
+ GetEncoderInfoWithBitrateLimitUpdate(
+ encoder_->GetEncoderInfo(), encoder_config_, default_limits_allowed_),
+ encoder_config_.Copy(), send_codec_);
stream_resource_manager_.SetEncoderSettings(encoder_settings);
input_state_provider_.OnEncoderSettingsChanged(encoder_settings);
bool is_screenshare = encoder_settings.encoder_config().content_type ==
@@ -2075,8 +2097,9 @@
encoder_target_bitrate_bps_.value());
absl::optional<VideoEncoder::ResolutionBitrateLimits> encoder_bitrate_limits =
- encoder_->GetEncoderInfo().GetEncoderBitrateLimitsForResolution(
- pixel_count);
+ GetEncoderInfoWithBitrateLimitUpdate(
+ encoder_->GetEncoderInfo(), encoder_config_, default_limits_allowed_)
+ .GetEncoderBitrateLimitsForResolution(pixel_count);
if (encoder_bitrate_limits.has_value()) {
// Use bitrate limits provided by encoder.
diff --git a/video/video_stream_encoder.h b/video/video_stream_encoder.h
index 26d71d0..b1c3bd8 100644
--- a/video/video_stream_encoder.h
+++ b/video/video_stream_encoder.h
@@ -440,6 +440,9 @@
VideoSourceSinkController video_source_sink_controller_
RTC_GUARDED_BY(main_queue_);
+ // Default bitrate limits in EncoderInfoSettings allowed.
+ const bool default_limits_allowed_;
+
// Public methods are proxied to the task queues. The queues must be destroyed
// first to make sure no tasks run that use other members.
rtc::TaskQueue encoder_queue_;
diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc
index d74ebe8..5583ba5 100644
--- a/video/video_stream_encoder_unittest.cc
+++ b/video/video_stream_encoder_unittest.cc
@@ -37,6 +37,7 @@
#include "modules/video_coding/utility/quality_scaler.h"
#include "modules/video_coding/utility/simulcast_rate_allocator.h"
#include "rtc_base/event.h"
+#include "rtc_base/experiments/encoder_info_settings.h"
#include "rtc_base/gunit.h"
#include "rtc_base/logging.h"
#include "rtc_base/ref_counted_object.h"
@@ -2092,6 +2093,70 @@
}
TEST_F(VideoStreamEncoderTest,
+ DefaultEncoderMaxAndMinBitratesUsedForTwoStreamsHighestActive) {
+ // Two streams, highest stream active.
+ VideoEncoderConfig config;
+ const int kNumStreams = 2;
+ test::FillEncoderConfiguration(kVideoCodecVP8, kNumStreams, &config);
+ config.max_bitrate_bps = 0;
+ config.simulcast_layers[0].active = false;
+ config.simulcast_layers[1].active = true;
+ config.video_stream_factory =
+ new rtc::RefCountedObject<cricket::EncoderStreamFactory>(
+ "VP8", /*max qp*/ 56, /*screencast*/ false,
+ /*screenshare enabled*/ false);
+ video_stream_encoder_->ConfigureEncoder(config.Copy(), kMaxPayloadLength);
+
+ // Default bitrate limits for 270p should be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ kDefaultLimits270p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
+ 480 * 270);
+ video_source_.IncomingCapturedFrame(CreateFrame(1, 480, 270));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(fake_encoder_.video_codec().numberOfSimulcastStreams, kNumStreams);
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits270p->min_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000);
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits270p->max_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000);
+
+ // Default bitrate limits for 360p should be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ kDefaultLimits360p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
+ 640 * 360);
+ video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->min_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000);
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->max_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000);
+
+ // Resolution b/w 270p and 360p. The default limits for 360p should be used.
+ video_source_.IncomingCapturedFrame(
+ CreateFrame(3, (640 + 480) / 2, (360 + 270) / 2));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->min_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000);
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits360p->max_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000);
+
+ // Default bitrate limits for 540p should be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits>
+ kDefaultLimits540p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(
+ 960 * 540);
+ video_source_.IncomingCapturedFrame(CreateFrame(4, 960, 540));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits540p->min_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000);
+ EXPECT_EQ(static_cast<uint32_t>(kDefaultLimits540p->max_bitrate_bps),
+ fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000);
+
+ video_stream_encoder_->Stop();
+}
+
+TEST_F(VideoStreamEncoderTest,
EncoderMaxAndMinBitratesUsedForThreeStreamsMiddleActive) {
const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p(
480 * 270, 34 * 1000, 12 * 1000, 1234 * 1000);
@@ -5439,6 +5504,141 @@
}
TEST_F(VideoStreamEncoderTest,
+ DefaultMaxAndMinBitratesUsedIfMiddleStreamActive) {
+ VideoEncoderConfig video_encoder_config;
+ test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
+ &video_encoder_config);
+ VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
+ vp9_settings.numberOfSpatialLayers = 3;
+ // Since only one layer is active - automatic resize should be enabled.
+ vp9_settings.automaticResizeOn = true;
+ video_encoder_config.encoder_specific_settings =
+ new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
+ vp9_settings);
+ video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrateBps;
+ video_encoder_config.content_type =
+ VideoEncoderConfig::ContentType::kRealtimeVideo;
+ // Simulcast layers are used to indicate which spatial layers are active.
+ video_encoder_config.simulcast_layers.resize(3);
+ video_encoder_config.simulcast_layers[0].active = false;
+ video_encoder_config.simulcast_layers[1].active = true;
+ video_encoder_config.simulcast_layers[2].active = false;
+
+ video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
+ kMaxPayloadLength);
+ video_stream_encoder_->WaitUntilTaskQueueIsIdle();
+
+ // The default bitrate limits for 360p should be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits360p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(640 *
+ 360);
+ video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(fake_encoder_.video_codec().numberOfSimulcastStreams, 1);
+ EXPECT_EQ(fake_encoder_.video_codec().codecType,
+ VideoCodecType::kVideoCodecVP9);
+ EXPECT_EQ(fake_encoder_.video_codec().VP9()->numberOfSpatialLayers, 2);
+ EXPECT_TRUE(fake_encoder_.video_codec().spatialLayers[0].active);
+ EXPECT_EQ(640, fake_encoder_.video_codec().spatialLayers[0].width);
+ EXPECT_EQ(360, fake_encoder_.video_codec().spatialLayers[0].height);
+ EXPECT_EQ(static_cast<uint32_t>(kLimits360p->min_bitrate_bps),
+ fake_encoder_.video_codec().spatialLayers[0].minBitrate * 1000);
+ EXPECT_EQ(static_cast<uint32_t>(kLimits360p->max_bitrate_bps),
+ fake_encoder_.video_codec().spatialLayers[0].maxBitrate * 1000);
+
+ // The default bitrate limits for 270p should be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits270p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(480 *
+ 270);
+ video_source_.IncomingCapturedFrame(CreateFrame(2, 960, 540));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(fake_encoder_.video_codec().numberOfSimulcastStreams, 1);
+ EXPECT_EQ(fake_encoder_.video_codec().codecType,
+ VideoCodecType::kVideoCodecVP9);
+ EXPECT_EQ(fake_encoder_.video_codec().VP9()->numberOfSpatialLayers, 2);
+ EXPECT_TRUE(fake_encoder_.video_codec().spatialLayers[0].active);
+ EXPECT_EQ(480, fake_encoder_.video_codec().spatialLayers[0].width);
+ EXPECT_EQ(270, fake_encoder_.video_codec().spatialLayers[0].height);
+ EXPECT_EQ(static_cast<uint32_t>(kLimits270p->min_bitrate_bps),
+ fake_encoder_.video_codec().spatialLayers[0].minBitrate * 1000);
+ EXPECT_EQ(static_cast<uint32_t>(kLimits270p->max_bitrate_bps),
+ fake_encoder_.video_codec().spatialLayers[0].maxBitrate * 1000);
+
+ video_stream_encoder_->Stop();
+}
+
+TEST_F(VideoStreamEncoderTest, DefaultMaxAndMinBitratesNotUsedIfDisabled) {
+ webrtc::test::ScopedFieldTrials field_trials(
+ "WebRTC-DefaultBitrateLimitsKillSwitch/Enabled/");
+ VideoEncoderConfig video_encoder_config;
+ test::FillEncoderConfiguration(PayloadStringToCodecType("VP9"), 1,
+ &video_encoder_config);
+ VideoCodecVP9 vp9_settings = VideoEncoder::GetDefaultVp9Settings();
+ vp9_settings.numberOfSpatialLayers = 3;
+ // Since only one layer is active - automatic resize should be enabled.
+ vp9_settings.automaticResizeOn = true;
+ video_encoder_config.encoder_specific_settings =
+ new rtc::RefCountedObject<VideoEncoderConfig::Vp9EncoderSpecificSettings>(
+ vp9_settings);
+ video_encoder_config.max_bitrate_bps = kSimulcastTargetBitrateBps;
+ video_encoder_config.content_type =
+ VideoEncoderConfig::ContentType::kRealtimeVideo;
+ // Simulcast layers are used to indicate which spatial layers are active.
+ video_encoder_config.simulcast_layers.resize(3);
+ video_encoder_config.simulcast_layers[0].active = false;
+ video_encoder_config.simulcast_layers[1].active = true;
+ video_encoder_config.simulcast_layers[2].active = false;
+
+ // Reset encoder for field trials to take effect.
+ ConfigureEncoder(video_encoder_config.Copy());
+
+ video_stream_encoder_->ConfigureEncoder(video_encoder_config.Copy(),
+ kMaxPayloadLength);
+ video_stream_encoder_->WaitUntilTaskQueueIsIdle();
+
+ // The default bitrate limits for 360p should not be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits360p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(640 *
+ 360);
+ video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(fake_encoder_.video_codec().numberOfSimulcastStreams, 1);
+ EXPECT_EQ(fake_encoder_.video_codec().codecType,
+ VideoCodecType::kVideoCodecVP9);
+ EXPECT_EQ(fake_encoder_.video_codec().VP9()->numberOfSpatialLayers, 2);
+ EXPECT_TRUE(fake_encoder_.video_codec().spatialLayers[0].active);
+ EXPECT_EQ(640, fake_encoder_.video_codec().spatialLayers[0].width);
+ EXPECT_EQ(360, fake_encoder_.video_codec().spatialLayers[0].height);
+ EXPECT_NE(static_cast<uint32_t>(kLimits360p->max_bitrate_bps),
+ fake_encoder_.video_codec().spatialLayers[0].maxBitrate * 1000);
+
+ video_stream_encoder_->Stop();
+}
+
+TEST_F(VideoStreamEncoderTest, SinglecastBitrateLimitsNotUsedForOneStream) {
+ ResetEncoder("VP9", /*num_streams=*/1, /*num_temporal_layers=*/1,
+ /*num_spatial_layers=*/1, /*screenshare=*/false);
+
+ // The default singlecast bitrate limits for 720p should not be used.
+ const absl::optional<VideoEncoder::ResolutionBitrateLimits> kLimits720p =
+ EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution(1280 *
+ 720);
+ video_source_.IncomingCapturedFrame(CreateFrame(1, 1280, 720));
+ EXPECT_FALSE(WaitForFrame(1000));
+ EXPECT_EQ(fake_encoder_.video_codec().numberOfSimulcastStreams, 1);
+ EXPECT_EQ(fake_encoder_.video_codec().codecType,
+ VideoCodecType::kVideoCodecVP9);
+ EXPECT_EQ(fake_encoder_.video_codec().VP9()->numberOfSpatialLayers, 1);
+ EXPECT_TRUE(fake_encoder_.video_codec().spatialLayers[0].active);
+ EXPECT_EQ(1280, fake_encoder_.video_codec().spatialLayers[0].width);
+ EXPECT_EQ(720, fake_encoder_.video_codec().spatialLayers[0].height);
+ EXPECT_NE(static_cast<uint32_t>(kLimits720p->max_bitrate_bps),
+ fake_encoder_.video_codec().spatialLayers[0].maxBitrate * 1000);
+
+ video_stream_encoder_->Stop();
+}
+
+TEST_F(VideoStreamEncoderTest,
EncoderMaxAndMinBitratesNotUsedIfLowestStreamActive) {
const VideoEncoder::ResolutionBitrateLimits kEncoderLimits180p(
320 * 180, 34 * 1000, 12 * 1000, 1234 * 1000);