xref: /aosp_15_r20/external/webrtc/rtc_base/rate_tracker_unittest.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1*d9f75844SAndroid Build Coastguard Worker /*
2*d9f75844SAndroid Build Coastguard Worker  *  Copyright 2015 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 "rtc_base/rate_tracker.h"
12*d9f75844SAndroid Build Coastguard Worker 
13*d9f75844SAndroid Build Coastguard Worker #include "test/gtest.h"
14*d9f75844SAndroid Build Coastguard Worker 
15*d9f75844SAndroid Build Coastguard Worker namespace rtc {
16*d9f75844SAndroid Build Coastguard Worker namespace {
17*d9f75844SAndroid Build Coastguard Worker const uint32_t kBucketIntervalMs = 100;
18*d9f75844SAndroid Build Coastguard Worker }  // namespace
19*d9f75844SAndroid Build Coastguard Worker 
20*d9f75844SAndroid Build Coastguard Worker class RateTrackerForTest : public RateTracker {
21*d9f75844SAndroid Build Coastguard Worker  public:
RateTrackerForTest()22*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest() : RateTracker(kBucketIntervalMs, 10u), time_(0) {}
Time() const23*d9f75844SAndroid Build Coastguard Worker   int64_t Time() const override { return time_; }
AdvanceTime(int delta)24*d9f75844SAndroid Build Coastguard Worker   void AdvanceTime(int delta) { time_ += delta; }
25*d9f75844SAndroid Build Coastguard Worker 
26*d9f75844SAndroid Build Coastguard Worker  private:
27*d9f75844SAndroid Build Coastguard Worker   int64_t time_;
28*d9f75844SAndroid Build Coastguard Worker };
29*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,Test30FPS)30*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, Test30FPS) {
31*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
32*d9f75844SAndroid Build Coastguard Worker 
33*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 300; ++i) {
34*d9f75844SAndroid Build Coastguard Worker     tracker.AddSamples(1);
35*d9f75844SAndroid Build Coastguard Worker     tracker.AdvanceTime(33);
36*d9f75844SAndroid Build Coastguard Worker     if (i % 3 == 0) {
37*d9f75844SAndroid Build Coastguard Worker       tracker.AdvanceTime(1);
38*d9f75844SAndroid Build Coastguard Worker     }
39*d9f75844SAndroid Build Coastguard Worker   }
40*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(30.0, tracker.ComputeRateForInterval(50000));
41*d9f75844SAndroid Build Coastguard Worker }
42*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,Test60FPS)43*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, Test60FPS) {
44*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
45*d9f75844SAndroid Build Coastguard Worker 
46*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 300; ++i) {
47*d9f75844SAndroid Build Coastguard Worker     tracker.AddSamples(1);
48*d9f75844SAndroid Build Coastguard Worker     tracker.AdvanceTime(16);
49*d9f75844SAndroid Build Coastguard Worker     if (i % 3 != 0) {
50*d9f75844SAndroid Build Coastguard Worker       tracker.AdvanceTime(1);
51*d9f75844SAndroid Build Coastguard Worker     }
52*d9f75844SAndroid Build Coastguard Worker   }
53*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(60.0, tracker.ComputeRateForInterval(1000));
54*d9f75844SAndroid Build Coastguard Worker }
55*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,TestRateTrackerBasics)56*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestRateTrackerBasics) {
57*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
58*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRateForInterval(1000));
59*d9f75844SAndroid Build Coastguard Worker 
60*d9f75844SAndroid Build Coastguard Worker   // Add a sample.
61*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(1234);
62*d9f75844SAndroid Build Coastguard Worker   // Advance the clock by less than one bucket interval (no rate returned).
63*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(kBucketIntervalMs - 1);
64*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRate());
65*d9f75844SAndroid Build Coastguard Worker   // Advance the clock by 100 ms (one bucket interval).
66*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(1);
67*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRateForInterval(1000));
68*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRate());
69*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U, tracker.TotalSampleCount());
70*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeTotalRate());
71*d9f75844SAndroid Build Coastguard Worker 
72*d9f75844SAndroid Build Coastguard Worker   // Repeat.
73*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(1234);
74*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(100);
75*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRateForInterval(1000));
76*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeRate());
77*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
78*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(12340.0, tracker.ComputeTotalRate());
79*d9f75844SAndroid Build Coastguard Worker 
80*d9f75844SAndroid Build Coastguard Worker   // Advance the clock by 800 ms, so we've elapsed a full second.
81*d9f75844SAndroid Build Coastguard Worker   // units_second should now be filled in properly.
82*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(800);
83*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRateForInterval(1000));
84*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRate());
85*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
86*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeTotalRate());
87*d9f75844SAndroid Build Coastguard Worker 
88*d9f75844SAndroid Build Coastguard Worker   // Poll the tracker again immediately. The reported rate should stay the same.
89*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRateForInterval(1000));
90*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeRate());
91*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
92*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0 * 2.0, tracker.ComputeTotalRate());
93*d9f75844SAndroid Build Coastguard Worker 
94*d9f75844SAndroid Build Coastguard Worker   // Do nothing and advance by a second. We should drop down to zero.
95*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(1000);
96*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRateForInterval(1000));
97*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRate());
98*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U * 2, tracker.TotalSampleCount());
99*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0, tracker.ComputeTotalRate());
100*d9f75844SAndroid Build Coastguard Worker 
101*d9f75844SAndroid Build Coastguard Worker   // Send a bunch of data at a constant rate for 5.5 "seconds".
102*d9f75844SAndroid Build Coastguard Worker   // We should report the rate properly.
103*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 5500; i += 100) {
104*d9f75844SAndroid Build Coastguard Worker     tracker.AddSamples(9876U);
105*d9f75844SAndroid Build Coastguard Worker     tracker.AdvanceTime(100);
106*d9f75844SAndroid Build Coastguard Worker   }
107*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(9876.0 * 10.0, tracker.ComputeRateForInterval(1000));
108*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(9876.0 * 10.0, tracker.ComputeRate());
109*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U * 2 + 9876U * 55, tracker.TotalSampleCount());
110*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ((1234.0 * 2.0 + 9876.0 * 55.0) / 7.5,
111*d9f75844SAndroid Build Coastguard Worker                    tracker.ComputeTotalRate());
112*d9f75844SAndroid Build Coastguard Worker 
113*d9f75844SAndroid Build Coastguard Worker   // Advance the clock by 500 ms. Since we sent nothing over this half-second,
114*d9f75844SAndroid Build Coastguard Worker   // the reported rate should be reduced by half.
115*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(500);
116*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(9876.0 * 5.0, tracker.ComputeRateForInterval(1000));
117*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(9876.0 * 5.0, tracker.ComputeRate());
118*d9f75844SAndroid Build Coastguard Worker   EXPECT_EQ(1234U * 2 + 9876U * 55, tracker.TotalSampleCount());
119*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ((1234.0 * 2.0 + 9876.0 * 55.0) / 8.0,
120*d9f75844SAndroid Build Coastguard Worker                    tracker.ComputeTotalRate());
121*d9f75844SAndroid Build Coastguard Worker 
122*d9f75844SAndroid Build Coastguard Worker   // Rate over the last half second should be zero.
123*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRateForInterval(500));
124*d9f75844SAndroid Build Coastguard Worker }
125*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,TestLongPeriodBetweenSamples)126*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestLongPeriodBetweenSamples) {
127*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
128*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(1);
129*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(1000);
130*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1.0, tracker.ComputeRate());
131*d9f75844SAndroid Build Coastguard Worker 
132*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(2000);
133*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(0.0, tracker.ComputeRate());
134*d9f75844SAndroid Build Coastguard Worker 
135*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(2000);
136*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(1);
137*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1.0, tracker.ComputeRate());
138*d9f75844SAndroid Build Coastguard Worker }
139*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,TestRolloff)140*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestRolloff) {
141*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
142*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 10; ++i) {
143*d9f75844SAndroid Build Coastguard Worker     tracker.AddSamples(1U);
144*d9f75844SAndroid Build Coastguard Worker     tracker.AdvanceTime(100);
145*d9f75844SAndroid Build Coastguard Worker   }
146*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(10.0, tracker.ComputeRate());
147*d9f75844SAndroid Build Coastguard Worker 
148*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 10; ++i) {
149*d9f75844SAndroid Build Coastguard Worker     tracker.AddSamples(1U);
150*d9f75844SAndroid Build Coastguard Worker     tracker.AdvanceTime(50);
151*d9f75844SAndroid Build Coastguard Worker   }
152*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(15.0, tracker.ComputeRate());
153*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(20.0, tracker.ComputeRateForInterval(500));
154*d9f75844SAndroid Build Coastguard Worker 
155*d9f75844SAndroid Build Coastguard Worker   for (int i = 0; i < 10; ++i) {
156*d9f75844SAndroid Build Coastguard Worker     tracker.AddSamples(1U);
157*d9f75844SAndroid Build Coastguard Worker     tracker.AdvanceTime(50);
158*d9f75844SAndroid Build Coastguard Worker   }
159*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(20.0, tracker.ComputeRate());
160*d9f75844SAndroid Build Coastguard Worker }
161*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,TestGetUnitSecondsAfterInitialValue)162*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestGetUnitSecondsAfterInitialValue) {
163*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
164*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(1234);
165*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(1000);
166*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(1234.0, tracker.ComputeRateForInterval(1000));
167*d9f75844SAndroid Build Coastguard Worker }
168*d9f75844SAndroid Build Coastguard Worker 
TEST(RateTrackerTest,TestLargeNumbers)169*d9f75844SAndroid Build Coastguard Worker TEST(RateTrackerTest, TestLargeNumbers) {
170*d9f75844SAndroid Build Coastguard Worker   RateTrackerForTest tracker;
171*d9f75844SAndroid Build Coastguard Worker   const uint64_t large_number = 0x100000000;
172*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(large_number);
173*d9f75844SAndroid Build Coastguard Worker   tracker.AdvanceTime(1000);
174*d9f75844SAndroid Build Coastguard Worker   tracker.AddSamples(large_number);
175*d9f75844SAndroid Build Coastguard Worker   EXPECT_DOUBLE_EQ(large_number * 2, tracker.ComputeRate());
176*d9f75844SAndroid Build Coastguard Worker }
177*d9f75844SAndroid Build Coastguard Worker 
178*d9f75844SAndroid Build Coastguard Worker }  // namespace rtc
179