OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (c) 2012 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 <algorithm> | |
12 | |
13 #include "webrtc/base/rate_statistics.h" | |
14 #include "webrtc/test/gtest.h" | |
15 | |
16 namespace { | |
17 | |
18 using webrtc::RateStatistics; | |
19 | |
20 const int64_t kWindowMs = 500; | |
21 | |
22 class RateStatisticsTest : public ::testing::Test { | |
23 protected: | |
24 RateStatisticsTest() : stats_(kWindowMs, 8000) {} | |
25 RateStatistics stats_; | |
26 }; | |
27 | |
28 TEST_F(RateStatisticsTest, TestStrictMode) { | |
29 int64_t now_ms = 0; | |
30 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
31 | |
32 const uint32_t kPacketSize = 1500u; | |
33 const uint32_t kExpectedRateBps = kPacketSize * 1000 * 8; | |
34 | |
35 // Single data point is not enough for valid estimate. | |
36 stats_.Update(kPacketSize, now_ms++); | |
37 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
38 | |
39 // Expecting 1200 kbps since the window is initially kept small and grows as | |
40 // we have more data. | |
41 stats_.Update(kPacketSize, now_ms); | |
42 EXPECT_EQ(kExpectedRateBps, *stats_.Rate(now_ms)); | |
43 | |
44 stats_.Reset(); | |
45 // Expecting 0 after init. | |
46 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
47 | |
48 const int kInterval = 10; | |
49 for (int i = 0; i < 100000; ++i) { | |
50 if (i % kInterval == 0) | |
51 stats_.Update(kPacketSize, now_ms); | |
52 | |
53 // Approximately 1200 kbps expected. Not exact since when packets | |
54 // are removed we will jump 10 ms to the next packet. | |
55 if (i > kInterval) { | |
56 rtc::Optional<uint32_t> rate = stats_.Rate(now_ms); | |
57 EXPECT_TRUE(static_cast<bool>(rate)); | |
58 uint32_t samples = i / kInterval + 1; | |
59 uint64_t total_bits = samples * kPacketSize * 8; | |
60 uint32_t rate_bps = static_cast<uint32_t>((1000 * total_bits) / (i + 1)); | |
61 EXPECT_NEAR(rate_bps, *rate, 22000u); | |
62 } | |
63 now_ms += 1; | |
64 } | |
65 now_ms += kWindowMs; | |
66 // The window is 2 seconds. If nothing has been received for that time | |
67 // the estimate should be 0. | |
68 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
69 } | |
70 | |
71 TEST_F(RateStatisticsTest, IncreasingThenDecreasingBitrate) { | |
72 int64_t now_ms = 0; | |
73 stats_.Reset(); | |
74 // Expecting 0 after init. | |
75 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
76 | |
77 stats_.Update(1000, ++now_ms); | |
78 const uint32_t kExpectedBitrate = 8000000; | |
79 // 1000 bytes per millisecond until plateau is reached. | |
80 int prev_error = kExpectedBitrate; | |
81 rtc::Optional<uint32_t> bitrate; | |
82 while (++now_ms < 10000) { | |
83 stats_.Update(1000, now_ms); | |
84 bitrate = stats_.Rate(now_ms); | |
85 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
86 int error = kExpectedBitrate - *bitrate; | |
87 error = std::abs(error); | |
88 // Expect the estimation error to decrease as the window is extended. | |
89 EXPECT_LE(error, prev_error + 1); | |
90 prev_error = error; | |
91 } | |
92 // Window filled, expect to be close to 8000000. | |
93 EXPECT_EQ(kExpectedBitrate, *bitrate); | |
94 | |
95 // 1000 bytes per millisecond until 10-second mark, 8000 kbps expected. | |
96 while (++now_ms < 10000) { | |
97 stats_.Update(1000, now_ms); | |
98 bitrate = stats_.Rate(now_ms); | |
99 EXPECT_EQ(kExpectedBitrate, *bitrate); | |
100 } | |
101 | |
102 // Zero bytes per millisecond until 0 is reached. | |
103 while (++now_ms < 20000) { | |
104 stats_.Update(0, now_ms); | |
105 rtc::Optional<uint32_t> new_bitrate = stats_.Rate(now_ms); | |
106 if (static_cast<bool>(new_bitrate) && *new_bitrate != *bitrate) { | |
107 // New bitrate must be lower than previous one. | |
108 EXPECT_LT(*new_bitrate, *bitrate); | |
109 } else { | |
110 // 0 kbps expected. | |
111 EXPECT_EQ(0u, *new_bitrate); | |
112 break; | |
113 } | |
114 bitrate = new_bitrate; | |
115 } | |
116 | |
117 // Zero bytes per millisecond until 20-second mark, 0 kbps expected. | |
118 while (++now_ms < 20000) { | |
119 stats_.Update(0, now_ms); | |
120 EXPECT_EQ(0u, *stats_.Rate(now_ms)); | |
121 } | |
122 } | |
123 | |
124 TEST_F(RateStatisticsTest, ResetAfterSilence) { | |
125 int64_t now_ms = 0; | |
126 stats_.Reset(); | |
127 // Expecting 0 after init. | |
128 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
129 | |
130 const uint32_t kExpectedBitrate = 8000000; | |
131 // 1000 bytes per millisecond until the window has been filled. | |
132 int prev_error = kExpectedBitrate; | |
133 rtc::Optional<uint32_t> bitrate; | |
134 while (++now_ms < 10000) { | |
135 stats_.Update(1000, now_ms); | |
136 bitrate = stats_.Rate(now_ms); | |
137 if (bitrate) { | |
138 int error = kExpectedBitrate - *bitrate; | |
139 error = std::abs(error); | |
140 // Expect the estimation error to decrease as the window is extended. | |
141 EXPECT_LE(error, prev_error + 1); | |
142 prev_error = error; | |
143 } | |
144 } | |
145 // Window filled, expect to be close to 8000000. | |
146 EXPECT_EQ(kExpectedBitrate, *bitrate); | |
147 | |
148 now_ms += kWindowMs + 1; | |
149 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
150 stats_.Update(1000, now_ms); | |
151 ++now_ms; | |
152 stats_.Update(1000, now_ms); | |
153 // We expect two samples of 1000 bytes, and that the bitrate is measured over | |
154 // 500 ms, i.e. 2 * 8 * 1000 / 0.500 = 32000. | |
155 EXPECT_EQ(32000u, *stats_.Rate(now_ms)); | |
156 | |
157 // Reset, add the same samples again. | |
158 stats_.Reset(); | |
159 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
160 stats_.Update(1000, now_ms); | |
161 ++now_ms; | |
162 stats_.Update(1000, now_ms); | |
163 // We expect two samples of 1000 bytes, and that the bitrate is measured over | |
164 // 2 ms (window size has been reset) i.e. 2 * 8 * 1000 / 0.002 = 8000000. | |
165 EXPECT_EQ(kExpectedBitrate, *stats_.Rate(now_ms)); | |
166 } | |
167 | |
168 TEST_F(RateStatisticsTest, HandlesChangingWindowSize) { | |
169 int64_t now_ms = 0; | |
170 stats_.Reset(); | |
171 | |
172 // Sanity test window size. | |
173 EXPECT_TRUE(stats_.SetWindowSize(kWindowMs, now_ms)); | |
174 EXPECT_FALSE(stats_.SetWindowSize(kWindowMs + 1, now_ms)); | |
175 EXPECT_FALSE(stats_.SetWindowSize(0, now_ms)); | |
176 EXPECT_TRUE(stats_.SetWindowSize(1, now_ms)); | |
177 EXPECT_TRUE(stats_.SetWindowSize(kWindowMs, now_ms)); | |
178 | |
179 // Fill the buffer at a rate of 1 byte / millisecond (8 kbps). | |
180 const int kBatchSize = 10; | |
181 for (int i = 0; i <= kWindowMs; i += kBatchSize) | |
182 stats_.Update(kBatchSize, now_ms += kBatchSize); | |
183 EXPECT_EQ(static_cast<uint32_t>(8000), *stats_.Rate(now_ms)); | |
184 | |
185 // Halve the window size, rate should stay the same. | |
186 EXPECT_TRUE(stats_.SetWindowSize(kWindowMs / 2, now_ms)); | |
187 EXPECT_EQ(static_cast<uint32_t>(8000), *stats_.Rate(now_ms)); | |
188 | |
189 // Double the window size again, rate should stay the same. (As the window | |
190 // won't actually expand until new bit and bobs fall into it. | |
191 EXPECT_TRUE(stats_.SetWindowSize(kWindowMs, now_ms)); | |
192 EXPECT_EQ(static_cast<uint32_t>(8000), *stats_.Rate(now_ms)); | |
193 | |
194 // Fill the now empty half with bits it twice the rate. | |
195 for (int i = 0; i < kWindowMs / 2; i += kBatchSize) | |
196 stats_.Update(kBatchSize * 2, now_ms += kBatchSize); | |
197 | |
198 // Rate should have increase be 50%. | |
199 EXPECT_EQ(static_cast<uint32_t>((8000 * 3) / 2), *stats_.Rate(now_ms)); | |
200 } | |
201 | |
202 TEST_F(RateStatisticsTest, RespectsWindowSizeEdges) { | |
203 int64_t now_ms = 0; | |
204 stats_.Reset(); | |
205 // Expecting 0 after init. | |
206 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
207 | |
208 // One byte per ms, using one big sample. | |
209 stats_.Update(kWindowMs, now_ms); | |
210 now_ms += kWindowMs - 2; | |
211 // Shouldn't work! (Only one sample, not full window size.) | |
212 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
213 | |
214 // Window size should be full, and the single data point should be accepted. | |
215 ++now_ms; | |
216 rtc::Optional<uint32_t> bitrate = stats_.Rate(now_ms); | |
217 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
218 EXPECT_EQ(1000 * 8u, *bitrate); | |
219 | |
220 // Add another, now we have twice the bitrate. | |
221 stats_.Update(kWindowMs, now_ms); | |
222 bitrate = stats_.Rate(now_ms); | |
223 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
224 EXPECT_EQ(2 * 1000 * 8u, *bitrate); | |
225 | |
226 // Now that first sample should drop out... | |
227 now_ms += 1; | |
228 bitrate = stats_.Rate(now_ms); | |
229 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
230 EXPECT_EQ(1000 * 8u, *bitrate); | |
231 } | |
232 | |
233 TEST_F(RateStatisticsTest, HandlesZeroCounts) { | |
234 int64_t now_ms = 0; | |
235 stats_.Reset(); | |
236 // Expecting 0 after init. | |
237 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
238 | |
239 stats_.Update(kWindowMs, now_ms); | |
240 now_ms += kWindowMs - 1; | |
241 stats_.Update(0, now_ms); | |
242 rtc::Optional<uint32_t> bitrate = stats_.Rate(now_ms); | |
243 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
244 EXPECT_EQ(1000 * 8u, *bitrate); | |
245 | |
246 // Move window along so first data point falls out. | |
247 ++now_ms; | |
248 bitrate = stats_.Rate(now_ms); | |
249 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
250 EXPECT_EQ(0u, *bitrate); | |
251 | |
252 // Move window so last data point falls out. | |
253 now_ms += kWindowMs; | |
254 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
255 } | |
256 | |
257 TEST_F(RateStatisticsTest, HandlesQuietPeriods) { | |
258 int64_t now_ms = 0; | |
259 stats_.Reset(); | |
260 // Expecting 0 after init. | |
261 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
262 | |
263 stats_.Update(0, now_ms); | |
264 now_ms += kWindowMs - 1; | |
265 rtc::Optional<uint32_t> bitrate = stats_.Rate(now_ms); | |
266 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
267 EXPECT_EQ(0u, *bitrate); | |
268 | |
269 // Move window along so first data point falls out. | |
270 ++now_ms; | |
271 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms))); | |
272 | |
273 // Move window a long way out. | |
274 now_ms += 2 * kWindowMs; | |
275 stats_.Update(0, now_ms); | |
276 bitrate = stats_.Rate(now_ms); | |
277 EXPECT_TRUE(static_cast<bool>(bitrate)); | |
278 EXPECT_EQ(0u, *bitrate); | |
279 } | |
280 } // namespace | |
OLD | NEW |