xref: /aosp_15_r20/external/webrtc/video/encoder_bitrate_adjuster_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "video/encoder_bitrate_adjuster.h"
12 
13 #include <memory>
14 #include <vector>
15 
16 #include "api/units/data_rate.h"
17 #include "rtc_base/fake_clock.h"
18 #include "rtc_base/numerics/safe_conversions.h"
19 #include "test/field_trial.h"
20 #include "test/gtest.h"
21 
22 namespace webrtc {
23 namespace test {
24 
25 class EncoderBitrateAdjusterTest : public ::testing::Test {
26  public:
27   static constexpr int64_t kWindowSizeMs = 3000;
28   static constexpr int kDefaultBitrateBps = 300000;
29   static constexpr int kDefaultFrameRateFps = 30;
30   // For network utilization higher than media utilization, loop over a
31   // sequence where the first half undershoots and the second half overshoots
32   // by the same amount.
33   static constexpr int kSequenceLength = 4;
34   static_assert(kSequenceLength % 2 == 0, "Sequence length must be even.");
35 
EncoderBitrateAdjusterTest()36   EncoderBitrateAdjusterTest()
37       : target_bitrate_(DataRate::BitsPerSec(kDefaultBitrateBps)),
38         target_framerate_fps_(kDefaultFrameRateFps),
39         tl_pattern_idx_{},
40         sequence_idx_{} {}
41 
42  protected:
SetUpAdjuster(size_t num_spatial_layers,size_t num_temporal_layers,bool vp9_svc)43   void SetUpAdjuster(size_t num_spatial_layers,
44                      size_t num_temporal_layers,
45                      bool vp9_svc) {
46     // Initialize some default VideoCodec instance with the given number of
47     // layers.
48     if (vp9_svc) {
49       codec_.codecType = VideoCodecType::kVideoCodecVP9;
50       codec_.numberOfSimulcastStreams = 1;
51       codec_.VP9()->numberOfSpatialLayers = num_spatial_layers;
52       codec_.VP9()->numberOfTemporalLayers = num_temporal_layers;
53       for (size_t si = 0; si < num_spatial_layers; ++si) {
54         codec_.spatialLayers[si].minBitrate = 100 * (1 << si);
55         codec_.spatialLayers[si].targetBitrate = 200 * (1 << si);
56         codec_.spatialLayers[si].maxBitrate = 300 * (1 << si);
57         codec_.spatialLayers[si].active = true;
58         codec_.spatialLayers[si].numberOfTemporalLayers = num_temporal_layers;
59       }
60     } else {
61       codec_.codecType = VideoCodecType::kVideoCodecVP8;
62       codec_.numberOfSimulcastStreams = num_spatial_layers;
63       codec_.VP8()->numberOfTemporalLayers = num_temporal_layers;
64       for (size_t si = 0; si < num_spatial_layers; ++si) {
65         codec_.simulcastStream[si].minBitrate = 100 * (1 << si);
66         codec_.simulcastStream[si].targetBitrate = 200 * (1 << si);
67         codec_.simulcastStream[si].maxBitrate = 300 * (1 << si);
68         codec_.simulcastStream[si].active = true;
69         codec_.simulcastStream[si].numberOfTemporalLayers = num_temporal_layers;
70       }
71     }
72 
73     for (size_t si = 0; si < num_spatial_layers; ++si) {
74       encoder_info_.fps_allocation[si].resize(num_temporal_layers);
75       double fraction = 1.0;
76       for (int ti = num_temporal_layers - 1; ti >= 0; --ti) {
77         encoder_info_.fps_allocation[si][ti] = static_cast<uint8_t>(
78             VideoEncoder::EncoderInfo::kMaxFramerateFraction * fraction + 0.5);
79         fraction /= 2.0;
80       }
81     }
82 
83     adjuster_ = std::make_unique<EncoderBitrateAdjuster>(codec_);
84     adjuster_->OnEncoderInfo(encoder_info_);
85     current_adjusted_allocation_ =
86         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
87             current_input_allocation_, target_framerate_fps_));
88   }
89 
InsertFrames(std::vector<std::vector<double>> media_utilization_factors,int64_t duration_ms)90   void InsertFrames(std::vector<std::vector<double>> media_utilization_factors,
91                     int64_t duration_ms) {
92     InsertFrames(media_utilization_factors, media_utilization_factors,
93                  duration_ms);
94   }
95 
InsertFrames(std::vector<std::vector<double>> media_utilization_factors,std::vector<std::vector<double>> network_utilization_factors,int64_t duration_ms)96   void InsertFrames(
97       std::vector<std::vector<double>> media_utilization_factors,
98       std::vector<std::vector<double>> network_utilization_factors,
99       int64_t duration_ms) {
100     RTC_DCHECK_EQ(media_utilization_factors.size(),
101                   network_utilization_factors.size());
102 
103     const int64_t start_us = rtc::TimeMicros();
104     while (rtc::TimeMicros() <
105            start_us + (duration_ms * rtc::kNumMicrosecsPerMillisec)) {
106       clock_.AdvanceTime(TimeDelta::Seconds(1) / target_framerate_fps_);
107       for (size_t si = 0; si < NumSpatialLayers(); ++si) {
108         const std::vector<int>& tl_pattern =
109             kTlPatterns[NumTemporalLayers(si) - 1];
110         const size_t ti =
111             tl_pattern[(tl_pattern_idx_[si]++) % tl_pattern.size()];
112 
113         uint32_t layer_bitrate_bps =
114             current_adjusted_allocation_.GetBitrate(si, ti);
115         double layer_framerate_fps = target_framerate_fps_;
116         if (encoder_info_.fps_allocation[si].size() > ti) {
117           uint8_t layer_fps_fraction = encoder_info_.fps_allocation[si][ti];
118           if (ti > 0) {
119             // We're interested in the frame rate for this layer only, not
120             // cumulative frame rate.
121             layer_fps_fraction -= encoder_info_.fps_allocation[si][ti - 1];
122           }
123           layer_framerate_fps =
124               (target_framerate_fps_ * layer_fps_fraction) /
125               VideoEncoder::EncoderInfo::kMaxFramerateFraction;
126         }
127         double media_utilization_factor = 1.0;
128         double network_utilization_factor = 1.0;
129         if (media_utilization_factors.size() > si) {
130           RTC_DCHECK_EQ(media_utilization_factors[si].size(),
131                         network_utilization_factors[si].size());
132           if (media_utilization_factors[si].size() > ti) {
133             media_utilization_factor = media_utilization_factors[si][ti];
134             network_utilization_factor = network_utilization_factors[si][ti];
135           }
136         }
137         RTC_DCHECK_GE(network_utilization_factor, media_utilization_factor);
138 
139         // Frame size based on constant (media) overshoot.
140         const size_t media_frame_size = media_utilization_factor *
141                                         (layer_bitrate_bps / 8.0) /
142                                         layer_framerate_fps;
143 
144         constexpr int kFramesWithPenalty = (kSequenceLength / 2) - 1;
145         RTC_DCHECK_GT(kFramesWithPenalty, 0);
146 
147         // The positive/negative size diff needed to achieve network rate but
148         // not media rate penalty is the difference between the utilization
149         // factors times the media rate frame size, then scaled by the fraction
150         // between total frames and penalized frames in the sequence.
151         // Cap to media frame size to avoid negative size undershoot.
152         const size_t network_frame_size_diff_bytes = std::min(
153             media_frame_size,
154             static_cast<size_t>(
155                 (((network_utilization_factor - media_utilization_factor) *
156                   media_frame_size) *
157                  kSequenceLength) /
158                     kFramesWithPenalty +
159                 0.5));
160 
161         int sequence_idx = sequence_idx_[si][ti];
162         sequence_idx_[si][ti] = (sequence_idx_[si][ti] + 1) % kSequenceLength;
163         const DataSize frame_size = DataSize::Bytes(
164             (sequence_idx < kSequenceLength / 2)
165                 ? media_frame_size - network_frame_size_diff_bytes
166                 : media_frame_size + network_frame_size_diff_bytes);
167 
168         adjuster_->OnEncodedFrame(frame_size, si, ti);
169         sequence_idx = ++sequence_idx % kSequenceLength;
170       }
171     }
172   }
173 
NumSpatialLayers() const174   size_t NumSpatialLayers() const {
175     if (codec_.codecType == VideoCodecType::kVideoCodecVP9) {
176       return codec_.VP9().numberOfSpatialLayers;
177     }
178     return codec_.numberOfSimulcastStreams;
179   }
180 
NumTemporalLayers(int spatial_index)181   size_t NumTemporalLayers(int spatial_index) {
182     if (codec_.codecType == VideoCodecType::kVideoCodecVP9) {
183       return codec_.spatialLayers[spatial_index].numberOfTemporalLayers;
184     }
185     return codec_.simulcastStream[spatial_index].numberOfTemporalLayers;
186   }
187 
ExpectNear(const VideoBitrateAllocation & expected_allocation,const VideoBitrateAllocation & actual_allocation,double allowed_error_fraction)188   void ExpectNear(const VideoBitrateAllocation& expected_allocation,
189                   const VideoBitrateAllocation& actual_allocation,
190                   double allowed_error_fraction) {
191     for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
192       for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
193         if (expected_allocation.HasBitrate(si, ti)) {
194           EXPECT_TRUE(actual_allocation.HasBitrate(si, ti));
195           uint32_t expected_layer_bitrate_bps =
196               expected_allocation.GetBitrate(si, ti);
197           EXPECT_NEAR(expected_layer_bitrate_bps,
198                       actual_allocation.GetBitrate(si, ti),
199                       static_cast<uint32_t>(expected_layer_bitrate_bps *
200                                             allowed_error_fraction));
201         } else {
202           EXPECT_FALSE(actual_allocation.HasBitrate(si, ti));
203         }
204       }
205     }
206   }
207 
MultiplyAllocation(const VideoBitrateAllocation & allocation,double factor)208   VideoBitrateAllocation MultiplyAllocation(
209       const VideoBitrateAllocation& allocation,
210       double factor) {
211     VideoBitrateAllocation multiplied_allocation;
212     for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
213       for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
214         if (allocation.HasBitrate(si, ti)) {
215           multiplied_allocation.SetBitrate(
216               si, ti,
217               static_cast<uint32_t>(factor * allocation.GetBitrate(si, ti) +
218                                     0.5));
219         }
220       }
221     }
222     return multiplied_allocation;
223   }
224 
225   VideoCodec codec_;
226   VideoEncoder::EncoderInfo encoder_info_;
227   std::unique_ptr<EncoderBitrateAdjuster> adjuster_;
228   VideoBitrateAllocation current_input_allocation_;
229   VideoBitrateAllocation current_adjusted_allocation_;
230   rtc::ScopedFakeClock clock_;
231   DataRate target_bitrate_;
232   double target_framerate_fps_;
233   int tl_pattern_idx_[kMaxSpatialLayers];
234   int sequence_idx_[kMaxSpatialLayers][kMaxTemporalStreams];
235 
236   const std::vector<int> kTlPatterns[kMaxTemporalStreams] = {
237       {0},
238       {0, 1},
239       {0, 2, 1, 2},
240       {0, 3, 2, 3, 1, 3, 2, 3}};
241 };
242 
TEST_F(EncoderBitrateAdjusterTest,SingleLayerOptimal)243 TEST_F(EncoderBitrateAdjusterTest, SingleLayerOptimal) {
244   // Single layer, well behaved encoder.
245   current_input_allocation_.SetBitrate(0, 0, 300000);
246   target_framerate_fps_ = 30;
247   SetUpAdjuster(1, 1, false);
248   InsertFrames({{1.0}}, kWindowSizeMs);
249   current_adjusted_allocation_ =
250       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
251           current_input_allocation_, target_framerate_fps_));
252   // Adjusted allocation near input. Allow 1% error margin due to rounding
253   // errors etc.
254   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
255 }
256 
TEST_F(EncoderBitrateAdjusterTest,SingleLayerOveruse)257 TEST_F(EncoderBitrateAdjusterTest, SingleLayerOveruse) {
258   // Single layer, well behaved encoder.
259   current_input_allocation_.SetBitrate(0, 0, 300000);
260   target_framerate_fps_ = 30;
261   SetUpAdjuster(1, 1, false);
262   InsertFrames({{1.2}}, kWindowSizeMs);
263   current_adjusted_allocation_ =
264       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
265           current_input_allocation_, target_framerate_fps_));
266   // Adjusted allocation lowered by 20%.
267   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.2),
268              current_adjusted_allocation_, 0.01);
269 }
270 
TEST_F(EncoderBitrateAdjusterTest,SingleLayerUnderuse)271 TEST_F(EncoderBitrateAdjusterTest, SingleLayerUnderuse) {
272   // Single layer, well behaved encoder.
273   current_input_allocation_.SetBitrate(0, 0, 300000);
274   target_framerate_fps_ = 30;
275   SetUpAdjuster(1, 1, false);
276   InsertFrames({{0.5}}, kWindowSizeMs);
277   current_adjusted_allocation_ =
278       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
279           current_input_allocation_, target_framerate_fps_));
280   // Undershoot, adjusted should exactly match input.
281   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00);
282 }
283 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersOptimalSize)284 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOptimalSize) {
285   // Three temporal layers, 60%/20%/20% bps distro, well behaved encoder.
286   current_input_allocation_.SetBitrate(0, 0, 180000);
287   current_input_allocation_.SetBitrate(0, 1, 60000);
288   current_input_allocation_.SetBitrate(0, 2, 60000);
289   target_framerate_fps_ = 30;
290   SetUpAdjuster(1, 3, false);
291   InsertFrames({{1.0, 1.0, 1.0}}, kWindowSizeMs);
292   current_adjusted_allocation_ =
293       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
294           current_input_allocation_, target_framerate_fps_));
295   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
296 }
297 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersOvershoot)298 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOvershoot) {
299   // Three temporal layers, 60%/20%/20% bps distro.
300   // 10% overshoot on all layers.
301   current_input_allocation_.SetBitrate(0, 0, 180000);
302   current_input_allocation_.SetBitrate(0, 1, 60000);
303   current_input_allocation_.SetBitrate(0, 2, 60000);
304   target_framerate_fps_ = 30;
305   SetUpAdjuster(1, 3, false);
306   InsertFrames({{1.1, 1.1, 1.1}}, kWindowSizeMs);
307   current_adjusted_allocation_ =
308       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
309           current_input_allocation_, target_framerate_fps_));
310   // Adjusted allocation lowered by 10%.
311   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
312              current_adjusted_allocation_, 0.01);
313 }
314 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersUndershoot)315 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersUndershoot) {
316   // Three temporal layers, 60%/20%/20% bps distro, undershoot all layers.
317   current_input_allocation_.SetBitrate(0, 0, 180000);
318   current_input_allocation_.SetBitrate(0, 1, 60000);
319   current_input_allocation_.SetBitrate(0, 2, 60000);
320   target_framerate_fps_ = 30;
321   SetUpAdjuster(1, 3, false);
322   InsertFrames({{0.8, 0.8, 0.8}}, kWindowSizeMs);
323   current_adjusted_allocation_ =
324       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
325           current_input_allocation_, target_framerate_fps_));
326   // Adjusted allocation identical since we don't boost bitrates.
327   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.0);
328 }
329 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersSkewedOvershoot)330 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersSkewedOvershoot) {
331   // Three temporal layers, 60%/20%/20% bps distro.
332   // 10% overshoot on base layer, 20% on higher layers.
333   current_input_allocation_.SetBitrate(0, 0, 180000);
334   current_input_allocation_.SetBitrate(0, 1, 60000);
335   current_input_allocation_.SetBitrate(0, 2, 60000);
336   target_framerate_fps_ = 30;
337   SetUpAdjuster(1, 3, false);
338   InsertFrames({{1.1, 1.2, 1.2}}, kWindowSizeMs);
339   current_adjusted_allocation_ =
340       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
341           current_input_allocation_, target_framerate_fps_));
342   // Expected overshoot is weighted by bitrate:
343   // (0.6 * 1.1 + 0.2 * 1.2 + 0.2 * 1.2) = 1.14
344   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.14),
345              current_adjusted_allocation_, 0.01);
346 }
347 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersNonLayeredEncoder)348 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersNonLayeredEncoder) {
349   // Three temporal layers, 60%/20%/20% bps allocation, 10% overshoot,
350   // encoder does not actually support temporal layers.
351   current_input_allocation_.SetBitrate(0, 0, 180000);
352   current_input_allocation_.SetBitrate(0, 1, 60000);
353   current_input_allocation_.SetBitrate(0, 2, 60000);
354   target_framerate_fps_ = 30;
355   SetUpAdjuster(1, 1, false);
356   InsertFrames({{1.1}}, kWindowSizeMs);
357   current_adjusted_allocation_ =
358       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
359           current_input_allocation_, target_framerate_fps_));
360   // Expect the actual 10% overuse to be detected and the allocation to
361   // only contain the one entry.
362   VideoBitrateAllocation expected_allocation;
363   expected_allocation.SetBitrate(
364       0, 0,
365       static_cast<uint32_t>(current_input_allocation_.get_sum_bps() / 1.10));
366   ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01);
367 }
368 
TEST_F(EncoderBitrateAdjusterTest,IgnoredStream)369 TEST_F(EncoderBitrateAdjusterTest, IgnoredStream) {
370   // Encoder with three temporal layers, but in a mode that does not support
371   // deterministic frame rate. Those are ignored, even if bitrate overshoots.
372   current_input_allocation_.SetBitrate(0, 0, 180000);
373   current_input_allocation_.SetBitrate(0, 1, 60000);
374   target_framerate_fps_ = 30;
375   SetUpAdjuster(1, 1, false);
376   encoder_info_.fps_allocation[0].clear();
377   adjuster_->OnEncoderInfo(encoder_info_);
378 
379   InsertFrames({{1.1}}, kWindowSizeMs);
380   current_adjusted_allocation_ =
381       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
382           current_input_allocation_, target_framerate_fps_));
383 
384   // Values passed through.
385   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00);
386 }
387 
TEST_F(EncoderBitrateAdjusterTest,DifferentSpatialOvershoots)388 TEST_F(EncoderBitrateAdjusterTest, DifferentSpatialOvershoots) {
389   // Two streams, both with three temporal layers.
390   // S0 has 5% overshoot, S1 has 25% overshoot.
391   current_input_allocation_.SetBitrate(0, 0, 180000);
392   current_input_allocation_.SetBitrate(0, 1, 60000);
393   current_input_allocation_.SetBitrate(0, 2, 60000);
394   current_input_allocation_.SetBitrate(1, 0, 400000);
395   current_input_allocation_.SetBitrate(1, 1, 150000);
396   current_input_allocation_.SetBitrate(1, 2, 150000);
397   target_framerate_fps_ = 30;
398   // Run twice, once configured as simulcast and once as VP9 SVC.
399   for (int i = 0; i < 2; ++i) {
400     SetUpAdjuster(2, 3, i == 0);
401     InsertFrames({{1.05, 1.05, 1.05}, {1.25, 1.25, 1.25}}, kWindowSizeMs);
402     current_adjusted_allocation_ =
403         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
404             current_input_allocation_, target_framerate_fps_));
405     VideoBitrateAllocation expected_allocation;
406     for (size_t ti = 0; ti < 3; ++ti) {
407       expected_allocation.SetBitrate(
408           0, ti,
409           static_cast<uint32_t>(current_input_allocation_.GetBitrate(0, ti) /
410                                 1.05));
411       expected_allocation.SetBitrate(
412           1, ti,
413           static_cast<uint32_t>(current_input_allocation_.GetBitrate(1, ti) /
414                                 1.25));
415     }
416     ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01);
417   }
418 }
419 
TEST_F(EncoderBitrateAdjusterTest,HeadroomAllowsOvershootToMediaRate)420 TEST_F(EncoderBitrateAdjusterTest, HeadroomAllowsOvershootToMediaRate) {
421   // Two streams, both with three temporal layers.
422   // Media rate is 1.0, but network rate is higher.
423   ScopedFieldTrials field_trial(
424       "WebRTC-VideoRateControl/adjuster_use_headroom:true/");
425 
426   const uint32_t kS0Bitrate = 300000;
427   const uint32_t kS1Bitrate = 900000;
428   current_input_allocation_.SetBitrate(0, 0, kS0Bitrate / 3);
429   current_input_allocation_.SetBitrate(0, 1, kS0Bitrate / 3);
430   current_input_allocation_.SetBitrate(0, 2, kS0Bitrate / 3);
431   current_input_allocation_.SetBitrate(1, 0, kS1Bitrate / 3);
432   current_input_allocation_.SetBitrate(1, 1, kS1Bitrate / 3);
433   current_input_allocation_.SetBitrate(1, 2, kS1Bitrate / 3);
434 
435   target_framerate_fps_ = 30;
436 
437   // Run twice, once configured as simulcast and once as VP9 SVC.
438   for (int i = 0; i < 2; ++i) {
439     SetUpAdjuster(2, 3, i == 0);
440     // Network rate has 10% overshoot, but media rate is correct at 1.0.
441     InsertFrames({{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}},
442                  {{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}},
443                  kWindowSizeMs * kSequenceLength);
444 
445     // Push back by 10%.
446     current_adjusted_allocation_ =
447         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
448             current_input_allocation_, target_framerate_fps_));
449     ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
450                current_adjusted_allocation_, 0.01);
451 
452     // Add 10% link headroom, overshoot is now allowed.
453     current_adjusted_allocation_ =
454         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
455             current_input_allocation_, target_framerate_fps_,
456             DataRate::BitsPerSec(current_input_allocation_.get_sum_bps() *
457                                  1.1)));
458     ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
459   }
460 }
461 
TEST_F(EncoderBitrateAdjusterTest,DontExceedMediaRateEvenWithHeadroom)462 TEST_F(EncoderBitrateAdjusterTest, DontExceedMediaRateEvenWithHeadroom) {
463   // Two streams, both with three temporal layers.
464   // Media rate is 1.1, but network rate is higher.
465   ScopedFieldTrials field_trial(
466       "WebRTC-VideoRateControl/adjuster_use_headroom:true/");
467 
468   const uint32_t kS0Bitrate = 300000;
469   const uint32_t kS1Bitrate = 900000;
470   current_input_allocation_.SetBitrate(0, 0, kS0Bitrate / 3);
471   current_input_allocation_.SetBitrate(0, 1, kS0Bitrate / 3);
472   current_input_allocation_.SetBitrate(0, 2, kS0Bitrate / 3);
473   current_input_allocation_.SetBitrate(1, 0, kS1Bitrate / 3);
474   current_input_allocation_.SetBitrate(1, 1, kS1Bitrate / 3);
475   current_input_allocation_.SetBitrate(1, 2, kS1Bitrate / 3);
476 
477   target_framerate_fps_ = 30;
478 
479   // Run twice, once configured as simulcast and once as VP9 SVC.
480   for (int i = 0; i < 2; ++i) {
481     SetUpAdjuster(2, 3, i == 0);
482     // Network rate has 30% overshoot, media rate has 10% overshoot.
483     InsertFrames({{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}},
484                  {{1.3, 1.3, 1.3}, {1.3, 1.3, 1.3}},
485                  kWindowSizeMs * kSequenceLength);
486 
487     // Push back by 30%.
488     current_adjusted_allocation_ =
489         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
490             current_input_allocation_, target_framerate_fps_));
491     // The up-down causes a bit more noise, allow slightly more error margin.
492     ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.3),
493                current_adjusted_allocation_, 0.015);
494 
495     // Add 100% link headroom, overshoot from network to media rate is allowed.
496     current_adjusted_allocation_ =
497         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
498             current_input_allocation_, target_framerate_fps_,
499             DataRate::BitsPerSec(current_input_allocation_.get_sum_bps() * 2)));
500     ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
501                current_adjusted_allocation_, 0.015);
502   }
503 }
504 
505 }  // namespace test
506 }  // namespace webrtc
507