OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2015 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 <limits> | |
12 #include <memory> | |
13 #include <vector> | |
14 | |
15 #include "webrtc/base/checks.h" | |
16 #include "webrtc/base/mod_ops.h" | |
17 #include "webrtc/modules/rtp_rtcp/mocks/mock_transport_feedback.h" | |
18 #include "webrtc/test/gmock.h" | |
19 #include "webrtc/test/gtest.h" | |
20 #include "webrtc/voice_engine/transport_feedback_packet_loss_tracker.h" | |
21 | |
22 using webrtc::rtcp::MockTransportFeedback; | |
23 using webrtc::rtcp::TransportFeedback; | |
24 using testing::Return; | |
25 using testing::StrictMock; | |
26 | |
27 namespace webrtc { | |
28 | |
29 namespace { | |
30 | |
31 constexpr size_t kMaxConsecutiveOldReports = 4; | |
32 | |
33 // All tests are run multiple times with various baseline sequence number, | |
34 // to weed out potential bugs with wrap-around handling. | |
35 constexpr uint16_t kBases[] = {0x0000, 0x3456, 0xc032, 0xfffe}; | |
36 | |
37 void AddTransportFeedbackAndValidate( | |
38 TransportFeedbackPacketLossTracker* tracker, | |
39 uint16_t base_sequence_num, | |
40 const std::vector<bool>& reception_status_vec) { | |
41 std::vector<TransportFeedback::StatusSymbol> statuses; | |
42 for (bool status : reception_status_vec) { | |
43 if (!status) { | |
44 statuses.push_back(TransportFeedback::StatusSymbol::kNotReceived); | |
45 } else { | |
46 // |kReceivedSmallDelta| and |kReceivedLargeDelta| make no difference to | |
47 // TransportFeedbackPacketLossTracker. So we test only one case. | |
48 statuses.push_back(TransportFeedback::StatusSymbol::kReceivedSmallDelta); | |
49 } | |
50 } | |
51 StrictMock<MockTransportFeedback> mock_feedback; | |
52 EXPECT_CALL(mock_feedback, GetBaseSequence()) | |
53 .WillOnce(Return(base_sequence_num)); | |
54 EXPECT_CALL(mock_feedback, GetStatusVector()).WillOnce(Return(statuses)); | |
55 tracker->OnReceivedTransportFeedback(mock_feedback); | |
56 tracker->Validate(); | |
57 } | |
58 | |
59 } // namespace | |
60 | |
61 // Sanity check on an empty window. | |
62 TEST(TransportFeedbackPacketLossTrackerTest, EmptyWindow) { | |
63 std::unique_ptr<TransportFeedback> feedback; | |
64 float plr = 0.0f; // Packet-loss-rate | |
65 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
66 | |
67 TransportFeedbackPacketLossTracker tracker(5, 10); | |
68 | |
69 // PLR and CPLR reported as unknown before reception of first feedback. | |
70 EXPECT_FALSE(tracker.GetPacketLossRates(&plr, &cplr)); | |
71 } | |
72 | |
73 // Sanity check on partially filled window. | |
74 TEST(TransportFeedbackPacketLossTrackerTest, PartiallyFilledWindow) { | |
75 for (uint16_t base : kBases) { | |
76 float plr = 0.0f; // Packet-loss-rate | |
77 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
78 TransportFeedbackPacketLossTracker tracker(5, 10); | |
79 | |
80 // PLR and CPLR reported as unknown before minimum window size reached. | |
81 // Expected window contents: [] -> [1001]. | |
82 AddTransportFeedbackAndValidate(&tracker, base, {true, false, false, true}); | |
83 EXPECT_FALSE(tracker.GetPacketLossRates(&plr, &cplr)); | |
84 } | |
85 } | |
86 | |
87 // Sanity check on minimum filled window. | |
88 TEST(TransportFeedbackPacketLossTrackerTest, MinimumFilledWindow) { | |
89 for (uint16_t base : kBases) { | |
90 float plr = 0.0f; // Packet-loss-rate | |
91 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
92 TransportFeedbackPacketLossTracker tracker(5, 10); | |
93 | |
94 // PLR and CPLR correctly calculated after minimum window size reached. | |
95 // Expected window contents: [] -> [10011]. | |
96 AddTransportFeedbackAndValidate(&tracker, base, | |
97 {true, false, false, true, true}); | |
98 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
99 EXPECT_EQ(plr, 2.0f / 5.0f); | |
100 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
101 } | |
102 } | |
103 | |
104 // Additional reports update PLR and CPLR. | |
105 TEST(TransportFeedbackPacketLossTrackerTest, ExtendWindow) { | |
106 for (uint16_t base : kBases) { | |
107 float plr = 0.0f; // Packet-loss-rate | |
108 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
109 TransportFeedbackPacketLossTracker tracker(5, 20); | |
110 | |
111 // Expected window contents: [] -> [10011]. | |
112 AddTransportFeedbackAndValidate(&tracker, base, | |
113 {true, false, false, true, true}); | |
114 | |
115 // Expected window contents: [10011] -> [10011-10101]. | |
116 AddTransportFeedbackAndValidate(&tracker, base + 5, | |
117 {true, false, true, false, true}); | |
118 | |
119 // Expected window contents: [10011-10101] -> [10011-10101-10001]. | |
120 AddTransportFeedbackAndValidate(&tracker, base + 10, | |
121 {true, false, false, false, true}); | |
122 | |
123 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
124 EXPECT_EQ(plr, 7.0f / 15.0f); | |
125 EXPECT_EQ(cplr, 3.0f / 15.0f); | |
126 } | |
127 } | |
128 | |
129 TEST(TransportFeedbackPacketLossTrackerTest, AllReceived) { | |
130 for (uint16_t base : kBases) { | |
131 float plr = 0.0f; // Packet-loss-rate | |
132 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
133 TransportFeedbackPacketLossTracker tracker(5, 10); | |
134 | |
135 // PLR and CPLR correctly calculated after minimum window size reached. | |
136 // Expected window contents: [] -> [11111]. | |
137 AddTransportFeedbackAndValidate(&tracker, base, | |
138 {true, true, true, true, true}); | |
139 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
140 EXPECT_EQ(plr, 0.0f); | |
141 EXPECT_EQ(cplr, 0.0f); | |
142 } | |
143 } | |
144 | |
145 TEST(TransportFeedbackPacketLossTrackerTest, AllLost) { | |
146 for (uint16_t base : kBases) { | |
147 float plr = 0.0f; // Packet-loss-rate | |
148 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
149 TransportFeedbackPacketLossTracker tracker(5, 10); | |
150 | |
151 // PLR and CPLR correctly calculated after minimum window size reached. | |
152 // Expected window contents: [] -> [00000]. | |
153 AddTransportFeedbackAndValidate(&tracker, base, | |
154 {false, false, false, false, false}); | |
155 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
156 EXPECT_EQ(plr, 5.0f / 5.0f); | |
157 EXPECT_EQ(cplr, 4.0f / 5.0f); | |
158 } | |
159 } | |
160 | |
161 // Repeated reports are ignored. | |
162 TEST(TransportFeedbackPacketLossTrackerTest, ReportRepetition) { | |
163 for (uint16_t base : kBases) { | |
164 float plr = 0.0f; // Packet-loss-rate | |
165 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
166 TransportFeedbackPacketLossTracker tracker(5, 10); | |
167 | |
168 // Expected window contents: [] -> [10011]. | |
169 AddTransportFeedbackAndValidate(&tracker, base, | |
170 {true, false, false, true, true}); | |
171 | |
172 // Repeat entire previous feedback | |
173 // Expected window contents: [10011] -> [10011]. | |
174 AddTransportFeedbackAndValidate(&tracker, base, | |
175 {true, false, false, true, true}); | |
176 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
177 EXPECT_EQ(plr, 2.0f / 5.0f); | |
178 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
179 } | |
180 } | |
181 | |
182 // Report overlap. | |
183 TEST(TransportFeedbackPacketLossTrackerTest, ReportOverlap) { | |
184 for (uint16_t base : kBases) { | |
185 float plr = 0.0f; // Packet-loss-rate | |
186 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
187 TransportFeedbackPacketLossTracker tracker(5, 10); | |
188 | |
189 // Expected window contents: [] -> [10011]. | |
190 AddTransportFeedbackAndValidate(&tracker, base, | |
191 {true, false, false, true, true}); | |
192 | |
193 // Expected window contents: [10011] -> [10011-01]. | |
194 AddTransportFeedbackAndValidate(&tracker, base + 3, | |
195 {true, true, false, true}); | |
196 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
197 EXPECT_EQ(plr, 3.0f / 7.0f); | |
198 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
199 } | |
200 } | |
201 | |
202 // Report conflict. | |
203 TEST(TransportFeedbackPacketLossTrackerTest, ReportConflict) { | |
204 for (uint16_t base : kBases) { | |
205 float plr = 0.0f; // Packet-loss-rate | |
206 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
207 TransportFeedbackPacketLossTracker tracker(5, 10); | |
208 | |
209 // Expected window contents: [] -> [01001]. | |
210 AddTransportFeedbackAndValidate(&tracker, base, | |
211 {false, true, false, false, true}); | |
212 | |
213 // Expected window contents: [01001] -> [11101]. | |
214 // While false->true will be applied, true -> false will be ignored. | |
215 AddTransportFeedbackAndValidate(&tracker, base, {true, false, true}); | |
216 | |
217 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
218 EXPECT_EQ(plr, 1.0f / 5.0f); | |
219 EXPECT_EQ(cplr, 0.0f / 5.0f); | |
220 } | |
221 } | |
222 | |
223 // Skipped packets treated as unknown (not lost). | |
224 TEST(TransportFeedbackPacketLossTrackerTest, SkippedPackets) { | |
225 for (uint16_t base : kBases) { | |
226 float plr = 0.0f; // Packet-loss-rate | |
227 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
228 TransportFeedbackPacketLossTracker tracker(5, 10); | |
229 | |
230 // Expected window contents: [] -> [10011]. | |
231 AddTransportFeedbackAndValidate(&tracker, base, | |
232 {true, false, false, true, true}); | |
233 | |
234 // Expected window contents: [10011] -> [10011-101]. | |
235 AddTransportFeedbackAndValidate(&tracker, base + 100, {true, false, true}); | |
236 | |
237 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
238 EXPECT_EQ(plr, 3.0f / 8.0f); | |
239 EXPECT_EQ(cplr, 1.0f / 8.0f); | |
240 } | |
241 } | |
242 | |
243 // The window retain information up to the configured max-window-size, but | |
244 // starts discarding after that. | |
245 TEST(TransportFeedbackPacketLossTrackerTest, MaxWindowSize) { | |
246 for (uint16_t base : kBases) { | |
247 float plr = 0.0f; // Packet-loss-rate | |
248 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
249 TransportFeedbackPacketLossTracker tracker(10, 10); | |
250 | |
251 // Expected window contents: [] -> [10101-00001]. | |
252 AddTransportFeedbackAndValidate( | |
253 &tracker, base, | |
254 {true, false, true, false, true, false, false, false, false, true}); | |
255 | |
256 // Up to max-window-size retained. | |
257 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
258 EXPECT_EQ(plr, 6.0f / 10.0f); | |
259 EXPECT_EQ(cplr, 3.0f / 10.0f); | |
260 | |
261 // Expected window contents: [10101-00001] -> [00001-10111]. | |
262 AddTransportFeedbackAndValidate(&tracker, base + 10, | |
263 {true, false, true, true, true}); | |
264 | |
265 // After max-window-size, older entries discarded to accommodate newer ones. | |
266 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
267 EXPECT_EQ(plr, 5.0f / 10.0f); | |
268 EXPECT_EQ(cplr, 3.0f / 10.0f); | |
269 } | |
270 } | |
271 | |
272 // Inserting into the middle of a full window works correctly. | |
273 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddle) { | |
274 for (uint16_t base : kBases) { | |
275 float plr = 0.0f; // Packet-loss-rate | |
276 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
277 TransportFeedbackPacketLossTracker tracker(10, 10); | |
278 | |
279 // Expected window contents: [] -> [10101]. | |
280 AddTransportFeedbackAndValidate(&tracker, base, | |
281 {true, false, true, false, true}); | |
282 | |
283 // Expected window contents: [10101] -> [10101-10001]. | |
284 AddTransportFeedbackAndValidate(&tracker, base + 100, | |
285 {true, false, false, false, true}); | |
286 | |
287 // Setup sanity | |
288 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
289 EXPECT_EQ(plr, 5.0f / 10.0f); | |
290 EXPECT_EQ(cplr, 2.0f / 10.0f); | |
291 | |
292 // Insert into the middle of this full window - it discards the older data. | |
293 // Expected window contents: [10101-10001] -> [11111-10001]. | |
294 AddTransportFeedbackAndValidate(&tracker, base + 50, | |
295 {true, true, true, true, true}); | |
296 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
297 EXPECT_EQ(plr, 3.0f / 10.0f); | |
298 EXPECT_EQ(cplr, 2.0f / 10.0f); | |
299 } | |
300 } | |
301 | |
302 // Entries in the second quadrant treated like those in the first. | |
303 // The sequence number is used in a looped manner. 0xFFFF is followed by 0x0000. | |
kwiberg-webrtc
2017/01/05 02:51:12
I think the usual term is "wrapped", as in "after
minyue-webrtc
2017/01/19 10:57:55
the word was chosen to explain why "quadrant", as
| |
304 // In many tests, we divide the circle of sequence number into 4 quadrants, and | |
305 // verify the behavior of TransportFeedbackPacketLossTracker over them. | |
kwiberg-webrtc
2017/01/05 02:51:12
So each quadrant is 14 bits' worth of sequence num
minyue-webrtc
2017/01/19 10:57:55
I updated the wording here. See if that helps.
| |
306 TEST(TransportFeedbackPacketLossTrackerTest, SecondQuadrant) { | |
307 for (uint16_t base : kBases) { | |
308 float plr = 0.0f; // Packet-loss-rate | |
309 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
310 TransportFeedbackPacketLossTracker tracker(5, 20); | |
311 | |
312 // Expected window contents: [] -> [10011]. | |
313 AddTransportFeedbackAndValidate(&tracker, base, | |
314 {true, false, false, true, true}); | |
315 | |
316 // Window *does* get updated with inputs from quadrant #2. | |
317 // Expected window contents: [10011] -> [10011-1]. | |
318 AddTransportFeedbackAndValidate(&tracker, base + 0x4321, {true}); | |
319 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
320 EXPECT_EQ(plr, 2.0f / 6.0f); | |
321 EXPECT_EQ(cplr, 1.0f / 6.0f); | |
322 | |
323 // Correct recognition of quadrant #2: up to, but not including, base + | |
324 // 0x8000 | |
325 // Expected window contents: [10011-1] -> [10011-11]. | |
326 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff, {true}); | |
327 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
328 EXPECT_EQ(plr, 2.0f / 7.0f); | |
329 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
330 } | |
331 } | |
332 | |
333 // Insertion into the third quadrant moves the base of the window. | |
334 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantMovesBase) { | |
335 for (uint16_t base : kBases) { | |
336 float plr = 0.0f; // Packet-loss-rate | |
337 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
338 TransportFeedbackPacketLossTracker tracker(5, 20); | |
339 | |
340 // Seed the test. | |
341 // Expected window contents: [] -> [10011-01]. | |
342 AddTransportFeedbackAndValidate( | |
343 &tracker, base, {true, false, false, true, true, false, true}); | |
344 | |
345 // Quadrant #3 begins at base + 0x8000. It triggers moving the window so | |
346 // that | |
347 // at least one (oldest) report shifts out of window. | |
348 // Expected window contents: [10011-01] -> [10110-01]. | |
349 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
350 {true, false, false, true}); | |
351 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
352 EXPECT_EQ(plr, 3.0f / 7.0f); | |
353 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
354 | |
355 // The base can move more than once, because the minimum quadrant-1 packets | |
356 // were dropped out of the window, and some remain. | |
357 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | |
358 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
359 EXPECT_EQ(plr, 2.0f / 7.0f); | |
360 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
361 } | |
362 } | |
363 | |
364 // After the base has moved due to insertion into the third quadrant, it is | |
365 // still possible to insert into the middle of the window and obtain the correct | |
366 // PLR and CPLR. Insertion into the middle before the max window size has been | |
367 // achieved does not cause older packets to be dropped. | |
368 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMove) { | |
369 for (uint16_t base : kBases) { | |
370 float plr = 0.0f; // Packet-loss-rate | |
371 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
372 TransportFeedbackPacketLossTracker tracker(5, 20); | |
373 | |
374 // Seed the test. | |
375 // Expected window contents: [] -> [10011-01]. | |
376 AddTransportFeedbackAndValidate( | |
377 &tracker, base, {true, false, false, true, true, false, true}); | |
378 | |
379 // Expected window contents: [10011-01] -> [10110-01]. | |
380 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
381 {true, false, false, true}); | |
382 | |
383 // Inserting into the middle still works after the base has shifted. | |
384 // Expected window contents: [10110-01] -> [10110-01011-001]. | |
385 AddTransportFeedbackAndValidate(&tracker, base + 0x5000, | |
386 {true, false, false, true, false, true}); | |
387 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
388 EXPECT_EQ(plr, 6.0f / 13.0f); | |
389 EXPECT_EQ(cplr, 2.0f / 13.0f); | |
390 | |
391 // The base can keep moving after inserting into the middle. | |
392 // Expected window contents: [10110-01011-001] -> [11001-01100-111]. | |
393 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | |
394 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
395 EXPECT_EQ(plr, 5.0f / 13.0f); | |
396 EXPECT_EQ(cplr, 2.0f / 13.0f); | |
397 } | |
398 } | |
399 | |
400 // After moving the base of the window, the max window size is still observed. | |
401 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantObservesMaxWindow) { | |
kwiberg-webrtc
2017/01/05 02:51:12
Aha, who's the eagle eye, I wonder...
| |
402 for (uint16_t base : kBases) { | |
403 float plr = 0.0f; // Packet-loss-rate | |
404 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
405 TransportFeedbackPacketLossTracker tracker(10, 15); | |
406 | |
407 // Expected window contents: [] -> [10011-10101]. | |
408 AddTransportFeedbackAndValidate( | |
409 &tracker, base, | |
410 {true, false, false, true, true, true, false, true, false, true}); | |
411 | |
412 // Expected window contents: [10011-10101] -> [11101-01101]. | |
413 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
414 {true, false, true}); | |
415 | |
416 // Push into middle until max window is reached. | |
417 // Expected window contents: [11101-01101] -> [11101-01100-01101]. | |
418 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | |
419 {true, false, false, false, true}); | |
420 | |
421 // Setup sanity | |
422 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
423 EXPECT_EQ(plr, 6.0f / 15.0f); | |
424 EXPECT_EQ(cplr, 2.0f / 15.0f); | |
425 | |
426 // Pushing new packets into the middle would discard older packets. | |
427 // Expected window contents: [11101-01100-01101] -> [01011-00011-01101]. | |
428 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 5, | |
429 {true, false, true}); | |
430 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
431 EXPECT_EQ(plr, 7.0f / 15.0f); | |
432 EXPECT_EQ(cplr, 2.0f / 15.0f); | |
433 } | |
434 } | |
435 | |
436 // A new feedback in quadrant #3 might shift enough old feedbacks out of window, | |
437 // that we'd go back to an unknown PLR and CPLR. | |
438 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantThreeMovedBaseMinWindow) { | |
439 for (uint16_t base : kBases) { | |
440 float plr = 0.0f; // Packet-loss-rate | |
441 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
442 TransportFeedbackPacketLossTracker tracker(5, 20); | |
443 | |
444 // Expected window contents: [] -> [10011-10101]. | |
445 AddTransportFeedbackAndValidate( | |
446 &tracker, base, | |
447 {true, false, false, true, true, true, false, true, false, true}); | |
448 EXPECT_TRUE( | |
449 tracker.GetPacketLossRates(&plr, &cplr)); // Min window reached. | |
450 | |
451 // A new feedback in quadrant #3 might shift enough old feedbacks out of | |
452 // window, that we'd go back to an unknown PLR and CPLR. This *doesn't* | |
453 // necessarily mean all of the old ones were discarded, though. | |
454 // Expected window contents: [10011-10101] -> [0111]. | |
455 AddTransportFeedbackAndValidate(&tracker, base + 0x8006, {true, true}); | |
456 EXPECT_FALSE(tracker.GetPacketLossRates(&plr, &cplr)); | |
457 | |
458 // Inserting in the middle shows that though some of the elements were | |
459 // ejected, some were retained. | |
460 // Expected window contents: [] -> [01101-11]. | |
461 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | |
462 {true, false, true}); | |
463 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
464 EXPECT_EQ(plr, 2.0f / 7.0f); | |
465 EXPECT_EQ(cplr, 0.0f / 7.0f); | |
466 } | |
467 } | |
468 | |
469 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | |
470 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourInitiallyIgnored) { | |
471 for (uint16_t base : kBases) { | |
472 float plr = 0.0f; // Packet-loss-rate | |
473 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
474 TransportFeedbackPacketLossTracker tracker(5, 20); | |
475 | |
476 // Expected window contents: [] -> [10011]. | |
477 AddTransportFeedbackAndValidate(&tracker, base, | |
478 {true, false, false, true, true}); | |
479 | |
480 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
481 // consecutive reports). | |
482 // Expected window contents: [10011] -> [10011]. | |
483 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
484 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
485 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
486 EXPECT_EQ(plr, 2.0f / 5.0f); | |
487 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
488 } | |
489 } | |
490 } | |
491 | |
492 // Receiving a packet from quadrant #1 resets the counter for quadrant #4. | |
493 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ1) { | |
494 for (uint16_t base : kBases) { | |
495 float plr = 0.0f; // Packet-loss-rate | |
496 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
497 TransportFeedbackPacketLossTracker tracker(5, 20); | |
498 | |
499 // Expected window contents: [] -> [10011]. | |
500 AddTransportFeedbackAndValidate(&tracker, base, | |
501 {true, false, false, true, true}); | |
502 | |
503 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
504 // consecutive reports). | |
505 // Expected window contents: [10011] -> [10011]. | |
506 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
507 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
508 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
509 EXPECT_EQ(plr, 2.0f / 5.0f); | |
510 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
511 } | |
512 | |
513 // If we receive a feedback in quadrant #1, the above counter is reset. | |
514 // Expected window contents: [10011] -> [10011-1]. | |
515 AddTransportFeedbackAndValidate(&tracker, base + 0x000f, {true}); | |
516 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
517 // Note: though the feedback message reports three packets, it only gets | |
518 // counted once. | |
519 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
520 {true, false, true}); | |
521 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
522 EXPECT_EQ(plr, 2.0f / 6.0f); | |
523 EXPECT_EQ(cplr, 1.0f / 6.0f); | |
524 } | |
525 } | |
526 } | |
527 | |
528 // Receiving a packet from quadrant #2 resets the counter for quadrant #4. | |
529 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ2) { | |
530 for (uint16_t base : kBases) { | |
531 float plr = 0.0f; // Packet-loss-rate | |
532 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
533 TransportFeedbackPacketLossTracker tracker(5, 20); | |
534 | |
535 // Expected window contents: [] -> [10011]. | |
536 AddTransportFeedbackAndValidate(&tracker, base, | |
537 {true, false, false, true, true}); | |
538 | |
539 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
540 // consecutive reports). | |
541 // Expected window contents: [10011] -> [10011]. | |
542 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
543 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
544 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
545 EXPECT_EQ(plr, 2.0f / 5.0f); | |
546 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
547 } | |
548 | |
549 // If we receive a feedback in quadrant #1, the above counter is reset. | |
550 // Expected window contents: [10011] -> [10011-1]. | |
551 AddTransportFeedbackAndValidate(&tracker, base + 0x400f, {true}); | |
552 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
553 // Note: though the feedback message reports three packets, it only gets | |
554 // counted once. | |
555 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
556 {true, false, true}); | |
557 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
558 EXPECT_EQ(plr, 2.0f / 6.0f); | |
559 EXPECT_EQ(cplr, 1.0f / 6.0f); | |
560 } | |
561 } | |
562 } | |
563 | |
564 // Receiving a packet from quadrant #3 resets the counter for quadrant #4. | |
565 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ3) { | |
566 for (uint16_t base : kBases) { | |
567 float plr = 0.0f; // Packet-loss-rate | |
568 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
569 TransportFeedbackPacketLossTracker tracker(5, 20); | |
570 | |
571 // Expected window contents: [] -> [10011-10001]. | |
572 AddTransportFeedbackAndValidate( | |
573 &tracker, base, | |
574 {true, false, false, true, true, true, false, false, false, true}); | |
575 | |
576 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
577 // consecutive reports). | |
578 // Expected window contents: [10011-10001] -> [10011-10001]. | |
579 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
580 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
581 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
582 EXPECT_EQ(plr, 5.0f / 10.0f); | |
583 EXPECT_EQ(cplr, 3.0f / 10.0f); | |
584 } | |
585 | |
586 // If we receive a feedback in quadrant #1, the above counter is reset. | |
587 // Expected window contents: [10011-10001] -> [11100-01111]. | |
588 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
589 {true, true, true}); | |
590 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
591 // Note: though the feedback message reports three packets, it only gets | |
592 // counted once. | |
593 AddTransportFeedbackAndValidate(&tracker, base + 0xc000 + 10, | |
594 {true, false, true}); | |
595 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
596 EXPECT_EQ(plr, 3.0f / 10.0f); | |
597 EXPECT_EQ(cplr, 2.0f / 10.0f); | |
598 } | |
599 } | |
600 } | |
601 | |
602 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | |
603 // After that, the window is reset. | |
604 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourReset) { | |
605 for (uint16_t base : kBases) { | |
606 float plr = 0.0f; // Packet-loss-rate | |
607 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
608 TransportFeedbackPacketLossTracker tracker(5, 20); | |
609 | |
610 // Expected window contents: [] -> [10011-10001]. | |
611 AddTransportFeedbackAndValidate( | |
612 &tracker, base, | |
613 {true, false, false, true, true, true, false, false, false, true}); | |
614 | |
615 // The first kMaxConsecutiveOldReports quadrant #4 reports are ignored. | |
616 // It doesn't matter that they consist of multiple packets - each report | |
617 // is only counted once. | |
618 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
619 // Expected window contents: [10011-10001] -> [10011-10001]. | |
620 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
621 {true, true, false, true}); | |
622 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
623 EXPECT_EQ(plr, 5.0f / 10.0f); | |
624 EXPECT_EQ(cplr, 3.0f / 10.0f); | |
625 } | |
626 | |
627 // One additional feedback in quadrant #4 brings us over | |
628 // kMaxConsecutiveOldReports consecutive "old" reports, resetting the | |
629 // window. | |
630 // Note: The report doesn't have to be the same as the previous ones. | |
631 // Expected window contents: [10011-10001] -> [10011]. | |
632 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
633 {true, false, false, true, true}); | |
634 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
635 | |
636 // The new window is not completely empty - it's been seeded with the | |
637 // packets reported in the feedback that has triggered the reset. | |
638 EXPECT_EQ(plr, 2.0f / 5.0f); | |
639 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
640 } | |
641 } | |
642 | |
643 // Feedbacks spanning multiple quadrant are treated correctly (Q1-Q2). | |
644 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ1Q2) { | |
645 for (uint16_t base : kBases) { | |
646 float plr = 0.0f; // Packet-loss-rate | |
647 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
648 TransportFeedbackPacketLossTracker tracker(5, 20); | |
649 | |
650 // Expected window contents: [] -> [10011]. | |
651 AddTransportFeedbackAndValidate(&tracker, base, | |
652 {true, false, false, true, true}); | |
653 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
654 | |
655 // A feedback with entries in both quadrant #1 and #2 gets both counted: | |
656 // Expected window contents: [10011] -> [10011-11]. | |
657 AddTransportFeedbackAndValidate(&tracker, base + 0x3fff, {true, true}); | |
658 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
659 EXPECT_EQ(plr, 2.0f / 7.0f); | |
660 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
661 } | |
662 } | |
663 | |
664 // Feedbacks spanning multiple quadrant are treated correctly (Q2-Q3). | |
665 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ2Q3) { | |
666 for (uint16_t base : kBases) { | |
667 float plr = 0.0f; // Packet-loss-rate | |
668 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
669 TransportFeedbackPacketLossTracker tracker(5, 20); | |
670 | |
671 // Expected window contents: [] -> [10011-00001]. | |
672 AddTransportFeedbackAndValidate( | |
673 &tracker, base, | |
674 {true, false, false, true, true, false, false, false, false, true}); | |
675 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
676 EXPECT_EQ(plr, 6.0f / 10.0f); | |
677 EXPECT_EQ(cplr, 4.0f / 10.0f); | |
678 | |
679 // A feedback with entries in both quadrant #2 and #3 gets both counted, | |
680 // but only those from #3 trigger throwing out old entries from quadrant #1: | |
681 // Expected window contents: [10011-00001] -> [01100-00110-01]. | |
682 AddTransportFeedbackAndValidate(&tracker, base + 0x7ffe, | |
683 {true, false, false, true}); | |
684 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
685 EXPECT_EQ(plr, 7.0f / 12.0f); | |
686 EXPECT_EQ(cplr, 4.0f / 12.0f); | |
687 } | |
688 } | |
689 | |
690 // Feedbacks spanning multiple quadrant are treated correctly (Q2-Q3). | |
691 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ3Q4) { | |
692 for (uint16_t base : kBases) { | |
693 float plr = 0.0f; // Packet-loss-rate | |
694 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
695 | |
696 TransportFeedbackPacketLossTracker tracker(5, 20); | |
697 | |
698 // Expected window contents: [] -> [10011-00001]. | |
699 AddTransportFeedbackAndValidate( | |
700 &tracker, base, | |
701 {true, false, false, true, true, false, false, false, false, true}); | |
702 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
703 EXPECT_EQ(plr, 6.0f / 10.0f); | |
704 EXPECT_EQ(cplr, 4.0f / 10.0f); | |
705 | |
706 // A feedback with entries in both quadrant #3 and #4 would have the entries | |
707 // from quadrant #3 shift enough quadrant #1 entries out of window, that | |
708 // by the time the #4 packets are examined, the moving baseline has made | |
709 // them into quadrant #3 packets. | |
710 // Expected window contents: [10011-00001] -> [10011]. | |
711 AddTransportFeedbackAndValidate(&tracker, base + 0xbfff, | |
712 {true, false, false, true, true}); | |
713 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
714 EXPECT_EQ(plr, 2.0f / 5.0f); | |
715 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
716 } | |
717 } | |
718 | |
719 } // namespace webrtc | |
OLD | NEW |