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