diff --git a/experiments/field_trials.py b/experiments/field_trials.py index 12338e360a..26328e6834 100755 --- a/experiments/field_trials.py +++ b/experiments/field_trials.py @@ -59,6 +59,9 @@ ACTIVE_FIELD_TRIALS: FrozenSet[FieldTrial] = frozenset([ FieldTrial('WebRTC-Av1-GetEncoderInfoOverride', 42225234, date(2024, 4, 1)), + FieldTrial('WebRTC-BitrateAdjusterUseNewfangledHeadroomAdjustment', + 349561566, + date(2025, 8, 26)), FieldTrial('WebRTC-Bwe-LimitPacingFactorByUpperLinkCapacityEstimate', 42220543, date(2025, 1, 1)), diff --git a/video/encoder_bitrate_adjuster.cc b/video/encoder_bitrate_adjuster.cc index 0dbcb075bd..ae25527427 100644 --- a/video/encoder_bitrate_adjuster.cc +++ b/video/encoder_bitrate_adjuster.cc @@ -41,19 +41,23 @@ struct LayerRateInfo { } }; } // namespace -constexpr int64_t EncoderBitrateAdjuster::kWindowSizeMs; +constexpr TimeDelta EncoderBitrateAdjuster::kWindowSize; constexpr size_t EncoderBitrateAdjuster::kMinFramesSinceLayoutChange; constexpr double EncoderBitrateAdjuster::kDefaultUtilizationFactor; EncoderBitrateAdjuster::EncoderBitrateAdjuster( const VideoCodec& codec_settings, - const FieldTrialsView& field_trials) + const FieldTrialsView& field_trials, + Clock& clock) : utilize_bandwidth_headroom_(RateControlSettings(field_trials) .BitrateAdjusterCanUseNetworkHeadroom()), + use_newfangled_headroom_adjustment_(field_trials.IsEnabled( + "WebRTC-BitrateAdjusterUseNewfangledHeadroomAdjustment")), frames_since_layout_change_(0), min_bitrates_bps_{}, codec_(codec_settings.codecType), - codec_mode_(codec_settings.mode) { + codec_mode_(codec_settings.mode), + clock_(clock) { // TODO(https://crbug.com/webrtc/14891): If we want to support simulcast of // SVC streams, EncoderBitrateAdjuster needs to be updated to care about both // `simulcastStream` and `spatialLayers` at the same time. @@ -94,6 +98,7 @@ EncoderBitrateAdjuster::~EncoderBitrateAdjuster() = default; VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( const VideoEncoder::RateControlParameters& rates) { current_rate_control_parameters_ = rates; + const Timestamp now = clock_.CurrentTime(); // First check that overshoot detectors exist, and store per simulcast/spatial // layer how many active temporal layers we have. @@ -109,7 +114,7 @@ VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( if (!overshoot_detectors_[si][ti]) { overshoot_detectors_[si][ti] = std::make_unique( - kWindowSizeMs, codec_, + kWindowSize.ms(), codec_, codec_mode_ == VideoCodecMode::kScreensharing); frames_since_layout_change_ = 0; } @@ -119,10 +124,26 @@ VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( frames_since_layout_change_ = 0; } } + if (use_newfangled_headroom_adjustment_) { + // Instantiate average media rate trackers, one per active spatial layer. + + DataRate spatial_layer_rate = + DataRate::BitsPerSec(rates.bitrate.GetSpatialLayerSum(si)); + if (spatial_layer_rate.IsZero()) { + media_rate_trackers_[si].reset(); + } else { + if (media_rate_trackers_[si] == nullptr) { + constexpr int kMaxDataPointsInUtilizationTrackers = 100; + media_rate_trackers_[si] = std::make_unique( + kMaxDataPointsInUtilizationTrackers, kWindowSize); + } + // Media rate trackers use the unadjusted target rate. + media_rate_trackers_[si]->OnDataRateChanged(spatial_layer_rate, now); + } + } } // Next poll the overshoot detectors and populate the adjusted allocation. - const int64_t now_ms = rtc::TimeMillis(); VideoBitrateAllocation adjusted_allocation; std::vector layer_infos; DataRate wanted_overshoot_sum = DataRate::Zero(); @@ -153,12 +174,16 @@ VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( RTC_DCHECK(overshoot_detectors_[si][0]); layer_info.link_utilization_factor = overshoot_detectors_[si][0] - ->GetNetworkRateUtilizationFactor(now_ms) + ->GetNetworkRateUtilizationFactor(now.ms()) .value_or(kDefaultUtilizationFactor); layer_info.media_utilization_factor = - overshoot_detectors_[si][0] - ->GetMediaRateUtilizationFactor(now_ms) - .value_or(kDefaultUtilizationFactor); + use_newfangled_headroom_adjustment_ + ? media_rate_trackers_[si] + ->GetRateUtilizationFactor(now) + .value_or(kDefaultUtilizationFactor) + : overshoot_detectors_[si][0] + ->GetMediaRateUtilizationFactor(now.ms()) + .value_or(kDefaultUtilizationFactor); } else if (layer_info.target_rate > DataRate::Zero()) { // Multiple temporal layers enabled for this simulcast/spatial layer. // Update rate for each of them and make a weighted average of utilization @@ -170,9 +195,11 @@ VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( RTC_DCHECK(overshoot_detectors_[si][ti]); const absl::optional ti_link_utilization_factor = overshoot_detectors_[si][ti]->GetNetworkRateUtilizationFactor( - now_ms); + now.ms()); + const absl::optional ti_media_utilization_factor = - overshoot_detectors_[si][ti]->GetMediaRateUtilizationFactor(now_ms); + overshoot_detectors_[si][ti]->GetMediaRateUtilizationFactor( + now.ms()); if (!ti_link_utilization_factor || !ti_media_utilization_factor) { layer_info.link_utilization_factor = kDefaultUtilizationFactor; layer_info.media_utilization_factor = kDefaultUtilizationFactor; @@ -186,14 +213,17 @@ VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( layer_info.media_utilization_factor += weight * ti_media_utilization_factor.value(); } + + if (use_newfangled_headroom_adjustment_) { + layer_info.media_utilization_factor = + media_rate_trackers_[si]->GetRateUtilizationFactor(now).value_or( + kDefaultUtilizationFactor); + } } else { RTC_DCHECK_NOTREACHED(); } if (layer_info.link_utilization_factor < 1.0) { - // TODO(sprang): Consider checking underuse and allowing it to cancel some - // potential overuse by other streams. - // Don't boost target bitrate if encoder is under-using. layer_info.link_utilization_factor = 1.0; } else { @@ -313,7 +343,7 @@ VideoBitrateAllocation EncoderBitrateAdjuster::AdjustRateAllocation( overshoot_detectors_[si][ti]->SetTargetRate( DataRate::BitsPerSec(layer_bitrate_bps), - fps_fraction * rates.framerate_fps, now_ms); + fps_fraction * rates.framerate_fps, now.ms()); } } } @@ -345,6 +375,10 @@ void EncoderBitrateAdjuster::OnEncodedFrame(DataSize size, if (detector) { detector->OnEncodedFrame(size.bytes(), rtc::TimeMillis()); } + if (media_rate_trackers_[stream_index]) { + media_rate_trackers_[stream_index]->OnDataProduced(size, + clock_.CurrentTime()); + } } void EncoderBitrateAdjuster::Reset() { @@ -352,6 +386,7 @@ void EncoderBitrateAdjuster::Reset() { for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) { overshoot_detectors_[si][ti].reset(); } + media_rate_trackers_[si].reset(); } // Call AdjustRateAllocation() with the last know bitrate allocation, so that // the appropriate overuse detectors are immediately re-created. diff --git a/video/encoder_bitrate_adjuster.h b/video/encoder_bitrate_adjuster.h index 7150bee668..9248b0d5eb 100644 --- a/video/encoder_bitrate_adjuster.h +++ b/video/encoder_bitrate_adjuster.h @@ -14,17 +14,20 @@ #include #include "api/field_trials_view.h" +#include "api/units/time_delta.h" #include "api/video/encoded_image.h" #include "api/video/video_bitrate_allocation.h" #include "api/video_codecs/video_encoder.h" +#include "system_wrappers/include/clock.h" #include "video/encoder_overshoot_detector.h" +#include "video/rate_utilization_tracker.h" namespace webrtc { class EncoderBitrateAdjuster { public: // Size of sliding window used to track overshoot rate. - static constexpr int64_t kWindowSizeMs = 3000; + static constexpr TimeDelta kWindowSize = TimeDelta::Seconds(3); // Minimum number of frames since last layout change required to trust the // overshoot statistics. Otherwise falls back to default utilization. // By layout change, we mean any simulcast/spatial/temporal layer being either @@ -36,7 +39,8 @@ class EncoderBitrateAdjuster { static constexpr double kDefaultUtilizationFactor = 1.2; EncoderBitrateAdjuster(const VideoCodec& codec_settings, - const FieldTrialsView& field_trials); + const FieldTrialsView& field_trials, + Clock& clock); ~EncoderBitrateAdjuster(); // Adjusts the given rate allocation to make it paceable within the target @@ -59,6 +63,7 @@ class EncoderBitrateAdjuster { private: const bool utilize_bandwidth_headroom_; + const bool use_newfangled_headroom_adjustment_; VideoEncoder::RateControlParameters current_rate_control_parameters_; // FPS allocation of temporal layers, per simulcast/spatial layer. Represented @@ -73,6 +78,10 @@ class EncoderBitrateAdjuster { std::unique_ptr overshoot_detectors_[kMaxSpatialLayers][kMaxTemporalStreams]; + // Per spatial layer track of average media utilization. + std::unique_ptr + media_rate_trackers_[kMaxSpatialLayers]; + // Minimum bitrates allowed, per spatial layer. uint32_t min_bitrates_bps_[kMaxSpatialLayers]; @@ -81,6 +90,8 @@ class EncoderBitrateAdjuster { // Codec mode: { kRealtimeVideo, kScreensharing }. VideoCodecMode codec_mode_; + + Clock& clock_; }; } // namespace webrtc diff --git a/video/encoder_bitrate_adjuster_unittest.cc b/video/encoder_bitrate_adjuster_unittest.cc index ad672f617b..f65c366381 100644 --- a/video/encoder_bitrate_adjuster_unittest.cc +++ b/video/encoder_bitrate_adjuster_unittest.cc @@ -11,19 +11,26 @@ #include "video/encoder_bitrate_adjuster.h" #include +#include #include #include "api/field_trials_view.h" #include "api/units/data_rate.h" -#include "rtc_base/fake_clock.h" +#include "rtc_base/logging.h" #include "rtc_base/numerics/safe_conversions.h" #include "test/gtest.h" #include "test/scoped_key_value_config.h" +#include "test/time_controller/simulated_time_controller.h" namespace webrtc { namespace test { -class EncoderBitrateAdjusterTest : public ::testing::Test { +using ::testing::Test; +using ::testing::Values; +using ::testing::WithParamInterface; + +class EncoderBitrateAdjusterTest : public Test, + public WithParamInterface { public: static constexpr int64_t kWindowSizeMs = 3000; static constexpr int kDefaultBitrateBps = 300000; @@ -35,10 +42,12 @@ class EncoderBitrateAdjusterTest : public ::testing::Test { static_assert(kSequenceLength % 2 == 0, "Sequence length must be even."); EncoderBitrateAdjusterTest() - : target_bitrate_(DataRate::BitsPerSec(kDefaultBitrateBps)), + : time_controller_(/*start_time=*/Timestamp::Millis(123)), + target_bitrate_(DataRate::BitsPerSec(kDefaultBitrateBps)), target_framerate_fps_(kDefaultFrameRateFps), tl_pattern_idx_{}, - sequence_idx_{} {} + sequence_idx_{}, + scoped_field_trial_(GetParam()) {} protected: void SetUpAdjusterWithCodec(size_t num_spatial_layers, @@ -55,8 +64,8 @@ class EncoderBitrateAdjusterTest : public ::testing::Test { } } - adjuster_ = - std::make_unique(codec_, scoped_field_trial_); + adjuster_ = std::make_unique( + codec_, scoped_field_trial_, *time_controller_.GetClock()); adjuster_->OnEncoderInfo(encoder_info_); current_adjusted_allocation_ = adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters( @@ -112,7 +121,8 @@ class EncoderBitrateAdjusterTest : public ::testing::Test { const int64_t start_us = rtc::TimeMicros(); while (rtc::TimeMicros() < start_us + (duration_ms * rtc::kNumMicrosecsPerMillisec)) { - clock_.AdvanceTime(TimeDelta::Seconds(1) / target_framerate_fps_); + time_controller_.AdvanceTime(TimeDelta::Seconds(1) / + target_framerate_fps_); for (size_t si = 0; si < NumSpatialLayers(); ++si) { const std::vector& tl_pattern = kTlPatterns[NumTemporalLayers(si) - 1]; @@ -231,12 +241,14 @@ class EncoderBitrateAdjusterTest : public ::testing::Test { return multiplied_allocation; } + GlobalSimulatedTimeController time_controller_; + VideoCodec codec_; VideoEncoder::EncoderInfo encoder_info_; std::unique_ptr adjuster_; VideoBitrateAllocation current_input_allocation_; VideoBitrateAllocation current_adjusted_allocation_; - rtc::ScopedFakeClock clock_; + DataRate target_bitrate_; double target_framerate_fps_; int tl_pattern_idx_[kMaxSpatialLayers]; @@ -250,7 +262,7 @@ class EncoderBitrateAdjusterTest : public ::testing::Test { {0, 3, 2, 3, 1, 3, 2, 3}}; }; -TEST_F(EncoderBitrateAdjusterTest, SingleLayerOptimal) { +TEST_P(EncoderBitrateAdjusterTest, SingleLayerOptimal) { // Single layer, well behaved encoder. current_input_allocation_.SetBitrate(0, 0, 300000); target_framerate_fps_ = 30; @@ -264,7 +276,7 @@ TEST_F(EncoderBitrateAdjusterTest, SingleLayerOptimal) { ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01); } -TEST_F(EncoderBitrateAdjusterTest, SingleLayerOveruse) { +TEST_P(EncoderBitrateAdjusterTest, SingleLayerOveruse) { // Single layer, well behaved encoder. current_input_allocation_.SetBitrate(0, 0, 300000); target_framerate_fps_ = 30; @@ -278,7 +290,7 @@ TEST_F(EncoderBitrateAdjusterTest, SingleLayerOveruse) { current_adjusted_allocation_, 0.01); } -TEST_F(EncoderBitrateAdjusterTest, SingleLayerUnderuse) { +TEST_P(EncoderBitrateAdjusterTest, SingleLayerUnderuse) { // Single layer, well behaved encoder. current_input_allocation_.SetBitrate(0, 0, 300000); target_framerate_fps_ = 30; @@ -291,7 +303,7 @@ TEST_F(EncoderBitrateAdjusterTest, SingleLayerUnderuse) { ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00); } -TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOptimalSize) { +TEST_P(EncoderBitrateAdjusterTest, ThreeTemporalLayersOptimalSize) { // Three temporal layers, 60%/20%/20% bps distro, well behaved encoder. current_input_allocation_.SetBitrate(0, 0, 180000); current_input_allocation_.SetBitrate(0, 1, 60000); @@ -305,7 +317,7 @@ TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOptimalSize) { ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01); } -TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOvershoot) { +TEST_P(EncoderBitrateAdjusterTest, ThreeTemporalLayersOvershoot) { // Three temporal layers, 60%/20%/20% bps distro. // 10% overshoot on all layers. current_input_allocation_.SetBitrate(0, 0, 180000); @@ -322,7 +334,7 @@ TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOvershoot) { current_adjusted_allocation_, 0.01); } -TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersUndershoot) { +TEST_P(EncoderBitrateAdjusterTest, ThreeTemporalLayersUndershoot) { // Three temporal layers, 60%/20%/20% bps distro, undershoot all layers. current_input_allocation_.SetBitrate(0, 0, 180000); current_input_allocation_.SetBitrate(0, 1, 60000); @@ -337,7 +349,7 @@ TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersUndershoot) { ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.0); } -TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersSkewedOvershoot) { +TEST_P(EncoderBitrateAdjusterTest, ThreeTemporalLayersSkewedOvershoot) { // Three temporal layers, 60%/20%/20% bps distro. // 10% overshoot on base layer, 20% on higher layers. current_input_allocation_.SetBitrate(0, 0, 180000); @@ -355,7 +367,7 @@ TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersSkewedOvershoot) { current_adjusted_allocation_, 0.01); } -TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersNonLayeredEncoder) { +TEST_P(EncoderBitrateAdjusterTest, ThreeTemporalLayersNonLayeredEncoder) { // Three temporal layers, 60%/20%/20% bps allocation, 10% overshoot, // encoder does not actually support temporal layers. current_input_allocation_.SetBitrate(0, 0, 180000); @@ -376,7 +388,7 @@ TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersNonLayeredEncoder) { ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01); } -TEST_F(EncoderBitrateAdjusterTest, IgnoredStream) { +TEST_P(EncoderBitrateAdjusterTest, IgnoredStream) { // Encoder with three temporal layers, but in a mode that does not support // deterministic frame rate. Those are ignored, even if bitrate overshoots. current_input_allocation_.SetBitrate(0, 0, 180000); @@ -395,7 +407,7 @@ TEST_F(EncoderBitrateAdjusterTest, IgnoredStream) { ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00); } -TEST_F(EncoderBitrateAdjusterTest, DifferentSpatialOvershoots) { +TEST_P(EncoderBitrateAdjusterTest, DifferentSpatialOvershoots) { // Two streams, both with three temporal layers. // S0 has 5% overshoot, S1 has 25% overshoot. current_input_allocation_.SetBitrate(0, 0, 180000); @@ -427,13 +439,14 @@ TEST_F(EncoderBitrateAdjusterTest, DifferentSpatialOvershoots) { } } -TEST_F(EncoderBitrateAdjusterTest, HeadroomAllowsOvershootToMediaRate) { +TEST_P(EncoderBitrateAdjusterTest, HeadroomAllowsOvershootToMediaRate) { + if (GetParam() == "WebRTC-VideoRateControl/adjuster_use_headroom:false/") { + // This test does not make sense without headroom adjustment. + GTEST_SKIP(); + } + // Two streams, both with three temporal layers. // Media rate is 1.0, but network rate is higher. - test::ScopedKeyValueConfig field_trial( - scoped_field_trial_, - "WebRTC-VideoRateControl/adjuster_use_headroom:true/"); - const uint32_t kS0Bitrate = 300000; const uint32_t kS1Bitrate = 900000; current_input_allocation_.SetBitrate(0, 0, kS0Bitrate / 3); @@ -470,12 +483,14 @@ TEST_F(EncoderBitrateAdjusterTest, HeadroomAllowsOvershootToMediaRate) { } } -TEST_F(EncoderBitrateAdjusterTest, DontExceedMediaRateEvenWithHeadroom) { +TEST_P(EncoderBitrateAdjusterTest, DontExceedMediaRateEvenWithHeadroom) { + if (GetParam() == "WebRTC-VideoRateControl/adjuster_use_headroom:false/") { + // This test does not make sense without headroom adjustment. + GTEST_SKIP(); + } + // Two streams, both with three temporal layers. // Media rate is 1.1, but network rate is higher. - test::ScopedKeyValueConfig field_trial( - scoped_field_trial_, - "WebRTC-VideoRateControl/adjuster_use_headroom:true/"); const uint32_t kS0Bitrate = 300000; const uint32_t kS1Bitrate = 900000; @@ -489,32 +504,37 @@ TEST_F(EncoderBitrateAdjusterTest, DontExceedMediaRateEvenWithHeadroom) { target_framerate_fps_ = 30; // Run twice, once configured as simulcast and once as VP9 SVC. - for (int i = 0; i < 2; ++i) { - SetUpAdjuster(2, 3, i == 0); - // Network rate has 30% overshoot, media rate has 10% overshoot. - InsertFrames({{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}}, - {{1.3, 1.3, 1.3}, {1.3, 1.3, 1.3}}, - kWindowSizeMs * kSequenceLength); + for (const bool is_svc : {false, true}) { + SetUpAdjuster(/*num_spatial_layers=*/2, + /*num_temporal_layers=*/3, is_svc); - // Push back by 30%. + // First insert frames with no overshoot. + InsertFrames({{1.0, 1.0, 1.0}}, kWindowSizeMs * kSequenceLength); + // Verify encoder is not pushed backed. current_adjusted_allocation_ = adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters( current_input_allocation_, target_framerate_fps_)); // The up-down causes a bit more noise, allow slightly more error margin. - ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.3), + ExpectNear(MultiplyAllocation(current_input_allocation_, 1.0), current_adjusted_allocation_, 0.015); + // Change network rate to 30% overshoot, media rate has 10% overshoot. + InsertFrames({{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}}, + {{1.3, 1.3, 1.3}, {1.3, 1.3, 1.3}}, + kWindowSizeMs * kSequenceLength); + // Add 100% link headroom, overshoot from network to media rate is allowed. current_adjusted_allocation_ = adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters( current_input_allocation_, target_framerate_fps_, DataRate::BitsPerSec(current_input_allocation_.get_sum_bps() * 2))); + ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1), - current_adjusted_allocation_, 0.015); + current_adjusted_allocation_, 0.02); } } -TEST_F(EncoderBitrateAdjusterTest, HonorsMinBitrateWithAv1) { +TEST_P(EncoderBitrateAdjusterTest, HonorsMinBitrateWithAv1) { // Single layer, well behaved encoder. const DataRate kHighBitrate = DataRate::KilobitsPerSec(20); const DataRate kALowerMinBitrate = DataRate::KilobitsPerSec(15); @@ -549,5 +569,13 @@ TEST_F(EncoderBitrateAdjusterTest, HonorsMinBitrateWithAv1) { ExpectNear(expected_input_allocation, current_adjusted_allocation_, 0.01); } +INSTANTIATE_TEST_SUITE_P( + AdjustWithHeadroomVariations, + EncoderBitrateAdjusterTest, + Values("WebRTC-VideoRateControl/adjuster_use_headroom:false/", + "WebRTC-VideoRateControl/adjuster_use_headroom:true/", + "WebRTC-VideoRateControl/adjuster_use_headroom:true/" + "WebRTC-BitrateAdjusterUseNewfangledHeadroomAdjustment/Enabled/")); + } // namespace test } // namespace webrtc diff --git a/video/video_stream_encoder.cc b/video/video_stream_encoder.cc index 3f958de241..1e7672cb2d 100644 --- a/video/video_stream_encoder.cc +++ b/video/video_stream_encoder.cc @@ -1345,8 +1345,8 @@ void VideoStreamEncoder::ReconfigureEncoder() { const VideoEncoder::EncoderInfo info = encoder_->GetEncoderInfo(); if (rate_control_settings_.UseEncoderBitrateAdjuster()) { - bitrate_adjuster_ = - std::make_unique(codec, env_.field_trials()); + bitrate_adjuster_ = std::make_unique( + codec, env_.field_trials(), env_.clock()); bitrate_adjuster_->OnEncoderInfo(info); } diff --git a/video/video_stream_encoder_unittest.cc b/video/video_stream_encoder_unittest.cc index f41a51e0d0..6549bd5de9 100644 --- a/video/video_stream_encoder_unittest.cc +++ b/video/video_stream_encoder_unittest.cc @@ -2611,8 +2611,7 @@ TEST_F(VideoStreamEncoderTest, CorrectlyAdjustsAv1Bitrate) { allowed_error_bps); // Insert frames until bitrate adjuster is saturated. - const TimeDelta runtime = - TimeDelta::Millis(EncoderBitrateAdjuster::kWindowSizeMs); + const TimeDelta runtime = EncoderBitrateAdjuster::kWindowSize; const Timestamp start_time = clock()->CurrentTime(); while (clock()->CurrentTime() - start_time < runtime) { video_source_.IncomingCapturedFrame(