xref: /aosp_15_r20/external/webrtc/common_video/bitrate_adjuster_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2016 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 "common_video/include/bitrate_adjuster.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include "api/units/time_delta.h"
14*d9f75844SAndroid Build Coastguard Worker #include "rtc_base/fake_clock.h"
15*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
16*d9f75844SAndroid Build Coastguard Worker 
17*d9f75844SAndroid Build Coastguard Worker namespace webrtc {
18*d9f75844SAndroid Build Coastguard Worker 
19*d9f75844SAndroid Build Coastguard Worker class BitrateAdjusterTest : public ::testing::Test {
20*d9f75844SAndroid Build Coastguard Worker  public:
BitrateAdjusterTest()21*d9f75844SAndroid Build Coastguard Worker   BitrateAdjusterTest()
22*d9f75844SAndroid Build Coastguard Worker       : adjuster_(kMinAdjustedBitratePct, kMaxAdjustedBitratePct) {}
23*d9f75844SAndroid Build Coastguard Worker 
24*d9f75844SAndroid Build Coastguard Worker   // Simulate an output bitrate for one update cycle of BitrateAdjuster.
SimulateBitrateBps(uint32_t bitrate_bps)25*d9f75844SAndroid Build Coastguard Worker   void SimulateBitrateBps(uint32_t bitrate_bps) {
26*d9f75844SAndroid Build Coastguard Worker     const uint32_t update_interval_ms =
27*d9f75844SAndroid Build Coastguard Worker         BitrateAdjuster::kBitrateUpdateIntervalMs;
28*d9f75844SAndroid Build Coastguard Worker     const uint32_t update_frame_interval =
29*d9f75844SAndroid Build Coastguard Worker         BitrateAdjuster::kBitrateUpdateFrameInterval;
30*d9f75844SAndroid Build Coastguard Worker     // Round up frame interval so we get one cycle passes.
31*d9f75844SAndroid Build Coastguard Worker     const uint32_t frame_interval_ms =
32*d9f75844SAndroid Build Coastguard Worker         (update_interval_ms + update_frame_interval - 1) /
33*d9f75844SAndroid Build Coastguard Worker         update_frame_interval;
34*d9f75844SAndroid Build Coastguard Worker     const size_t frame_size_bytes =
35*d9f75844SAndroid Build Coastguard Worker         (bitrate_bps * frame_interval_ms) / (8 * 1000);
36*d9f75844SAndroid Build Coastguard Worker     for (size_t i = 0; i < update_frame_interval; ++i) {
37*d9f75844SAndroid Build Coastguard Worker       clock_.AdvanceTime(webrtc::TimeDelta::Millis(frame_interval_ms));
38*d9f75844SAndroid Build Coastguard Worker       adjuster_.Update(frame_size_bytes);
39*d9f75844SAndroid Build Coastguard Worker     }
40*d9f75844SAndroid Build Coastguard Worker   }
41*d9f75844SAndroid Build Coastguard Worker 
GetTargetBitrateBpsPct(float pct)42*d9f75844SAndroid Build Coastguard Worker   uint32_t GetTargetBitrateBpsPct(float pct) {
43*d9f75844SAndroid Build Coastguard Worker     return pct * adjuster_.GetTargetBitrateBps();
44*d9f75844SAndroid Build Coastguard Worker   }
45*d9f75844SAndroid Build Coastguard Worker 
VerifyAdjustment()46*d9f75844SAndroid Build Coastguard Worker   void VerifyAdjustment() {
47*d9f75844SAndroid Build Coastguard Worker     // The adjusted bitrate should be between the estimated bitrate and the
48*d9f75844SAndroid Build Coastguard Worker     // target bitrate within clamp.
49*d9f75844SAndroid Build Coastguard Worker     uint32_t target_bitrate_bps = adjuster_.GetTargetBitrateBps();
50*d9f75844SAndroid Build Coastguard Worker     uint32_t adjusted_bitrate_bps = adjuster_.GetAdjustedBitrateBps();
51*d9f75844SAndroid Build Coastguard Worker     uint32_t estimated_bitrate_bps =
52*d9f75844SAndroid Build Coastguard Worker         adjuster_.GetEstimatedBitrateBps().value_or(target_bitrate_bps);
53*d9f75844SAndroid Build Coastguard Worker     uint32_t adjusted_lower_bound_bps =
54*d9f75844SAndroid Build Coastguard Worker         GetTargetBitrateBpsPct(kMinAdjustedBitratePct);
55*d9f75844SAndroid Build Coastguard Worker     uint32_t adjusted_upper_bound_bps =
56*d9f75844SAndroid Build Coastguard Worker         GetTargetBitrateBpsPct(kMaxAdjustedBitratePct);
57*d9f75844SAndroid Build Coastguard Worker     EXPECT_LE(adjusted_bitrate_bps, adjusted_upper_bound_bps);
58*d9f75844SAndroid Build Coastguard Worker     EXPECT_GE(adjusted_bitrate_bps, adjusted_lower_bound_bps);
59*d9f75844SAndroid Build Coastguard Worker     if (estimated_bitrate_bps > target_bitrate_bps) {
60*d9f75844SAndroid Build Coastguard Worker       EXPECT_LT(adjusted_bitrate_bps, target_bitrate_bps);
61*d9f75844SAndroid Build Coastguard Worker     }
62*d9f75844SAndroid Build Coastguard Worker   }
63*d9f75844SAndroid Build Coastguard Worker 
64*d9f75844SAndroid Build Coastguard Worker  protected:
65*d9f75844SAndroid Build Coastguard Worker   static const float kMinAdjustedBitratePct;
66*d9f75844SAndroid Build Coastguard Worker   static const float kMaxAdjustedBitratePct;
67*d9f75844SAndroid Build Coastguard Worker   rtc::ScopedFakeClock clock_;
68*d9f75844SAndroid Build Coastguard Worker   BitrateAdjuster adjuster_;
69*d9f75844SAndroid Build Coastguard Worker };
70*d9f75844SAndroid Build Coastguard Worker 
71*d9f75844SAndroid Build Coastguard Worker const float BitrateAdjusterTest::kMinAdjustedBitratePct = .5f;
72*d9f75844SAndroid Build Coastguard Worker const float BitrateAdjusterTest::kMaxAdjustedBitratePct = .95f;
73*d9f75844SAndroid Build Coastguard Worker 
TEST_F(BitrateAdjusterTest,VaryingBitrates)74*d9f75844SAndroid Build Coastguard Worker TEST_F(BitrateAdjusterTest, VaryingBitrates) {
75*d9f75844SAndroid Build Coastguard Worker   const uint32_t target_bitrate_bps = 640000;
76*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
77*d9f75844SAndroid Build Coastguard Worker 
78*d9f75844SAndroid Build Coastguard Worker   // Grossly overshoot for a little while. Adjusted bitrate should decrease.
79*d9f75844SAndroid Build Coastguard Worker   uint32_t actual_bitrate_bps = 2 * target_bitrate_bps;
80*d9f75844SAndroid Build Coastguard Worker   uint32_t last_adjusted_bitrate_bps = 0;
81*d9f75844SAndroid Build Coastguard Worker   uint32_t adjusted_bitrate_bps = 0;
82*d9f75844SAndroid Build Coastguard Worker 
83*d9f75844SAndroid Build Coastguard Worker   SimulateBitrateBps(actual_bitrate_bps);
84*d9f75844SAndroid Build Coastguard Worker   VerifyAdjustment();
85*d9f75844SAndroid Build Coastguard Worker   last_adjusted_bitrate_bps = adjuster_.GetAdjustedBitrateBps();
86*d9f75844SAndroid Build Coastguard Worker 
87*d9f75844SAndroid Build Coastguard Worker   SimulateBitrateBps(actual_bitrate_bps);
88*d9f75844SAndroid Build Coastguard Worker   VerifyAdjustment();
89*d9f75844SAndroid Build Coastguard Worker   adjusted_bitrate_bps = adjuster_.GetAdjustedBitrateBps();
90*d9f75844SAndroid Build Coastguard Worker   EXPECT_LE(adjusted_bitrate_bps, last_adjusted_bitrate_bps);
91*d9f75844SAndroid Build Coastguard Worker   last_adjusted_bitrate_bps = adjusted_bitrate_bps;
92*d9f75844SAndroid Build Coastguard Worker   // After two cycles we should've stabilized and hit the lower bound.
93*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(GetTargetBitrateBpsPct(kMinAdjustedBitratePct),
94*d9f75844SAndroid Build Coastguard Worker             adjusted_bitrate_bps);
95*d9f75844SAndroid Build Coastguard Worker 
96*d9f75844SAndroid Build Coastguard Worker   // Simulate encoder settling down. Adjusted bitrate should increase.
97*d9f75844SAndroid Build Coastguard Worker   SimulateBitrateBps(target_bitrate_bps);
98*d9f75844SAndroid Build Coastguard Worker   adjusted_bitrate_bps = adjuster_.GetAdjustedBitrateBps();
99*d9f75844SAndroid Build Coastguard Worker   VerifyAdjustment();
100*d9f75844SAndroid Build Coastguard Worker   EXPECT_GT(adjusted_bitrate_bps, last_adjusted_bitrate_bps);
101*d9f75844SAndroid Build Coastguard Worker   last_adjusted_bitrate_bps = adjusted_bitrate_bps;
102*d9f75844SAndroid Build Coastguard Worker 
103*d9f75844SAndroid Build Coastguard Worker   SimulateBitrateBps(target_bitrate_bps);
104*d9f75844SAndroid Build Coastguard Worker   adjusted_bitrate_bps = adjuster_.GetAdjustedBitrateBps();
105*d9f75844SAndroid Build Coastguard Worker   VerifyAdjustment();
106*d9f75844SAndroid Build Coastguard Worker   EXPECT_GT(adjusted_bitrate_bps, last_adjusted_bitrate_bps);
107*d9f75844SAndroid Build Coastguard Worker   last_adjusted_bitrate_bps = adjusted_bitrate_bps;
108*d9f75844SAndroid Build Coastguard Worker   // After two cycles we should've stabilized and hit the upper bound.
109*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(GetTargetBitrateBpsPct(kMaxAdjustedBitratePct),
110*d9f75844SAndroid Build Coastguard Worker             adjusted_bitrate_bps);
111*d9f75844SAndroid Build Coastguard Worker }
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker // Tests that large changes in target bitrate will result in immediate change
114*d9f75844SAndroid Build Coastguard Worker // in adjusted bitrate.
TEST_F(BitrateAdjusterTest,LargeTargetDelta)115*d9f75844SAndroid Build Coastguard Worker TEST_F(BitrateAdjusterTest, LargeTargetDelta) {
116*d9f75844SAndroid Build Coastguard Worker   uint32_t target_bitrate_bps = 640000;
117*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
118*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
119*d9f75844SAndroid Build Coastguard Worker 
120*d9f75844SAndroid Build Coastguard Worker   float delta_pct = BitrateAdjuster::kBitrateTolerancePct * 2;
121*d9f75844SAndroid Build Coastguard Worker 
122*d9f75844SAndroid Build Coastguard Worker   target_bitrate_bps = (1 + delta_pct) * target_bitrate_bps;
123*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
124*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
125*d9f75844SAndroid Build Coastguard Worker 
126*d9f75844SAndroid Build Coastguard Worker   target_bitrate_bps = (1 - delta_pct) * target_bitrate_bps;
127*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
128*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
129*d9f75844SAndroid Build Coastguard Worker }
130*d9f75844SAndroid Build Coastguard Worker 
131*d9f75844SAndroid Build Coastguard Worker // Tests that small changes in target bitrate within tolerance will not affect
132*d9f75844SAndroid Build Coastguard Worker // adjusted bitrate immediately.
TEST_F(BitrateAdjusterTest,SmallTargetDelta)133*d9f75844SAndroid Build Coastguard Worker TEST_F(BitrateAdjusterTest, SmallTargetDelta) {
134*d9f75844SAndroid Build Coastguard Worker   const uint32_t initial_target_bitrate_bps = 640000;
135*d9f75844SAndroid Build Coastguard Worker   uint32_t target_bitrate_bps = initial_target_bitrate_bps;
136*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
137*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(initial_target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
138*d9f75844SAndroid Build Coastguard Worker 
139*d9f75844SAndroid Build Coastguard Worker   float delta_pct = BitrateAdjuster::kBitrateTolerancePct / 2;
140*d9f75844SAndroid Build Coastguard Worker 
141*d9f75844SAndroid Build Coastguard Worker   target_bitrate_bps = (1 + delta_pct) * target_bitrate_bps;
142*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
143*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(initial_target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
144*d9f75844SAndroid Build Coastguard Worker 
145*d9f75844SAndroid Build Coastguard Worker   target_bitrate_bps = (1 - delta_pct) * target_bitrate_bps;
146*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
147*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(initial_target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
148*d9f75844SAndroid Build Coastguard Worker }
149*d9f75844SAndroid Build Coastguard Worker 
TEST_F(BitrateAdjusterTest,SmallTargetDeltaOverflow)150*d9f75844SAndroid Build Coastguard Worker TEST_F(BitrateAdjusterTest, SmallTargetDeltaOverflow) {
151*d9f75844SAndroid Build Coastguard Worker   const uint32_t initial_target_bitrate_bps = 640000;
152*d9f75844SAndroid Build Coastguard Worker   uint32_t target_bitrate_bps = initial_target_bitrate_bps;
153*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
154*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(initial_target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
155*d9f75844SAndroid Build Coastguard Worker 
156*d9f75844SAndroid Build Coastguard Worker   float delta_pct = BitrateAdjuster::kBitrateTolerancePct / 2;
157*d9f75844SAndroid Build Coastguard Worker 
158*d9f75844SAndroid Build Coastguard Worker   target_bitrate_bps = (1 + delta_pct) * target_bitrate_bps;
159*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
160*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(initial_target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
161*d9f75844SAndroid Build Coastguard Worker 
162*d9f75844SAndroid Build Coastguard Worker   // 1.05 * 1.05 is 1.1 which is greater than tolerance for the initial target
163*d9f75844SAndroid Build Coastguard Worker   // bitrate. Since we didn't advance the clock the adjuster never updated.
164*d9f75844SAndroid Build Coastguard Worker   target_bitrate_bps = (1 + delta_pct) * target_bitrate_bps;
165*d9f75844SAndroid Build Coastguard Worker   adjuster_.SetTargetBitrateBps(target_bitrate_bps);
166*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(target_bitrate_bps, adjuster_.GetAdjustedBitrateBps());
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker 
169*d9f75844SAndroid Build Coastguard Worker }  // namespace webrtc
170