From 258e9899f439196ee505edf825c2d1f66c21b143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=85sa=20Persson?= Date: Thu, 25 Feb 2021 10:39:51 +0100 Subject: [PATCH] Use default ResolutionBitrateLimits for simulcast with one active stream if not configured MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: none Change-Id: I049dd0924adc43ce249a8eda63cdcb13da42b030 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/208541 Reviewed-by: Sergey Silkin Commit-Queue: Åsa Persson Cr-Commit-Position: refs/heads/master@{#33343} --- rtc_base/experiments/encoder_info_settings.cc | 19 ++ rtc_base/experiments/encoder_info_settings.h | 5 + video/BUILD.gn | 2 + video/quality_scaling_tests.cc | 40 +++- video/video_stream_encoder.cc | 47 ++-- video/video_stream_encoder.h | 3 + video/video_stream_encoder_unittest.cc | 200 ++++++++++++++++++ 7 files changed, 302 insertions(+), 14 deletions(-) diff --git a/rtc_base/experiments/encoder_info_settings.cc b/rtc_base/experiments/encoder_info_settings.cc index a952c055bd..e0a186ea8c 100644 --- a/rtc_base/experiments/encoder_info_settings.cc +++ b/rtc_base/experiments/encoder_info_settings.cc @@ -32,6 +32,25 @@ std::vector ToResolutionBitrateLimits( } // 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 +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 +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 16ee9f9902..64bc88cbce 100644 --- a/rtc_base/experiments/encoder_info_settings.h +++ b/rtc_base/experiments/encoder_info_settings.h @@ -41,6 +41,11 @@ class EncoderInfoSettings { return resolution_bitrate_limits_; } + static std::vector + GetDefaultSinglecastBitrateLimits(); + static absl::optional + GetDefaultSinglecastBitrateLimitsForResolution(int frame_size_pixels); + protected: explicit EncoderInfoSettings(std::string name); diff --git a/video/BUILD.gn b/video/BUILD.gn index 1c92f36ccd..f296f44929 100644 --- a/video/BUILD.gn +++ b/video/BUILD.gn @@ -308,6 +308,7 @@ rtc_library("video_stream_encoder_impl") { "../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 @@ if (rtc_include_tests) { "../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 f1b6567ba0..6130e83093 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 @@ namespace { 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 @@ class QualityScalingTest : public test::CallTest { const std::string kPrefix = "WebRTC-Video-QualityScaling/Enabled-"; const std::string kEnd = ",0,0,0.9995,0.9999,1/"; + const absl::optional + kSinglecastLimits720p = + EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( + 1280 * 720); }; void QualityScalingTest::RunTest(const std::string& payload_name, @@ -210,10 +215,41 @@ TEST_F(QualityScalingTest, // 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 ae5872526c..cc6f36551e 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 @@ VideoLayersAllocation CreateVideoLayersAllocation( 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& streams) { int num_active = 0; for (const auto& stream : streams) { @@ -606,6 +623,8 @@ VideoStreamEncoder::VideoStreamEncoder( 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 @@ void VideoStreamEncoder::ReconfigureEncoder() { << ", 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 @@ void VideoStreamEncoder::ReconfigureEncoder() { // 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::ReconfigureEncoder() { } 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 @@ bool VideoStreamEncoder::DropDueToSize(uint32_t pixel_count) const { encoder_target_bitrate_bps_.value()); absl::optional 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 26d71d022e..b1c3bd8718 100644 --- a/video/video_stream_encoder.h +++ b/video/video_stream_encoder.h @@ -440,6 +440,9 @@ class VideoStreamEncoder : public VideoStreamEncoderInterface, 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 d74ebe84ad..5583ba5747 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" @@ -2091,6 +2092,70 @@ TEST_F(VideoStreamEncoderTest, video_stream_encoder_->Stop(); } +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( + "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 + 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(kDefaultLimits270p->min_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000); + EXPECT_EQ(static_cast(kDefaultLimits270p->max_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000); + + // Default bitrate limits for 360p should be used. + const absl::optional + kDefaultLimits360p = + EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( + 640 * 360); + video_source_.IncomingCapturedFrame(CreateFrame(2, 640, 360)); + EXPECT_FALSE(WaitForFrame(1000)); + EXPECT_EQ(static_cast(kDefaultLimits360p->min_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000); + EXPECT_EQ(static_cast(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(kDefaultLimits360p->min_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000); + EXPECT_EQ(static_cast(kDefaultLimits360p->max_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000); + + // Default bitrate limits for 540p should be used. + const absl::optional + kDefaultLimits540p = + EncoderInfoSettings::GetDefaultSinglecastBitrateLimitsForResolution( + 960 * 540); + video_source_.IncomingCapturedFrame(CreateFrame(4, 960, 540)); + EXPECT_FALSE(WaitForFrame(1000)); + EXPECT_EQ(static_cast(kDefaultLimits540p->min_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].minBitrate * 1000); + EXPECT_EQ(static_cast(kDefaultLimits540p->max_bitrate_bps), + fake_encoder_.video_codec().simulcastStream[1].maxBitrate * 1000); + + video_stream_encoder_->Stop(); +} + TEST_F(VideoStreamEncoderTest, EncoderMaxAndMinBitratesUsedForThreeStreamsMiddleActive) { const VideoEncoder::ResolutionBitrateLimits kEncoderLimits270p( @@ -5438,6 +5503,141 @@ TEST_F(VideoStreamEncoderTest, video_stream_encoder_->Stop(); } +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( + 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 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(kLimits360p->min_bitrate_bps), + fake_encoder_.video_codec().spatialLayers[0].minBitrate * 1000); + EXPECT_EQ(static_cast(kLimits360p->max_bitrate_bps), + fake_encoder_.video_codec().spatialLayers[0].maxBitrate * 1000); + + // The default bitrate limits for 270p should be used. + const absl::optional 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(kLimits270p->min_bitrate_bps), + fake_encoder_.video_codec().spatialLayers[0].minBitrate * 1000); + EXPECT_EQ(static_cast(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( + 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 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(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 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(kLimits720p->max_bitrate_bps), + fake_encoder_.video_codec().spatialLayers[0].maxBitrate * 1000); + + video_stream_encoder_->Stop(); +} + TEST_F(VideoStreamEncoderTest, EncoderMaxAndMinBitratesNotUsedIfLowestStreamActive) { const VideoEncoder::ResolutionBitrateLimits kEncoderLimits180p(