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