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     constexpr size_t kMaxFrameSize = 100000;
104     uint8_t buffer[kMaxFrameSize];
105 
106     const int64_t start_us = rtc::TimeMicros();
107     while (rtc::TimeMicros() <
108            start_us + (duration_ms * rtc::kNumMicrosecsPerMillisec)) {
109       clock_.AdvanceTime(TimeDelta::Seconds(1) / target_framerate_fps_);
110       for (size_t si = 0; si < NumSpatialLayers(); ++si) {
111         const std::vector<int>& tl_pattern =
112             kTlPatterns[NumTemporalLayers(si) - 1];
113         const size_t ti =
114             tl_pattern[(tl_pattern_idx_[si]++) % tl_pattern.size()];
115 
116         uint32_t layer_bitrate_bps =
117             current_adjusted_allocation_.GetBitrate(si, ti);
118         double layer_framerate_fps = target_framerate_fps_;
119         if (encoder_info_.fps_allocation[si].size() > ti) {
120           uint8_t layer_fps_fraction = encoder_info_.fps_allocation[si][ti];
121           if (ti > 0) {
122             // We're interested in the frame rate for this layer only, not
123             // cumulative frame rate.
124             layer_fps_fraction -= encoder_info_.fps_allocation[si][ti - 1];
125           }
126           layer_framerate_fps =
127               (target_framerate_fps_ * layer_fps_fraction) /
128               VideoEncoder::EncoderInfo::kMaxFramerateFraction;
129         }
130         double media_utilization_factor = 1.0;
131         double network_utilization_factor = 1.0;
132         if (media_utilization_factors.size() > si) {
133           RTC_DCHECK_EQ(media_utilization_factors[si].size(),
134                         network_utilization_factors[si].size());
135           if (media_utilization_factors[si].size() > ti) {
136             media_utilization_factor = media_utilization_factors[si][ti];
137             network_utilization_factor = network_utilization_factors[si][ti];
138           }
139         }
140         RTC_DCHECK_GE(network_utilization_factor, media_utilization_factor);
141 
142         // Frame size based on constant (media) overshoot.
143         const size_t media_frame_size = media_utilization_factor *
144                                         (layer_bitrate_bps / 8.0) /
145                                         layer_framerate_fps;
146 
147         constexpr int kFramesWithPenalty = (kSequenceLength / 2) - 1;
148         RTC_DCHECK_GT(kFramesWithPenalty, 0);
149 
150         // The positive/negative size diff needed to achieve network rate but
151         // not media rate penalty is the difference between the utilization
152         // factors times the media rate frame size, then scaled by the fraction
153         // between total frames and penalized frames in the sequence.
154         // Cap to media frame size to avoid negative size undershoot.
155         const size_t network_frame_size_diff_bytes = std::min(
156             media_frame_size,
157             static_cast<size_t>(
158                 (((network_utilization_factor - media_utilization_factor) *
159                   media_frame_size) *
160                  kSequenceLength) /
161                     kFramesWithPenalty +
162                 0.5));
163 
164         int sequence_idx = sequence_idx_[si][ti];
165         sequence_idx_[si][ti] = (sequence_idx_[si][ti] + 1) % kSequenceLength;
166         const size_t frame_size_bytes =
167             (sequence_idx < kSequenceLength / 2)
168                 ? media_frame_size - network_frame_size_diff_bytes
169                 : media_frame_size + network_frame_size_diff_bytes;
170 
171         EncodedImage image(buffer, 0, kMaxFrameSize);
172         image.set_size(frame_size_bytes);
173         image.SetSpatialIndex(si);
174         adjuster_->OnEncodedFrame(image, ti);
175         sequence_idx = ++sequence_idx % kSequenceLength;
176       }
177     }
178   }
179 
NumSpatialLayers() const180   size_t NumSpatialLayers() const {
181     if (codec_.codecType == VideoCodecType::kVideoCodecVP9) {
182       return codec_.VP9().numberOfSpatialLayers;
183     }
184     return codec_.numberOfSimulcastStreams;
185   }
186 
NumTemporalLayers(int spatial_index)187   size_t NumTemporalLayers(int spatial_index) {
188     if (codec_.codecType == VideoCodecType::kVideoCodecVP9) {
189       return codec_.spatialLayers[spatial_index].numberOfTemporalLayers;
190     }
191     return codec_.simulcastStream[spatial_index].numberOfTemporalLayers;
192   }
193 
ExpectNear(const VideoBitrateAllocation & expected_allocation,const VideoBitrateAllocation & actual_allocation,double allowed_error_fraction)194   void ExpectNear(const VideoBitrateAllocation& expected_allocation,
195                   const VideoBitrateAllocation& actual_allocation,
196                   double allowed_error_fraction) {
197     for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
198       for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
199         if (expected_allocation.HasBitrate(si, ti)) {
200           EXPECT_TRUE(actual_allocation.HasBitrate(si, ti));
201           uint32_t expected_layer_bitrate_bps =
202               expected_allocation.GetBitrate(si, ti);
203           EXPECT_NEAR(expected_layer_bitrate_bps,
204                       actual_allocation.GetBitrate(si, ti),
205                       static_cast<uint32_t>(expected_layer_bitrate_bps *
206                                             allowed_error_fraction));
207         } else {
208           EXPECT_FALSE(actual_allocation.HasBitrate(si, ti));
209         }
210       }
211     }
212   }
213 
MultiplyAllocation(const VideoBitrateAllocation & allocation,double factor)214   VideoBitrateAllocation MultiplyAllocation(
215       const VideoBitrateAllocation& allocation,
216       double factor) {
217     VideoBitrateAllocation multiplied_allocation;
218     for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
219       for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
220         if (allocation.HasBitrate(si, ti)) {
221           multiplied_allocation.SetBitrate(
222               si, ti,
223               static_cast<uint32_t>(factor * allocation.GetBitrate(si, ti) +
224                                     0.5));
225         }
226       }
227     }
228     return multiplied_allocation;
229   }
230 
231   VideoCodec codec_;
232   VideoEncoder::EncoderInfo encoder_info_;
233   std::unique_ptr<EncoderBitrateAdjuster> adjuster_;
234   VideoBitrateAllocation current_input_allocation_;
235   VideoBitrateAllocation current_adjusted_allocation_;
236   rtc::ScopedFakeClock clock_;
237   DataRate target_bitrate_;
238   double target_framerate_fps_;
239   int tl_pattern_idx_[kMaxSpatialLayers];
240   int sequence_idx_[kMaxSpatialLayers][kMaxTemporalStreams];
241 
242   const std::vector<int> kTlPatterns[kMaxTemporalStreams] = {
243       {0},
244       {0, 1},
245       {0, 2, 1, 2},
246       {0, 3, 2, 3, 1, 3, 2, 3}};
247 };
248 
TEST_F(EncoderBitrateAdjusterTest,SingleLayerOptimal)249 TEST_F(EncoderBitrateAdjusterTest, SingleLayerOptimal) {
250   // Single layer, well behaved encoder.
251   current_input_allocation_.SetBitrate(0, 0, 300000);
252   target_framerate_fps_ = 30;
253   SetUpAdjuster(1, 1, false);
254   InsertFrames({{1.0}}, kWindowSizeMs);
255   current_adjusted_allocation_ =
256       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
257           current_input_allocation_, target_framerate_fps_));
258   // Adjusted allocation near input. Allow 1% error margin due to rounding
259   // errors etc.
260   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
261 }
262 
TEST_F(EncoderBitrateAdjusterTest,SingleLayerOveruse)263 TEST_F(EncoderBitrateAdjusterTest, SingleLayerOveruse) {
264   // Single layer, well behaved encoder.
265   current_input_allocation_.SetBitrate(0, 0, 300000);
266   target_framerate_fps_ = 30;
267   SetUpAdjuster(1, 1, false);
268   InsertFrames({{1.2}}, kWindowSizeMs);
269   current_adjusted_allocation_ =
270       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
271           current_input_allocation_, target_framerate_fps_));
272   // Adjusted allocation lowered by 20%.
273   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.2),
274              current_adjusted_allocation_, 0.01);
275 }
276 
TEST_F(EncoderBitrateAdjusterTest,SingleLayerUnderuse)277 TEST_F(EncoderBitrateAdjusterTest, SingleLayerUnderuse) {
278   // Single layer, well behaved encoder.
279   current_input_allocation_.SetBitrate(0, 0, 300000);
280   target_framerate_fps_ = 30;
281   SetUpAdjuster(1, 1, false);
282   InsertFrames({{0.5}}, kWindowSizeMs);
283   current_adjusted_allocation_ =
284       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
285           current_input_allocation_, target_framerate_fps_));
286   // Undershoot, adjusted should exactly match input.
287   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00);
288 }
289 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersOptimalSize)290 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOptimalSize) {
291   // Three temporal layers, 60%/20%/20% bps distro, well behaved encoder.
292   current_input_allocation_.SetBitrate(0, 0, 180000);
293   current_input_allocation_.SetBitrate(0, 1, 60000);
294   current_input_allocation_.SetBitrate(0, 2, 60000);
295   target_framerate_fps_ = 30;
296   SetUpAdjuster(1, 3, false);
297   InsertFrames({{1.0, 1.0, 1.0}}, kWindowSizeMs);
298   current_adjusted_allocation_ =
299       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
300           current_input_allocation_, target_framerate_fps_));
301   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
302 }
303 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersOvershoot)304 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOvershoot) {
305   // Three temporal layers, 60%/20%/20% bps distro.
306   // 10% overshoot on all layers.
307   current_input_allocation_.SetBitrate(0, 0, 180000);
308   current_input_allocation_.SetBitrate(0, 1, 60000);
309   current_input_allocation_.SetBitrate(0, 2, 60000);
310   target_framerate_fps_ = 30;
311   SetUpAdjuster(1, 3, false);
312   InsertFrames({{1.1, 1.1, 1.1}}, kWindowSizeMs);
313   current_adjusted_allocation_ =
314       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
315           current_input_allocation_, target_framerate_fps_));
316   // Adjusted allocation lowered by 10%.
317   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
318              current_adjusted_allocation_, 0.01);
319 }
320 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersUndershoot)321 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersUndershoot) {
322   // Three temporal layers, 60%/20%/20% bps distro, undershoot all layers.
323   current_input_allocation_.SetBitrate(0, 0, 180000);
324   current_input_allocation_.SetBitrate(0, 1, 60000);
325   current_input_allocation_.SetBitrate(0, 2, 60000);
326   target_framerate_fps_ = 30;
327   SetUpAdjuster(1, 3, false);
328   InsertFrames({{0.8, 0.8, 0.8}}, kWindowSizeMs);
329   current_adjusted_allocation_ =
330       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
331           current_input_allocation_, target_framerate_fps_));
332   // Adjusted allocation identical since we don't boost bitrates.
333   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.0);
334 }
335 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersSkewedOvershoot)336 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersSkewedOvershoot) {
337   // Three temporal layers, 60%/20%/20% bps distro.
338   // 10% overshoot on base layer, 20% on higher layers.
339   current_input_allocation_.SetBitrate(0, 0, 180000);
340   current_input_allocation_.SetBitrate(0, 1, 60000);
341   current_input_allocation_.SetBitrate(0, 2, 60000);
342   target_framerate_fps_ = 30;
343   SetUpAdjuster(1, 3, false);
344   InsertFrames({{1.1, 1.2, 1.2}}, kWindowSizeMs);
345   current_adjusted_allocation_ =
346       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
347           current_input_allocation_, target_framerate_fps_));
348   // Expected overshoot is weighted by bitrate:
349   // (0.6 * 1.1 + 0.2 * 1.2 + 0.2 * 1.2) = 1.14
350   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.14),
351              current_adjusted_allocation_, 0.01);
352 }
353 
TEST_F(EncoderBitrateAdjusterTest,FourTemporalLayersSkewedOvershoot)354 TEST_F(EncoderBitrateAdjusterTest, FourTemporalLayersSkewedOvershoot) {
355   // Three temporal layers, 40%/30%/15%/15% bps distro.
356   // 10% overshoot on base layer, 20% on higher layers.
357   current_input_allocation_.SetBitrate(0, 0, 120000);
358   current_input_allocation_.SetBitrate(0, 1, 90000);
359   current_input_allocation_.SetBitrate(0, 2, 45000);
360   current_input_allocation_.SetBitrate(0, 3, 45000);
361   target_framerate_fps_ = 30;
362   SetUpAdjuster(1, 4, false);
363   InsertFrames({{1.1, 1.2, 1.2, 1.2}}, kWindowSizeMs);
364   current_adjusted_allocation_ =
365       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
366           current_input_allocation_, target_framerate_fps_));
367   // Expected overshoot is weighted by bitrate:
368   // (0.4 * 1.1 + 0.3 * 1.2 + 0.15 * 1.2 + 0.15 * 1.2) = 1.16
369   ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.16),
370              current_adjusted_allocation_, 0.01);
371 }
372 
TEST_F(EncoderBitrateAdjusterTest,ThreeTemporalLayersNonLayeredEncoder)373 TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersNonLayeredEncoder) {
374   // Three temporal layers, 60%/20%/20% bps allocation, 10% overshoot,
375   // encoder does not actually support temporal layers.
376   current_input_allocation_.SetBitrate(0, 0, 180000);
377   current_input_allocation_.SetBitrate(0, 1, 60000);
378   current_input_allocation_.SetBitrate(0, 2, 60000);
379   target_framerate_fps_ = 30;
380   SetUpAdjuster(1, 1, false);
381   InsertFrames({{1.1}}, kWindowSizeMs);
382   current_adjusted_allocation_ =
383       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
384           current_input_allocation_, target_framerate_fps_));
385   // Expect the actual 10% overuse to be detected and the allocation to
386   // only contain the one entry.
387   VideoBitrateAllocation expected_allocation;
388   expected_allocation.SetBitrate(
389       0, 0,
390       static_cast<uint32_t>(current_input_allocation_.get_sum_bps() / 1.10));
391   ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01);
392 }
393 
TEST_F(EncoderBitrateAdjusterTest,IgnoredStream)394 TEST_F(EncoderBitrateAdjusterTest, IgnoredStream) {
395   // Encoder with three temporal layers, but in a mode that does not support
396   // deterministic frame rate. Those are ignored, even if bitrate overshoots.
397   current_input_allocation_.SetBitrate(0, 0, 180000);
398   current_input_allocation_.SetBitrate(0, 1, 60000);
399   target_framerate_fps_ = 30;
400   SetUpAdjuster(1, 1, false);
401   encoder_info_.fps_allocation[0].clear();
402   adjuster_->OnEncoderInfo(encoder_info_);
403 
404   InsertFrames({{1.1}}, kWindowSizeMs);
405   current_adjusted_allocation_ =
406       adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
407           current_input_allocation_, target_framerate_fps_));
408 
409   // Values passed through.
410   ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00);
411 }
412 
TEST_F(EncoderBitrateAdjusterTest,DifferentSpatialOvershoots)413 TEST_F(EncoderBitrateAdjusterTest, DifferentSpatialOvershoots) {
414   // Two streams, both with three temporal layers.
415   // S0 has 5% overshoot, S1 has 25% overshoot.
416   current_input_allocation_.SetBitrate(0, 0, 180000);
417   current_input_allocation_.SetBitrate(0, 1, 60000);
418   current_input_allocation_.SetBitrate(0, 2, 60000);
419   current_input_allocation_.SetBitrate(1, 0, 400000);
420   current_input_allocation_.SetBitrate(1, 1, 150000);
421   current_input_allocation_.SetBitrate(1, 2, 150000);
422   target_framerate_fps_ = 30;
423   // Run twice, once configured as simulcast and once as VP9 SVC.
424   for (int i = 0; i < 2; ++i) {
425     SetUpAdjuster(2, 3, i == 0);
426     InsertFrames({{1.05, 1.05, 1.05}, {1.25, 1.25, 1.25}}, kWindowSizeMs);
427     current_adjusted_allocation_ =
428         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
429             current_input_allocation_, target_framerate_fps_));
430     VideoBitrateAllocation expected_allocation;
431     for (size_t ti = 0; ti < 3; ++ti) {
432       expected_allocation.SetBitrate(
433           0, ti,
434           static_cast<uint32_t>(current_input_allocation_.GetBitrate(0, ti) /
435                                 1.05));
436       expected_allocation.SetBitrate(
437           1, ti,
438           static_cast<uint32_t>(current_input_allocation_.GetBitrate(1, ti) /
439                                 1.25));
440     }
441     ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01);
442   }
443 }
444 
TEST_F(EncoderBitrateAdjusterTest,HeadroomAllowsOvershootToMediaRate)445 TEST_F(EncoderBitrateAdjusterTest, HeadroomAllowsOvershootToMediaRate) {
446   // Two streams, both with three temporal layers.
447   // Media rate is 1.0, but network rate is higher.
448   ScopedFieldTrials field_trial(
449       "WebRTC-VideoRateControl/adjuster_use_headroom:true/");
450 
451   const uint32_t kS0Bitrate = 300000;
452   const uint32_t kS1Bitrate = 900000;
453   current_input_allocation_.SetBitrate(0, 0, kS0Bitrate / 3);
454   current_input_allocation_.SetBitrate(0, 1, kS0Bitrate / 3);
455   current_input_allocation_.SetBitrate(0, 2, kS0Bitrate / 3);
456   current_input_allocation_.SetBitrate(1, 0, kS1Bitrate / 3);
457   current_input_allocation_.SetBitrate(1, 1, kS1Bitrate / 3);
458   current_input_allocation_.SetBitrate(1, 2, kS1Bitrate / 3);
459 
460   target_framerate_fps_ = 30;
461 
462   // Run twice, once configured as simulcast and once as VP9 SVC.
463   for (int i = 0; i < 2; ++i) {
464     SetUpAdjuster(2, 3, i == 0);
465     // Network rate has 10% overshoot, but media rate is correct at 1.0.
466     InsertFrames({{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}},
467                  {{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}},
468                  kWindowSizeMs * kSequenceLength);
469 
470     // Push back by 10%.
471     current_adjusted_allocation_ =
472         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
473             current_input_allocation_, target_framerate_fps_));
474     ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
475                current_adjusted_allocation_, 0.01);
476 
477     // Add 10% link headroom, overshoot is now allowed.
478     current_adjusted_allocation_ =
479         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
480             current_input_allocation_, target_framerate_fps_,
481             DataRate::BitsPerSec(current_input_allocation_.get_sum_bps() *
482                                  1.1)));
483     ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
484   }
485 }
486 
TEST_F(EncoderBitrateAdjusterTest,DontExceedMediaRateEvenWithHeadroom)487 TEST_F(EncoderBitrateAdjusterTest, DontExceedMediaRateEvenWithHeadroom) {
488   // Two streams, both with three temporal layers.
489   // Media rate is 1.1, but network rate is higher.
490   ScopedFieldTrials field_trial(
491       "WebRTC-VideoRateControl/adjuster_use_headroom:true/");
492 
493   const uint32_t kS0Bitrate = 300000;
494   const uint32_t kS1Bitrate = 900000;
495   current_input_allocation_.SetBitrate(0, 0, kS0Bitrate / 3);
496   current_input_allocation_.SetBitrate(0, 1, kS0Bitrate / 3);
497   current_input_allocation_.SetBitrate(0, 2, kS0Bitrate / 3);
498   current_input_allocation_.SetBitrate(1, 0, kS1Bitrate / 3);
499   current_input_allocation_.SetBitrate(1, 1, kS1Bitrate / 3);
500   current_input_allocation_.SetBitrate(1, 2, kS1Bitrate / 3);
501 
502   target_framerate_fps_ = 30;
503 
504   // Run twice, once configured as simulcast and once as VP9 SVC.
505   for (int i = 0; i < 2; ++i) {
506     SetUpAdjuster(2, 3, i == 0);
507     // Network rate has 30% overshoot, media rate has 10% overshoot.
508     InsertFrames({{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}},
509                  {{1.3, 1.3, 1.3}, {1.3, 1.3, 1.3}},
510                  kWindowSizeMs * kSequenceLength);
511 
512     // Push back by 30%.
513     current_adjusted_allocation_ =
514         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
515             current_input_allocation_, target_framerate_fps_));
516     // The up-down causes a bit more noise, allow slightly more error margin.
517     ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.3),
518                current_adjusted_allocation_, 0.015);
519 
520     // Add 100% link headroom, overshoot from network to media rate is allowed.
521     current_adjusted_allocation_ =
522         adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
523             current_input_allocation_, target_framerate_fps_,
524             DataRate::BitsPerSec(current_input_allocation_.get_sum_bps() * 2)));
525     ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
526                current_adjusted_allocation_, 0.015);
527   }
528 }
529 
530 }  // namespace test
531 }  // namespace webrtc
532