xref: /aosp_15_r20/external/webrtc/modules/video_coding/utility/bandwidth_quality_scaler_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
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