Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(962)

Side by Side Diff: webrtc/base/rate_statistics_unittest.cc

Issue 2029593002: Update RateStatistics to handle too-little-data case. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Addressed comment Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « webrtc/base/rate_statistics.cc ('k') | webrtc/common_video/bitrate_adjuster.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 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 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 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
11 #include <algorithm> 11 #include <algorithm>
12 12
13 #include "testing/gtest/include/gtest/gtest.h" 13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "webrtc/base/rate_statistics.h" 14 #include "webrtc/base/rate_statistics.h"
15 15
16 namespace { 16 namespace {
17 17
18 using webrtc::RateStatistics; 18 using webrtc::RateStatistics;
19 19
20 const int64_t kWindowMs = 500; 20 const int64_t kWindowMs = 500;
21 21
22 class RateStatisticsTest : public ::testing::Test { 22 class RateStatisticsTest : public ::testing::Test {
23 protected: 23 protected:
24 RateStatisticsTest() : stats_(kWindowMs, 8000) {} 24 RateStatisticsTest() : stats_(kWindowMs, 8000) {}
25 RateStatistics stats_; 25 RateStatistics stats_;
26 }; 26 };
27 27
28 TEST_F(RateStatisticsTest, TestStrictMode) { 28 TEST_F(RateStatisticsTest, TestStrictMode) {
29 int64_t now_ms = 0; 29 int64_t now_ms = 0;
30 // Should be initialized to 0. 30 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms)));
31 EXPECT_EQ(0u, stats_.Rate(now_ms)); 31
32 stats_.Update(1500, now_ms); 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
33 // Expecting 1200 kbps since the window is initially kept small and grows as 39 // Expecting 1200 kbps since the window is initially kept small and grows as
34 // we have more data. 40 // we have more data.
35 EXPECT_EQ(12000000u, stats_.Rate(now_ms)); 41 stats_.Update(kPacketSize, now_ms);
42 EXPECT_EQ(kExpectedRateBps, *stats_.Rate(now_ms));
43
36 stats_.Reset(); 44 stats_.Reset();
37 // Expecting 0 after init. 45 // Expecting 0 after init.
38 EXPECT_EQ(0u, stats_.Rate(now_ms)); 46 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms)));
47
48 const int kInterval = 10;
39 for (int i = 0; i < 100000; ++i) { 49 for (int i = 0; i < 100000; ++i) {
40 if (now_ms % 10 == 0) { 50 if (i % kInterval == 0)
41 stats_.Update(1500, now_ms); 51 stats_.Update(kPacketSize, now_ms);
42 } 52
43 // Approximately 1200 kbps expected. Not exact since when packets 53 // Approximately 1200 kbps expected. Not exact since when packets
44 // are removed we will jump 10 ms to the next packet. 54 // are removed we will jump 10 ms to the next packet.
45 if (now_ms > 0 && now_ms % kWindowMs == 0) { 55 if (i > kInterval) {
46 EXPECT_NEAR(1200000u, stats_.Rate(now_ms), 22000u); 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);
47 } 62 }
48 now_ms += 1; 63 now_ms += 1;
49 } 64 }
50 now_ms += kWindowMs; 65 now_ms += kWindowMs;
51 // The window is 2 seconds. If nothing has been received for that time 66 // The window is 2 seconds. If nothing has been received for that time
52 // the estimate should be 0. 67 // the estimate should be 0.
53 EXPECT_EQ(0u, stats_.Rate(now_ms)); 68 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms)));
54 } 69 }
55 70
56 TEST_F(RateStatisticsTest, IncreasingThenDecreasingBitrate) { 71 TEST_F(RateStatisticsTest, IncreasingThenDecreasingBitrate) {
57 int64_t now_ms = 0; 72 int64_t now_ms = 0;
58 stats_.Reset(); 73 stats_.Reset();
59 // Expecting 0 after init. 74 // Expecting 0 after init.
60 uint32_t bitrate = stats_.Rate(now_ms); 75 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms)));
61 EXPECT_EQ(0u, bitrate); 76
77 stats_.Update(1000, ++now_ms);
62 const uint32_t kExpectedBitrate = 8000000; 78 const uint32_t kExpectedBitrate = 8000000;
63 // 1000 bytes per millisecond until plateau is reached. 79 // 1000 bytes per millisecond until plateau is reached.
64 int prev_error = kExpectedBitrate; 80 int prev_error = kExpectedBitrate;
81 rtc::Optional<uint32_t> bitrate;
65 while (++now_ms < 10000) { 82 while (++now_ms < 10000) {
66 stats_.Update(1000, now_ms); 83 stats_.Update(1000, now_ms);
67 bitrate = stats_.Rate(now_ms); 84 bitrate = stats_.Rate(now_ms);
68 int error = kExpectedBitrate - bitrate; 85 EXPECT_TRUE(static_cast<bool>(bitrate));
86 int error = kExpectedBitrate - *bitrate;
69 error = std::abs(error); 87 error = std::abs(error);
70 // Expect the estimation error to decrease as the window is extended. 88 // Expect the estimation error to decrease as the window is extended.
71 EXPECT_LE(error, prev_error + 1); 89 EXPECT_LE(error, prev_error + 1);
72 prev_error = error; 90 prev_error = error;
73 } 91 }
74 // Window filled, expect to be close to 8000000. 92 // Window filled, expect to be close to 8000000.
75 EXPECT_EQ(kExpectedBitrate, bitrate); 93 EXPECT_EQ(kExpectedBitrate, *bitrate);
76 94
77 // 1000 bytes per millisecond until 10-second mark, 8000 kbps expected. 95 // 1000 bytes per millisecond until 10-second mark, 8000 kbps expected.
78 while (++now_ms < 10000) { 96 while (++now_ms < 10000) {
79 stats_.Update(1000, now_ms); 97 stats_.Update(1000, now_ms);
80 bitrate = stats_.Rate(now_ms); 98 bitrate = stats_.Rate(now_ms);
81 EXPECT_EQ(kExpectedBitrate, bitrate); 99 EXPECT_EQ(kExpectedBitrate, *bitrate);
82 } 100 }
101
83 // Zero bytes per millisecond until 0 is reached. 102 // Zero bytes per millisecond until 0 is reached.
84 while (++now_ms < 20000) { 103 while (++now_ms < 20000) {
85 stats_.Update(0, now_ms); 104 stats_.Update(0, now_ms);
86 uint32_t new_bitrate = stats_.Rate(now_ms); 105 rtc::Optional<uint32_t> new_bitrate = stats_.Rate(now_ms);
87 if (new_bitrate != bitrate) { 106 if (static_cast<bool>(new_bitrate) && *new_bitrate != *bitrate) {
88 // New bitrate must be lower than previous one. 107 // New bitrate must be lower than previous one.
89 EXPECT_LT(new_bitrate, bitrate); 108 EXPECT_LT(*new_bitrate, *bitrate);
90 } else { 109 } else {
91 // 0 kbps expected. 110 // 0 kbps expected.
92 EXPECT_EQ(0u, bitrate); 111 EXPECT_EQ(0u, *new_bitrate);
93 break; 112 break;
94 } 113 }
95 bitrate = new_bitrate; 114 bitrate = new_bitrate;
96 } 115 }
116
97 // Zero bytes per millisecond until 20-second mark, 0 kbps expected. 117 // Zero bytes per millisecond until 20-second mark, 0 kbps expected.
98 while (++now_ms < 20000) { 118 while (++now_ms < 20000) {
99 stats_.Update(0, now_ms); 119 stats_.Update(0, now_ms);
100 EXPECT_EQ(0u, stats_.Rate(now_ms)); 120 EXPECT_EQ(0u, *stats_.Rate(now_ms));
101 } 121 }
102 } 122 }
103 123
104 TEST_F(RateStatisticsTest, ResetAfterSilence) { 124 TEST_F(RateStatisticsTest, ResetAfterSilence) {
105 int64_t now_ms = 0; 125 int64_t now_ms = 0;
106 stats_.Reset(); 126 stats_.Reset();
107 // Expecting 0 after init. 127 // Expecting 0 after init.
108 uint32_t bitrate = stats_.Rate(now_ms); 128 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms)));
109 EXPECT_EQ(0u, bitrate); 129
110 const uint32_t kExpectedBitrate = 8000000; 130 const uint32_t kExpectedBitrate = 8000000;
111 // 1000 bytes per millisecond until the window has been filled. 131 // 1000 bytes per millisecond until the window has been filled.
112 int prev_error = kExpectedBitrate; 132 int prev_error = kExpectedBitrate;
133 rtc::Optional<uint32_t> bitrate;
113 while (++now_ms < 10000) { 134 while (++now_ms < 10000) {
114 stats_.Update(1000, now_ms); 135 stats_.Update(1000, now_ms);
115 bitrate = stats_.Rate(now_ms); 136 bitrate = stats_.Rate(now_ms);
116 int error = kExpectedBitrate - bitrate; 137 if (bitrate) {
117 error = std::abs(error); 138 int error = kExpectedBitrate - *bitrate;
118 // Expect the estimation error to decrease as the window is extended. 139 error = std::abs(error);
119 EXPECT_LE(error, prev_error + 1); 140 // Expect the estimation error to decrease as the window is extended.
120 prev_error = error; 141 EXPECT_LE(error, prev_error + 1);
142 prev_error = error;
143 }
121 } 144 }
122 // Window filled, expect to be close to 8000000. 145 // Window filled, expect to be close to 8000000.
123 EXPECT_EQ(kExpectedBitrate, bitrate); 146 EXPECT_EQ(kExpectedBitrate, *bitrate);
124 147
125 now_ms += kWindowMs + 1; 148 now_ms += kWindowMs + 1;
126 EXPECT_EQ(0u, stats_.Rate(now_ms)); 149 EXPECT_FALSE(static_cast<bool>(stats_.Rate(now_ms)));
127 stats_.Update(1000, now_ms); 150 stats_.Update(1000, now_ms);
128 // We expect one sample of 1000 bytes, and that the bitrate is measured over 151 ++now_ms;
129 // 1 ms, i.e., 8 * 1000 / 0.001 = 8000000. 152 stats_.Update(1000, now_ms);
130 EXPECT_EQ(kExpectedBitrate, stats_.Rate(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);
131 } 279 }
132 } // namespace 280 } // namespace
OLDNEW
« no previous file with comments | « webrtc/base/rate_statistics.cc ('k') | webrtc/common_video/bitrate_adjuster.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698