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 // 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 |