blob: 27a38c4b8ad205fb95b47906fd549931a11c84c3 [file] [log] [blame]
Erik Språng7ca375c2019-02-06 16:20:17 +01001/*
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 <vector>
14
15#include "absl/memory/memory.h"
16#include "api/units/data_rate.h"
17#include "rtc_base/fake_clock.h"
18#include "rtc_base/numerics/safe_conversions.h"
Erik Språng3d11e2f2019-04-15 14:48:30 +020019#include "test/field_trial.h"
Erik Språng7ca375c2019-02-06 16:20:17 +010020#include "test/gtest.h"
21
22namespace webrtc {
Erik Språng3d11e2f2019-04-15 14:48:30 +020023namespace test {
Erik Språng7ca375c2019-02-06 16:20:17 +010024
25class 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;
Erik Språng3d11e2f2019-04-15 14:48:30 +020030 // 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
Erik Språng7ca375c2019-02-06 16:20:17 +010036 EncoderBitrateAdjusterTest()
37 : target_bitrate_(DataRate::bps(kDefaultBitrateBps)),
38 target_framerate_fps_(kDefaultFrameRateFps),
Erik Språng3d11e2f2019-04-15 14:48:30 +020039 tl_pattern_idx_{},
40 sequence_idx_{} {}
Erik Språng7ca375c2019-02-06 16:20:17 +010041
42 protected:
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_ = absl::make_unique<EncoderBitrateAdjuster>(codec_);
84 adjuster_->OnEncoderInfo(encoder_info_);
Erik Språng3d11e2f2019-04-15 14:48:30 +020085 current_adjusted_allocation_ =
86 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
87 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +010088 }
89
Erik Språng3d11e2f2019-04-15 14:48:30 +020090 void InsertFrames(std::vector<std::vector<double>> media_utilization_factors,
Erik Språng7ca375c2019-02-06 16:20:17 +010091 int64_t duration_ms) {
Erik Språng3d11e2f2019-04-15 14:48:30 +020092 InsertFrames(media_utilization_factors, media_utilization_factors,
93 duration_ms);
94 }
95
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
Erik Språng7ca375c2019-02-06 16:20:17 +0100103 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_.AdvanceTimeMicros(rtc::kNumMicrosecsPerSec /
110 target_framerate_fps_);
111 for (size_t si = 0; si < NumSpatialLayers(); ++si) {
112 const std::vector<int>& tl_pattern =
113 kTlPatterns[NumTemporalLayers(si) - 1];
114 const size_t ti =
115 tl_pattern[(tl_pattern_idx_[si]++) % tl_pattern.size()];
116
117 uint32_t layer_bitrate_bps =
118 current_adjusted_allocation_.GetBitrate(si, ti);
119 double layer_framerate_fps = target_framerate_fps_;
120 if (encoder_info_.fps_allocation[si].size() > ti) {
121 uint8_t layer_fps_fraction = encoder_info_.fps_allocation[si][ti];
122 if (ti > 0) {
123 // We're interested in the frame rate for this layer only, not
124 // cumulative frame rate.
125 layer_fps_fraction -= encoder_info_.fps_allocation[si][ti - 1];
126 }
127 layer_framerate_fps =
128 (target_framerate_fps_ * layer_fps_fraction) /
129 VideoEncoder::EncoderInfo::kMaxFramerateFraction;
130 }
Erik Språng3d11e2f2019-04-15 14:48:30 +0200131 double media_utilization_factor = 1.0;
132 double network_utilization_factor = 1.0;
133 if (media_utilization_factors.size() > si) {
134 RTC_DCHECK_EQ(media_utilization_factors[si].size(),
135 network_utilization_factors[si].size());
136 if (media_utilization_factors[si].size() > ti) {
137 media_utilization_factor = media_utilization_factors[si][ti];
138 network_utilization_factor = network_utilization_factors[si][ti];
139 }
Erik Språng7ca375c2019-02-06 16:20:17 +0100140 }
Erik Språng3d11e2f2019-04-15 14:48:30 +0200141 RTC_DCHECK_GE(network_utilization_factor, media_utilization_factor);
142
143 // Frame size based on constant (media) overshoot.
144 const size_t media_frame_size = media_utilization_factor *
145 (layer_bitrate_bps / 8.0) /
146 layer_framerate_fps;
147
148 constexpr int kFramesWithPenalty = (kSequenceLength / 2) - 1;
149 RTC_DCHECK_GT(kFramesWithPenalty, 0);
150
151 // The positive/negative size diff needed to achieve network rate but
152 // not media rate penalty is the difference between the utilization
153 // factors times the media rate frame size, then scaled by the fraction
154 // between total frames and penalized frames in the sequence.
155 // Cap to media frame size to avoid negative size undershoot.
156 const size_t network_frame_size_diff_bytes = std::min(
157 media_frame_size,
158 static_cast<size_t>(
159 (((network_utilization_factor - media_utilization_factor) *
160 media_frame_size) *
161 kSequenceLength) /
162 kFramesWithPenalty +
163 0.5));
164
165 int sequence_idx = sequence_idx_[si][ti];
166 sequence_idx_[si][ti] = (sequence_idx_[si][ti] + 1) % kSequenceLength;
167 const size_t frame_size_bytes =
168 (sequence_idx < kSequenceLength / 2)
169 ? media_frame_size - network_frame_size_diff_bytes
170 : media_frame_size + network_frame_size_diff_bytes;
Erik Språng7ca375c2019-02-06 16:20:17 +0100171
172 EncodedImage image(buffer, 0, kMaxFrameSize);
173 image.set_size(frame_size_bytes);
174 image.SetSpatialIndex(si);
175 adjuster_->OnEncodedFrame(image, ti);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200176 sequence_idx = ++sequence_idx % kSequenceLength;
Erik Språng7ca375c2019-02-06 16:20:17 +0100177 }
178 }
179 }
180
181 size_t NumSpatialLayers() const {
182 if (codec_.codecType == VideoCodecType::kVideoCodecVP9) {
183 return codec_.VP9().numberOfSpatialLayers;
184 }
185 return codec_.numberOfSimulcastStreams;
186 }
187
188 size_t NumTemporalLayers(int spatial_index) {
189 if (codec_.codecType == VideoCodecType::kVideoCodecVP9) {
190 return codec_.spatialLayers[spatial_index].numberOfTemporalLayers;
191 }
192 return codec_.simulcastStream[spatial_index].numberOfTemporalLayers;
193 }
194
195 void ExpectNear(const VideoBitrateAllocation& expected_allocation,
196 const VideoBitrateAllocation& actual_allocation,
197 double allowed_error_fraction) {
198 for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
199 for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
200 if (expected_allocation.HasBitrate(si, ti)) {
201 EXPECT_TRUE(actual_allocation.HasBitrate(si, ti));
202 uint32_t expected_layer_bitrate_bps =
203 expected_allocation.GetBitrate(si, ti);
204 EXPECT_NEAR(expected_layer_bitrate_bps,
205 actual_allocation.GetBitrate(si, ti),
206 static_cast<uint32_t>(expected_layer_bitrate_bps *
207 allowed_error_fraction));
208 } else {
209 EXPECT_FALSE(actual_allocation.HasBitrate(si, ti));
210 }
211 }
212 }
213 }
214
215 VideoBitrateAllocation MultiplyAllocation(
216 const VideoBitrateAllocation& allocation,
217 double factor) {
218 VideoBitrateAllocation multiplied_allocation;
219 for (size_t si = 0; si < kMaxSpatialLayers; ++si) {
220 for (size_t ti = 0; ti < kMaxTemporalStreams; ++ti) {
221 if (allocation.HasBitrate(si, ti)) {
222 multiplied_allocation.SetBitrate(
223 si, ti,
224 static_cast<uint32_t>(factor * allocation.GetBitrate(si, ti) +
225 0.5));
226 }
227 }
228 }
229 return multiplied_allocation;
230 }
231
232 VideoCodec codec_;
233 VideoEncoder::EncoderInfo encoder_info_;
234 std::unique_ptr<EncoderBitrateAdjuster> adjuster_;
235 VideoBitrateAllocation current_input_allocation_;
236 VideoBitrateAllocation current_adjusted_allocation_;
237 rtc::ScopedFakeClock clock_;
238 DataRate target_bitrate_;
239 double target_framerate_fps_;
240 int tl_pattern_idx_[kMaxSpatialLayers];
Erik Språng3d11e2f2019-04-15 14:48:30 +0200241 int sequence_idx_[kMaxSpatialLayers][kMaxTemporalStreams];
Erik Språng7ca375c2019-02-06 16:20:17 +0100242
243 const std::vector<int> kTlPatterns[kMaxTemporalStreams] = {
244 {0},
245 {0, 1},
246 {0, 2, 1, 2},
247 {0, 3, 2, 3, 1, 3, 2, 3}};
248};
249
250TEST_F(EncoderBitrateAdjusterTest, SingleLayerOptimal) {
251 // Single layer, well behaved encoder.
252 current_input_allocation_.SetBitrate(0, 0, 300000);
253 target_framerate_fps_ = 30;
254 SetUpAdjuster(1, 1, false);
255 InsertFrames({{1.0}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200256 current_adjusted_allocation_ =
257 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
258 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100259 // Adjusted allocation near input. Allow 1% error margin due to rounding
260 // errors etc.
261 ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
262}
263
264TEST_F(EncoderBitrateAdjusterTest, SingleLayerOveruse) {
265 // Single layer, well behaved encoder.
266 current_input_allocation_.SetBitrate(0, 0, 300000);
267 target_framerate_fps_ = 30;
268 SetUpAdjuster(1, 1, false);
269 InsertFrames({{1.2}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200270 current_adjusted_allocation_ =
271 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
272 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100273 // Adjusted allocation lowered by 20%.
274 ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.2),
275 current_adjusted_allocation_, 0.01);
276}
277
278TEST_F(EncoderBitrateAdjusterTest, SingleLayerUnderuse) {
279 // Single layer, well behaved encoder.
280 current_input_allocation_.SetBitrate(0, 0, 300000);
281 target_framerate_fps_ = 30;
282 SetUpAdjuster(1, 1, false);
283 InsertFrames({{0.5}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200284 current_adjusted_allocation_ =
285 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
286 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100287 // Undershoot, adjusted should exactly match input.
288 ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00);
289}
290
291TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOptimalSize) {
292 // Three temporal layers, 60%/20%/20% bps distro, well behaved encoder.
293 current_input_allocation_.SetBitrate(0, 0, 180000);
294 current_input_allocation_.SetBitrate(0, 1, 60000);
295 current_input_allocation_.SetBitrate(0, 2, 60000);
296 target_framerate_fps_ = 30;
297 SetUpAdjuster(1, 3, false);
298 InsertFrames({{1.0, 1.0, 1.0}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200299 current_adjusted_allocation_ =
300 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
301 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100302 ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
303}
304
305TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersOvershoot) {
306 // Three temporal layers, 60%/20%/20% bps distro.
307 // 10% overshoot on all layers.
308 current_input_allocation_.SetBitrate(0, 0, 180000);
309 current_input_allocation_.SetBitrate(0, 1, 60000);
310 current_input_allocation_.SetBitrate(0, 2, 60000);
311 target_framerate_fps_ = 30;
312 SetUpAdjuster(1, 3, false);
313 InsertFrames({{1.1, 1.1, 1.1}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200314 current_adjusted_allocation_ =
315 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
316 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100317 // Adjusted allocation lowered by 10%.
318 ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
319 current_adjusted_allocation_, 0.01);
320}
321
322TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersUndershoot) {
323 // Three temporal layers, 60%/20%/20% bps distro, undershoot all layers.
324 current_input_allocation_.SetBitrate(0, 0, 180000);
325 current_input_allocation_.SetBitrate(0, 1, 60000);
326 current_input_allocation_.SetBitrate(0, 2, 60000);
327 target_framerate_fps_ = 30;
328 SetUpAdjuster(1, 3, false);
329 InsertFrames({{0.8, 0.8, 0.8}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200330 current_adjusted_allocation_ =
331 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
332 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100333 // Adjusted allocation identical since we don't boost bitrates.
334 ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.0);
335}
336
337TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersSkewedOvershoot) {
338 // Three temporal layers, 60%/20%/20% bps distro.
339 // 10% overshoot on base layer, 20% on higher layers.
340 current_input_allocation_.SetBitrate(0, 0, 180000);
341 current_input_allocation_.SetBitrate(0, 1, 60000);
342 current_input_allocation_.SetBitrate(0, 2, 60000);
343 target_framerate_fps_ = 30;
344 SetUpAdjuster(1, 3, false);
345 InsertFrames({{1.1, 1.2, 1.2}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200346 current_adjusted_allocation_ =
347 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
348 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100349 // Expected overshoot is weighted by bitrate:
350 // (0.6 * 1.1 + 0.2 * 1.2 + 0.2 * 1.2) = 1.14
351 ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.14),
352 current_adjusted_allocation_, 0.01);
353}
354
355TEST_F(EncoderBitrateAdjusterTest, FourTemporalLayersSkewedOvershoot) {
356 // Three temporal layers, 40%/30%/15%/15% bps distro.
357 // 10% overshoot on base layer, 20% on higher layers.
358 current_input_allocation_.SetBitrate(0, 0, 120000);
359 current_input_allocation_.SetBitrate(0, 1, 90000);
360 current_input_allocation_.SetBitrate(0, 2, 45000);
361 current_input_allocation_.SetBitrate(0, 3, 45000);
362 target_framerate_fps_ = 30;
363 SetUpAdjuster(1, 4, false);
364 InsertFrames({{1.1, 1.2, 1.2, 1.2}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200365 current_adjusted_allocation_ =
366 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
367 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100368 // Expected overshoot is weighted by bitrate:
369 // (0.4 * 1.1 + 0.3 * 1.2 + 0.15 * 1.2 + 0.15 * 1.2) = 1.16
370 ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.16),
371 current_adjusted_allocation_, 0.01);
372}
373
374TEST_F(EncoderBitrateAdjusterTest, ThreeTemporalLayersNonLayeredEncoder) {
375 // Three temporal layers, 60%/20%/20% bps allocation, 10% overshoot,
376 // encoder does not actually support temporal layers.
377 current_input_allocation_.SetBitrate(0, 0, 180000);
378 current_input_allocation_.SetBitrate(0, 1, 60000);
379 current_input_allocation_.SetBitrate(0, 2, 60000);
380 target_framerate_fps_ = 30;
381 SetUpAdjuster(1, 1, false);
382 InsertFrames({{1.1}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200383 current_adjusted_allocation_ =
384 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
385 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100386 // Expect the actual 10% overuse to be detected and the allocation to
387 // only contain the one entry.
388 VideoBitrateAllocation expected_allocation;
389 expected_allocation.SetBitrate(
390 0, 0,
391 static_cast<uint32_t>(current_input_allocation_.get_sum_bps() / 1.10));
392 ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01);
393}
394
395TEST_F(EncoderBitrateAdjusterTest, IgnoredStream) {
396 // Encoder with three temporal layers, but in a mode that does not support
397 // deterministic frame rate. Those are ignored, even if bitrate overshoots.
398 current_input_allocation_.SetBitrate(0, 0, 180000);
399 current_input_allocation_.SetBitrate(0, 1, 60000);
400 target_framerate_fps_ = 30;
401 SetUpAdjuster(1, 1, false);
402 encoder_info_.fps_allocation[0].clear();
403 adjuster_->OnEncoderInfo(encoder_info_);
404
405 InsertFrames({{1.1}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200406 current_adjusted_allocation_ =
407 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
408 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100409
410 // Values passed through.
411 ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.00);
412}
413
414TEST_F(EncoderBitrateAdjusterTest, DifferentSpatialOvershoots) {
415 // Two streams, both with three temporal layers.
416 // S0 has 5% overshoot, S1 has 25% overshoot.
417 current_input_allocation_.SetBitrate(0, 0, 180000);
418 current_input_allocation_.SetBitrate(0, 1, 60000);
419 current_input_allocation_.SetBitrate(0, 2, 60000);
420 current_input_allocation_.SetBitrate(1, 0, 400000);
421 current_input_allocation_.SetBitrate(1, 1, 150000);
422 current_input_allocation_.SetBitrate(1, 2, 150000);
423 target_framerate_fps_ = 30;
424 // Run twice, once configured as simulcast and once as VP9 SVC.
425 for (int i = 0; i < 2; ++i) {
426 SetUpAdjuster(2, 3, i == 0);
427 InsertFrames({{1.05, 1.05, 1.05}, {1.25, 1.25, 1.25}}, kWindowSizeMs);
Erik Språng3d11e2f2019-04-15 14:48:30 +0200428 current_adjusted_allocation_ =
429 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
430 current_input_allocation_, target_framerate_fps_));
Erik Språng7ca375c2019-02-06 16:20:17 +0100431 VideoBitrateAllocation expected_allocation;
432 for (size_t ti = 0; ti < 3; ++ti) {
433 expected_allocation.SetBitrate(
434 0, ti,
435 static_cast<uint32_t>(current_input_allocation_.GetBitrate(0, ti) /
436 1.05));
437 expected_allocation.SetBitrate(
438 1, ti,
439 static_cast<uint32_t>(current_input_allocation_.GetBitrate(1, ti) /
440 1.25));
441 }
442 ExpectNear(expected_allocation, current_adjusted_allocation_, 0.01);
443 }
444}
445
Erik Språng3d11e2f2019-04-15 14:48:30 +0200446TEST_F(EncoderBitrateAdjusterTest, HeadroomAllowsOvershootToMediaRate) {
447 // Two streams, both with three temporal layers.
448 // Media rate is 1.0, but network rate is higher.
449 ScopedFieldTrials field_trial(
450 "WebRTC-VideoRateControl/adjuster_use_headroom:true/");
451
452 const uint32_t kS0Bitrate = 300000;
453 const uint32_t kS1Bitrate = 900000;
454 current_input_allocation_.SetBitrate(0, 0, kS0Bitrate / 3);
455 current_input_allocation_.SetBitrate(0, 1, kS0Bitrate / 3);
456 current_input_allocation_.SetBitrate(0, 2, kS0Bitrate / 3);
457 current_input_allocation_.SetBitrate(1, 0, kS1Bitrate / 3);
458 current_input_allocation_.SetBitrate(1, 1, kS1Bitrate / 3);
459 current_input_allocation_.SetBitrate(1, 2, kS1Bitrate / 3);
460
461 target_framerate_fps_ = 30;
462
463 // Run twice, once configured as simulcast and once as VP9 SVC.
464 for (int i = 0; i < 2; ++i) {
465 SetUpAdjuster(2, 3, i == 0);
466 // Network rate has 10% overshoot, but media rate is correct at 1.0.
467 InsertFrames({{1.0, 1.0, 1.0}, {1.0, 1.0, 1.0}},
468 {{1.1, 1.1, 1.1}, {1.1, 1.1, 1.1}},
469 kWindowSizeMs * kSequenceLength);
470
471 // Push back by 10%.
472 current_adjusted_allocation_ =
473 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
474 current_input_allocation_, target_framerate_fps_));
475 ExpectNear(MultiplyAllocation(current_input_allocation_, 1 / 1.1),
476 current_adjusted_allocation_, 0.01);
477
478 // Add 10% link headroom, overshoot is now allowed.
479 current_adjusted_allocation_ =
480 adjuster_->AdjustRateAllocation(VideoEncoder::RateControlParameters(
481 current_input_allocation_, target_framerate_fps_,
482 DataRate::bps(current_input_allocation_.get_sum_bps() * 1.1)));
483 ExpectNear(current_input_allocation_, current_adjusted_allocation_, 0.01);
484 }
485}
486
487TEST_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::bps(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
Erik Språng7ca375c2019-02-06 16:20:17 +0100531} // namespace webrtc