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; | |
danilchap
2017/01/19 11:26:54
e.g. here this implementation might be used instea
minyue-webrtc
2017/01/19 11:28:39
right. will do
| |
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 // Test the behavior of TransportFeedbackPacketLossTracker when there is a gap | |
303 // of more than 0x4000 in sequence number, i.e., 1/4 of total sequence numbers. | |
304 // Since the sequence number is used in a circular manner, i.e., after 0xffff, | |
305 // the sequence number wraps back to 0x0000, we refer to 1/4 of total sequence | |
306 // numbers as a quadrant. In this test, e.g., three transport feedbacks are | |
307 // added, whereas the 2nd and 3rd lie in the second quadrant w.r.t. the 1st | |
308 // feedback. | |
309 TEST(TransportFeedbackPacketLossTrackerTest, SecondQuadrant) { | |
310 for (uint16_t base : kBases) { | |
311 float plr = 0.0f; // Packet-loss-rate | |
312 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
313 TransportFeedbackPacketLossTracker tracker(5, 20); | |
314 | |
315 // Expected window contents: [] -> [10011]. | |
316 AddTransportFeedbackAndValidate(&tracker, base, | |
317 {true, false, false, true, true}); | |
318 | |
319 // Window *does* get updated with inputs from quadrant #2. | |
320 // Expected window contents: [10011] -> [10011-1]. | |
321 AddTransportFeedbackAndValidate(&tracker, base + 0x4321, {true}); | |
322 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
323 EXPECT_EQ(plr, 2.0f / 6.0f); | |
324 EXPECT_EQ(cplr, 1.0f / 6.0f); | |
325 | |
326 // Correct recognition of quadrant #2: up to, but not including, base + | |
327 // 0x8000 | |
328 // Expected window contents: [10011-1] -> [10011-11]. | |
329 AddTransportFeedbackAndValidate(&tracker, base + 0x7fff, {true}); | |
330 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
331 EXPECT_EQ(plr, 2.0f / 7.0f); | |
332 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
333 } | |
334 } | |
335 | |
336 // Insertion into the third quadrant moves the base of the window. | |
337 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantMovesBase) { | |
338 for (uint16_t base : kBases) { | |
339 float plr = 0.0f; // Packet-loss-rate | |
340 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
341 TransportFeedbackPacketLossTracker tracker(5, 20); | |
342 | |
343 // Seed the test. | |
344 // Expected window contents: [] -> [10011-01]. | |
345 AddTransportFeedbackAndValidate( | |
346 &tracker, base, {true, false, false, true, true, false, true}); | |
347 | |
348 // Quadrant #3 begins at base + 0x8000. It triggers moving the window so | |
349 // that | |
350 // at least one (oldest) report shifts out of window. | |
351 // Expected window contents: [10011-01] -> [10110-01]. | |
352 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
353 {true, false, false, true}); | |
354 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
355 EXPECT_EQ(plr, 3.0f / 7.0f); | |
356 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
357 | |
358 // The base can move more than once, because the minimum quadrant-1 packets | |
359 // were dropped out of the window, and some remain. | |
360 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | |
361 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
362 EXPECT_EQ(plr, 2.0f / 7.0f); | |
363 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
364 } | |
365 } | |
366 | |
367 // After the base has moved due to insertion into the third quadrant, it is | |
368 // still possible to insert into the middle of the window and obtain the correct | |
369 // PLR and CPLR. Insertion into the middle before the max window size has been | |
370 // achieved does not cause older packets to be dropped. | |
371 TEST(TransportFeedbackPacketLossTrackerTest, InsertIntoMiddleAfterBaseMove) { | |
372 for (uint16_t base : kBases) { | |
373 float plr = 0.0f; // Packet-loss-rate | |
374 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
375 TransportFeedbackPacketLossTracker tracker(5, 20); | |
376 | |
377 // Seed the test. | |
378 // Expected window contents: [] -> [10011-01]. | |
379 AddTransportFeedbackAndValidate( | |
380 &tracker, base, {true, false, false, true, true, false, true}); | |
381 | |
382 // Expected window contents: [10011-01] -> [10110-01]. | |
383 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
384 {true, false, false, true}); | |
385 | |
386 // Inserting into the middle still works after the base has shifted. | |
387 // Expected window contents: [10110-01] -> [10110-01011-001]. | |
388 AddTransportFeedbackAndValidate(&tracker, base + 0x5000, | |
389 {true, false, false, true, false, true}); | |
390 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
391 EXPECT_EQ(plr, 6.0f / 13.0f); | |
392 EXPECT_EQ(cplr, 2.0f / 13.0f); | |
393 | |
394 // The base can keep moving after inserting into the middle. | |
395 // Expected window contents: [10110-01011-001] -> [11001-01100-111]. | |
396 AddTransportFeedbackAndValidate(&tracker, base + 0x8000 + 4, {true, true}); | |
397 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
398 EXPECT_EQ(plr, 5.0f / 13.0f); | |
399 EXPECT_EQ(cplr, 2.0f / 13.0f); | |
400 } | |
401 } | |
402 | |
403 // After moving the base of the window, the max window size is still observed. | |
404 TEST(TransportFeedbackPacketLossTrackerTest, ThirdQuadrantObservesMaxWindow) { | |
405 for (uint16_t base : kBases) { | |
406 float plr = 0.0f; // Packet-loss-rate | |
407 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
408 TransportFeedbackPacketLossTracker tracker(10, 15); | |
409 | |
410 // Expected window contents: [] -> [10011-10101]. | |
411 AddTransportFeedbackAndValidate( | |
412 &tracker, base, | |
413 {true, false, false, true, true, true, false, true, false, true}); | |
414 | |
415 // Expected window contents: [10011-10101] -> [11101-01101]. | |
416 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
417 {true, false, true}); | |
418 | |
419 // Push into middle until max window is reached. | |
420 // Expected window contents: [11101-01101] -> [11101-01100-01101]. | |
421 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | |
422 {true, false, false, false, true}); | |
423 | |
424 // Setup sanity | |
425 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
426 EXPECT_EQ(plr, 6.0f / 15.0f); | |
427 EXPECT_EQ(cplr, 2.0f / 15.0f); | |
428 | |
429 // Pushing new packets into the middle would discard older packets. | |
430 // Expected window contents: [11101-01100-01101] -> [01011-00011-01101]. | |
431 AddTransportFeedbackAndValidate(&tracker, base + 0x4000 + 5, | |
432 {true, false, true}); | |
433 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
434 EXPECT_EQ(plr, 7.0f / 15.0f); | |
435 EXPECT_EQ(cplr, 2.0f / 15.0f); | |
436 } | |
437 } | |
438 | |
439 // A new feedback in quadrant #3 might shift enough old feedbacks out of window, | |
440 // that we'd go back to an unknown PLR and CPLR. | |
441 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantThreeMovedBaseMinWindow) { | |
442 for (uint16_t base : kBases) { | |
443 float plr = 0.0f; // Packet-loss-rate | |
444 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
445 TransportFeedbackPacketLossTracker tracker(5, 20); | |
446 | |
447 // Expected window contents: [] -> [10011-10101]. | |
448 AddTransportFeedbackAndValidate( | |
449 &tracker, base, | |
450 {true, false, false, true, true, true, false, true, false, true}); | |
451 EXPECT_TRUE( | |
452 tracker.GetPacketLossRates(&plr, &cplr)); // Min window reached. | |
453 | |
454 // A new feedback in quadrant #3 might shift enough old feedbacks out of | |
455 // window, that we'd go back to an unknown PLR and CPLR. This *doesn't* | |
456 // necessarily mean all of the old ones were discarded, though. | |
457 // Expected window contents: [10011-10101] -> [0111]. | |
458 AddTransportFeedbackAndValidate(&tracker, base + 0x8006, {true, true}); | |
459 EXPECT_FALSE(tracker.GetPacketLossRates(&plr, &cplr)); | |
460 | |
461 // Inserting in the middle shows that though some of the elements were | |
462 // ejected, some were retained. | |
463 // Expected window contents: [] -> [01101-11]. | |
464 AddTransportFeedbackAndValidate(&tracker, base + 0x4000, | |
465 {true, false, true}); | |
466 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
467 EXPECT_EQ(plr, 2.0f / 7.0f); | |
468 EXPECT_EQ(cplr, 0.0f / 7.0f); | |
469 } | |
470 } | |
471 | |
472 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | |
473 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourInitiallyIgnored) { | |
474 for (uint16_t base : kBases) { | |
475 float plr = 0.0f; // Packet-loss-rate | |
476 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
477 TransportFeedbackPacketLossTracker tracker(5, 20); | |
478 | |
479 // Expected window contents: [] -> [10011]. | |
480 AddTransportFeedbackAndValidate(&tracker, base, | |
481 {true, false, false, true, true}); | |
482 | |
483 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
484 // consecutive reports). | |
485 // Expected window contents: [10011] -> [10011]. | |
486 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
487 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
488 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
489 EXPECT_EQ(plr, 2.0f / 5.0f); | |
490 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
491 } | |
492 } | |
493 } | |
494 | |
495 // Receiving a packet from quadrant #1 resets the counter for quadrant #4. | |
496 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ1) { | |
497 for (uint16_t base : kBases) { | |
498 float plr = 0.0f; // Packet-loss-rate | |
499 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
500 TransportFeedbackPacketLossTracker tracker(5, 20); | |
501 | |
502 // Expected window contents: [] -> [10011]. | |
503 AddTransportFeedbackAndValidate(&tracker, base, | |
504 {true, false, false, true, true}); | |
505 | |
506 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
507 // consecutive reports). | |
508 // Expected window contents: [10011] -> [10011]. | |
509 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
510 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
511 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
512 EXPECT_EQ(plr, 2.0f / 5.0f); | |
513 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
514 } | |
515 | |
516 // If we receive a feedback in quadrant #1, the above counter is reset. | |
517 // Expected window contents: [10011] -> [10011-1]. | |
518 AddTransportFeedbackAndValidate(&tracker, base + 0x000f, {true}); | |
519 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
520 // Note: though the feedback message reports three packets, it only gets | |
521 // counted once. | |
522 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
523 {true, false, true}); | |
524 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
525 EXPECT_EQ(plr, 2.0f / 6.0f); | |
526 EXPECT_EQ(cplr, 1.0f / 6.0f); | |
527 } | |
528 } | |
529 } | |
530 | |
531 // Receiving a packet from quadrant #2 resets the counter for quadrant #4. | |
532 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ2) { | |
533 for (uint16_t base : kBases) { | |
534 float plr = 0.0f; // Packet-loss-rate | |
535 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
536 TransportFeedbackPacketLossTracker tracker(5, 20); | |
537 | |
538 // Expected window contents: [] -> [10011]. | |
539 AddTransportFeedbackAndValidate(&tracker, base, | |
540 {true, false, false, true, true}); | |
541 | |
542 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
543 // consecutive reports). | |
544 // Expected window contents: [10011] -> [10011]. | |
545 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
546 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
547 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
548 EXPECT_EQ(plr, 2.0f / 5.0f); | |
549 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
550 } | |
551 | |
552 // If we receive a feedback in quadrant #1, the above counter is reset. | |
553 // Expected window contents: [10011] -> [10011-1]. | |
554 AddTransportFeedbackAndValidate(&tracker, base + 0x400f, {true}); | |
555 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
556 // Note: though the feedback message reports three packets, it only gets | |
557 // counted once. | |
558 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
559 {true, false, true}); | |
560 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
561 EXPECT_EQ(plr, 2.0f / 6.0f); | |
562 EXPECT_EQ(cplr, 1.0f / 6.0f); | |
563 } | |
564 } | |
565 } | |
566 | |
567 // Receiving a packet from quadrant #3 resets the counter for quadrant #4. | |
568 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourCounterResetByQ3) { | |
569 for (uint16_t base : kBases) { | |
570 float plr = 0.0f; // Packet-loss-rate | |
571 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
572 TransportFeedbackPacketLossTracker tracker(5, 20); | |
573 | |
574 // Expected window contents: [] -> [10011-10001]. | |
575 AddTransportFeedbackAndValidate( | |
576 &tracker, base, | |
577 {true, false, false, true, true, true, false, false, false, true}); | |
578 | |
579 // Feedbacks in quadrant #4 are discarded (up to kMaxConsecutiveOldReports | |
580 // consecutive reports). | |
581 // Expected window contents: [10011-10001] -> [10011-10001]. | |
582 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
583 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, {true, true}); | |
584 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
585 EXPECT_EQ(plr, 5.0f / 10.0f); | |
586 EXPECT_EQ(cplr, 3.0f / 10.0f); | |
587 } | |
588 | |
589 // If we receive a feedback in quadrant #1, the above counter is reset. | |
590 // Expected window contents: [10011-10001] -> [11100-01111]. | |
591 AddTransportFeedbackAndValidate(&tracker, base + 0x8000, | |
592 {true, true, true}); | |
593 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
594 // Note: though the feedback message reports three packets, it only gets | |
595 // counted once. | |
596 AddTransportFeedbackAndValidate(&tracker, base + 0xc000 + 10, | |
597 {true, false, true}); | |
598 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
599 EXPECT_EQ(plr, 3.0f / 10.0f); | |
600 EXPECT_EQ(cplr, 2.0f / 10.0f); | |
601 } | |
602 } | |
603 } | |
604 | |
605 // Quadrant four reports ignored for up to kMaxConsecutiveOldReports times. | |
606 // After that, the window is reset. | |
607 TEST(TransportFeedbackPacketLossTrackerTest, QuadrantFourReset) { | |
608 for (uint16_t base : kBases) { | |
609 float plr = 0.0f; // Packet-loss-rate | |
610 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
611 TransportFeedbackPacketLossTracker tracker(5, 20); | |
612 | |
613 // Expected window contents: [] -> [10011-10001]. | |
614 AddTransportFeedbackAndValidate( | |
615 &tracker, base, | |
616 {true, false, false, true, true, true, false, false, false, true}); | |
617 | |
618 // The first kMaxConsecutiveOldReports quadrant #4 reports are ignored. | |
619 // It doesn't matter that they consist of multiple packets - each report | |
620 // is only counted once. | |
621 for (size_t i = 0; i < kMaxConsecutiveOldReports; i++) { | |
622 // Expected window contents: [10011-10001] -> [10011-10001]. | |
623 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
624 {true, true, false, true}); | |
625 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
626 EXPECT_EQ(plr, 5.0f / 10.0f); | |
627 EXPECT_EQ(cplr, 3.0f / 10.0f); | |
628 } | |
629 | |
630 // One additional feedback in quadrant #4 brings us over | |
631 // kMaxConsecutiveOldReports consecutive "old" reports, resetting the | |
632 // window. | |
633 // Note: The report doesn't have to be the same as the previous ones. | |
634 // Expected window contents: [10011-10001] -> [10011]. | |
635 AddTransportFeedbackAndValidate(&tracker, base + 0xc000, | |
636 {true, false, false, true, true}); | |
637 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
638 | |
639 // The new window is not completely empty - it's been seeded with the | |
640 // packets reported in the feedback that has triggered the reset. | |
641 EXPECT_EQ(plr, 2.0f / 5.0f); | |
642 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
643 } | |
644 } | |
645 | |
646 // Feedbacks spanning multiple quadrant are treated correctly (Q1-Q2). | |
647 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ1Q2) { | |
648 for (uint16_t base : kBases) { | |
649 float plr = 0.0f; // Packet-loss-rate | |
650 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
651 TransportFeedbackPacketLossTracker tracker(5, 20); | |
652 | |
653 // Expected window contents: [] -> [10011]. | |
654 AddTransportFeedbackAndValidate(&tracker, base, | |
655 {true, false, false, true, true}); | |
656 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
657 | |
658 // A feedback with entries in both quadrant #1 and #2 gets both counted: | |
659 // Expected window contents: [10011] -> [10011-11]. | |
660 AddTransportFeedbackAndValidate(&tracker, base + 0x3fff, {true, true}); | |
661 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
662 EXPECT_EQ(plr, 2.0f / 7.0f); | |
663 EXPECT_EQ(cplr, 1.0f / 7.0f); | |
664 } | |
665 } | |
666 | |
667 // Feedbacks spanning multiple quadrant are treated correctly (Q2-Q3). | |
668 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ2Q3) { | |
669 for (uint16_t base : kBases) { | |
670 float plr = 0.0f; // Packet-loss-rate | |
671 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
672 TransportFeedbackPacketLossTracker tracker(5, 20); | |
673 | |
674 // Expected window contents: [] -> [10011-00001]. | |
675 AddTransportFeedbackAndValidate( | |
676 &tracker, base, | |
677 {true, false, false, true, true, false, false, false, false, true}); | |
678 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
679 EXPECT_EQ(plr, 6.0f / 10.0f); | |
680 EXPECT_EQ(cplr, 4.0f / 10.0f); | |
681 | |
682 // A feedback with entries in both quadrant #2 and #3 gets both counted, | |
683 // but only those from #3 trigger throwing out old entries from quadrant #1: | |
684 // Expected window contents: [10011-00001] -> [01100-00110-01]. | |
685 AddTransportFeedbackAndValidate(&tracker, base + 0x7ffe, | |
686 {true, false, false, true}); | |
687 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
688 EXPECT_EQ(plr, 7.0f / 12.0f); | |
689 EXPECT_EQ(cplr, 4.0f / 12.0f); | |
690 } | |
691 } | |
692 | |
693 // Feedbacks spanning multiple quadrant are treated correctly (Q2-Q3). | |
694 TEST(TransportFeedbackPacketLossTrackerTest, MultiQuadrantQ3Q4) { | |
695 for (uint16_t base : kBases) { | |
696 float plr = 0.0f; // Packet-loss-rate | |
697 float cplr = 0.0f; // Consecutive-packet-loss-rate | |
698 | |
699 TransportFeedbackPacketLossTracker tracker(5, 20); | |
700 | |
701 // Expected window contents: [] -> [10011-00001]. | |
702 AddTransportFeedbackAndValidate( | |
703 &tracker, base, | |
704 {true, false, false, true, true, false, false, false, false, true}); | |
705 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
706 EXPECT_EQ(plr, 6.0f / 10.0f); | |
707 EXPECT_EQ(cplr, 4.0f / 10.0f); | |
708 | |
709 // A feedback with entries in both quadrant #3 and #4 would have the entries | |
710 // from quadrant #3 shift enough quadrant #1 entries out of window, that | |
711 // by the time the #4 packets are examined, the moving baseline has made | |
712 // them into quadrant #3 packets. | |
713 // Expected window contents: [10011-00001] -> [10011]. | |
714 AddTransportFeedbackAndValidate(&tracker, base + 0xbfff, | |
715 {true, false, false, true, true}); | |
716 EXPECT_TRUE(tracker.GetPacketLossRates(&plr, &cplr)); | |
717 EXPECT_EQ(plr, 2.0f / 5.0f); | |
718 EXPECT_EQ(cplr, 1.0f / 5.0f); | |
719 } | |
720 } | |
721 | |
722 } // namespace webrtc | |
OLD | NEW |