1 /*
2 * Copyright (c) 2021 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 "modules/video_coding/utility/bandwidth_quality_scaler.h"
12
13 #include <memory>
14 #include <string>
15
16 #include "api/units/time_delta.h"
17 #include "rtc_base/checks.h"
18 #include "rtc_base/event.h"
19 #include "rtc_base/experiments/encoder_info_settings.h"
20 #include "rtc_base/task_queue_for_test.h"
21 #include "rtc_base/time_utils.h"
22 #include "test/field_trial.h"
23 #include "test/gtest.h"
24
25 namespace webrtc {
26
27 namespace {
28 constexpr int kFramerateFps = 30;
29 constexpr TimeDelta kDefaultBitrateStateUpdateInterval = TimeDelta::Seconds(5);
30 constexpr TimeDelta kDefaultEncodeTime = TimeDelta::Seconds(1) / kFramerateFps;
31
32 } // namespace
33
34 class FakeBandwidthQualityScalerHandler
35 : public BandwidthQualityScalerUsageHandlerInterface {
36 public:
37 ~FakeBandwidthQualityScalerHandler() override = default;
OnReportUsageBandwidthHigh()38 void OnReportUsageBandwidthHigh() override {
39 adapt_down_event_count_++;
40 event_.Set();
41 }
42
OnReportUsageBandwidthLow()43 void OnReportUsageBandwidthLow() override {
44 adapt_up_event_count_++;
45 event_.Set();
46 }
47
48 rtc::Event event_;
49 int adapt_up_event_count_ = 0;
50 int adapt_down_event_count_ = 0;
51 };
52
53 class BandwidthQualityScalerUnderTest : public BandwidthQualityScaler {
54 public:
BandwidthQualityScalerUnderTest(BandwidthQualityScalerUsageHandlerInterface * handler)55 explicit BandwidthQualityScalerUnderTest(
56 BandwidthQualityScalerUsageHandlerInterface* handler)
57 : BandwidthQualityScaler(handler) {}
58
GetBitrateStateUpdateIntervalMs()59 int GetBitrateStateUpdateIntervalMs() {
60 return this->kBitrateStateUpdateInterval.ms() + 200;
61 }
62 };
63
64 class BandwidthQualityScalerTest
65 : public ::testing::Test,
66 public ::testing::WithParamInterface<std::string> {
67 protected:
68 enum ScaleDirection {
69 kKeepScaleNormalBandwidth,
70 kKeepScaleAboveMaxBandwidth,
71 kKeepScaleUnderMinBandwidth,
72 };
73
74 enum FrameType {
75 kKeyFrame,
76 kNormalFrame,
77 kNormalFrame_Overuse,
78 kNormalFrame_Underuse,
79 };
80 struct FrameConfig {
FrameConfigwebrtc::BandwidthQualityScalerTest::FrameConfig81 FrameConfig(int frame_num,
82 FrameType frame_type,
83 int actual_width,
84 int actual_height)
85 : frame_num(frame_num),
86 frame_type(frame_type),
87 actual_width(actual_width),
88 actual_height(actual_height) {}
89
90 int frame_num;
91 FrameType frame_type;
92 int actual_width;
93 int actual_height;
94 };
95
BandwidthQualityScalerTest()96 BandwidthQualityScalerTest()
97 : scoped_field_trial_(GetParam()),
98 task_queue_("BandwidthQualityScalerTestQueue"),
99 handler_(std::make_unique<FakeBandwidthQualityScalerHandler>()) {
100 task_queue_.SendTask(
101 [this] {
102 bandwidth_quality_scaler_ =
103 std::unique_ptr<BandwidthQualityScalerUnderTest>(
104 new BandwidthQualityScalerUnderTest(handler_.get()));
105 bandwidth_quality_scaler_->SetResolutionBitrateLimits(
106 EncoderInfoSettings::
107 GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted());
108 // Only for testing. Set first_timestamp_ in RateStatistics to 0.
109 bandwidth_quality_scaler_->ReportEncodeInfo(0, 0, 0, 0);
110 });
111 }
112
~BandwidthQualityScalerTest()113 ~BandwidthQualityScalerTest() {
114 task_queue_.SendTask([this] { bandwidth_quality_scaler_ = nullptr; });
115 }
116
GetFrameSizeBytes(const FrameConfig & config,const VideoEncoder::ResolutionBitrateLimits & bitrate_limits)117 int GetFrameSizeBytes(
118 const FrameConfig& config,
119 const VideoEncoder::ResolutionBitrateLimits& bitrate_limits) {
120 int scale = 8 * kFramerateFps;
121 switch (config.frame_type) {
122 case FrameType::kKeyFrame: {
123 // 4 is experimental value. Based on the test, the number of bytes of
124 // the key frame is about four times of the normal frame
125 return bitrate_limits.max_bitrate_bps * 4 / scale;
126 }
127 case FrameType::kNormalFrame_Overuse: {
128 return bitrate_limits.max_bitrate_bps * 3 / 2 / scale;
129 }
130 case FrameType::kNormalFrame_Underuse: {
131 return bitrate_limits.min_start_bitrate_bps * 3 / 4 / scale;
132 }
133 case FrameType::kNormalFrame: {
134 return (bitrate_limits.max_bitrate_bps +
135 bitrate_limits.min_start_bitrate_bps) /
136 2 / scale;
137 }
138 }
139 return -1;
140 }
141
142 absl::optional<VideoEncoder::ResolutionBitrateLimits>
GetDefaultSuitableBitrateLimit(int frame_size_pixels)143 GetDefaultSuitableBitrateLimit(int frame_size_pixels) {
144 return EncoderInfoSettings::
145 GetSinglecastBitrateLimitForResolutionWhenQpIsUntrusted(
146 frame_size_pixels,
147 EncoderInfoSettings::
148 GetDefaultSinglecastBitrateLimitsWhenQpIsUntrusted());
149 }
150
TriggerBandwidthQualityScalerTest(const std::vector<FrameConfig> & frame_configs)151 void TriggerBandwidthQualityScalerTest(
152 const std::vector<FrameConfig>& frame_configs) {
153 task_queue_.SendTask(
154 [frame_configs, this] {
155 RTC_CHECK(!frame_configs.empty());
156
157 int total_frame_nums = 0;
158 for (const FrameConfig& frame_config : frame_configs) {
159 total_frame_nums += frame_config.frame_num;
160 }
161
162 EXPECT_EQ(
163 kFramerateFps * kDefaultBitrateStateUpdateInterval.seconds(),
164 total_frame_nums);
165
166 uint32_t time_send_to_scaler_ms_ = rtc::TimeMillis();
167 for (size_t i = 0; i < frame_configs.size(); ++i) {
168 const FrameConfig& config = frame_configs[i];
169 absl::optional<VideoEncoder::ResolutionBitrateLimits>
170 suitable_bitrate = GetDefaultSuitableBitrateLimit(
171 config.actual_width * config.actual_height);
172 EXPECT_TRUE(suitable_bitrate);
173 for (int j = 0; j <= config.frame_num; ++j) {
174 time_send_to_scaler_ms_ += kDefaultEncodeTime.ms();
175 int frame_size_bytes =
176 GetFrameSizeBytes(config, suitable_bitrate.value());
177 RTC_CHECK(frame_size_bytes > 0);
178 bandwidth_quality_scaler_->ReportEncodeInfo(
179 frame_size_bytes, time_send_to_scaler_ms_,
180 config.actual_width, config.actual_height);
181 }
182 }
183 });
184 }
185
186 test::ScopedFieldTrials scoped_field_trial_;
187 TaskQueueForTest task_queue_;
188 std::unique_ptr<BandwidthQualityScalerUnderTest> bandwidth_quality_scaler_;
189 std::unique_ptr<FakeBandwidthQualityScalerHandler> handler_;
190 };
191
192 INSTANTIATE_TEST_SUITE_P(
193 FieldTrials,
194 BandwidthQualityScalerTest,
195 ::testing::Values("WebRTC-Video-BandwidthQualityScalerSettings/"
196 "bitrate_state_update_interval_s_:1/",
197 "WebRTC-Video-BandwidthQualityScalerSettings/"
198 "bitrate_state_update_interval_s_:2/"));
199
TEST_P(BandwidthQualityScalerTest,AllNormalFrame_640x360)200 TEST_P(BandwidthQualityScalerTest, AllNormalFrame_640x360) {
201 const std::vector<FrameConfig> frame_configs{
202 FrameConfig(150, FrameType::kNormalFrame, 640, 360)};
203 TriggerBandwidthQualityScalerTest(frame_configs);
204
205 // When resolution is 640*360, experimental working bitrate range is
206 // [500000,800000] bps. Encoded bitrate is 654253, so it falls in the range
207 // without any operation(up/down).
208 EXPECT_FALSE(handler_->event_.Wait(TimeDelta::Millis(
209 bandwidth_quality_scaler_->GetBitrateStateUpdateIntervalMs())));
210 EXPECT_EQ(0, handler_->adapt_down_event_count_);
211 EXPECT_EQ(0, handler_->adapt_up_event_count_);
212 }
213
TEST_P(BandwidthQualityScalerTest,AllNoramlFrame_AboveMaxBandwidth_640x360)214 TEST_P(BandwidthQualityScalerTest, AllNoramlFrame_AboveMaxBandwidth_640x360) {
215 const std::vector<FrameConfig> frame_configs{
216 FrameConfig(150, FrameType::kNormalFrame_Overuse, 640, 360)};
217 TriggerBandwidthQualityScalerTest(frame_configs);
218
219 // When resolution is 640*360, experimental working bitrate range is
220 // [500000,800000] bps. Encoded bitrate is 1208000 > 800000 * 0.95, so it
221 // triggers adapt_up_event_count_.
222 EXPECT_TRUE(handler_->event_.Wait(TimeDelta::Millis(
223 bandwidth_quality_scaler_->GetBitrateStateUpdateIntervalMs())));
224 EXPECT_EQ(0, handler_->adapt_down_event_count_);
225 EXPECT_EQ(1, handler_->adapt_up_event_count_);
226 }
227
TEST_P(BandwidthQualityScalerTest,AllNormalFrame_Underuse_640x360)228 TEST_P(BandwidthQualityScalerTest, AllNormalFrame_Underuse_640x360) {
229 const std::vector<FrameConfig> frame_configs{
230 FrameConfig(150, FrameType::kNormalFrame_Underuse, 640, 360)};
231 TriggerBandwidthQualityScalerTest(frame_configs);
232
233 // When resolution is 640*360, experimental working bitrate range is
234 // [500000,800000] bps. Encoded bitrate is 377379 < 500000 * 0.8, so it
235 // triggers adapt_down_event_count_.
236 EXPECT_TRUE(handler_->event_.Wait(TimeDelta::Millis(
237 bandwidth_quality_scaler_->GetBitrateStateUpdateIntervalMs())));
238 EXPECT_EQ(1, handler_->adapt_down_event_count_);
239 EXPECT_EQ(0, handler_->adapt_up_event_count_);
240 }
241
TEST_P(BandwidthQualityScalerTest,FixedFrameTypeTest1_640x360)242 TEST_P(BandwidthQualityScalerTest, FixedFrameTypeTest1_640x360) {
243 const std::vector<FrameConfig> frame_configs{
244 FrameConfig(5, FrameType::kNormalFrame_Underuse, 640, 360),
245 FrameConfig(110, FrameType::kNormalFrame, 640, 360),
246 FrameConfig(20, FrameType::kNormalFrame_Overuse, 640, 360),
247 FrameConfig(15, FrameType::kKeyFrame, 640, 360),
248 };
249 TriggerBandwidthQualityScalerTest(frame_configs);
250
251 // When resolution is 640*360, experimental working bitrate range is
252 // [500000,800000] bps. Encoded bitrate is 1059462 > 800000 * 0.95, so it
253 // triggers adapt_up_event_count_.
254 EXPECT_TRUE(handler_->event_.Wait(TimeDelta::Millis(
255 bandwidth_quality_scaler_->GetBitrateStateUpdateIntervalMs())));
256 EXPECT_EQ(0, handler_->adapt_down_event_count_);
257 EXPECT_EQ(1, handler_->adapt_up_event_count_);
258 }
259
TEST_P(BandwidthQualityScalerTest,FixedFrameTypeTest2_640x360)260 TEST_P(BandwidthQualityScalerTest, FixedFrameTypeTest2_640x360) {
261 const std::vector<FrameConfig> frame_configs{
262 FrameConfig(10, FrameType::kNormalFrame_Underuse, 640, 360),
263 FrameConfig(50, FrameType::kNormalFrame, 640, 360),
264 FrameConfig(5, FrameType::kKeyFrame, 640, 360),
265 FrameConfig(85, FrameType::kNormalFrame_Overuse, 640, 360),
266 };
267 TriggerBandwidthQualityScalerTest(frame_configs);
268
269 // When resolution is 640*360, experimental working bitrate range is
270 // [500000,800000] bps. Encoded bitrate is 1059462 > 800000 * 0.95, so it
271 // triggers adapt_up_event_count_.
272 EXPECT_TRUE(handler_->event_.Wait(TimeDelta::Millis(
273 bandwidth_quality_scaler_->GetBitrateStateUpdateIntervalMs())));
274 EXPECT_EQ(0, handler_->adapt_down_event_count_);
275 EXPECT_EQ(1, handler_->adapt_up_event_count_);
276 }
277
278 } // namespace webrtc
279