nack_tracker_unittest.cc (20484B)
1 /* 2 * Copyright (c) 2013 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 "modules/audio_coding/neteq/nack_tracker.h" 12 13 #include <algorithm> 14 #include <cstddef> 15 #include <cstdint> 16 #include <memory> 17 #include <vector> 18 19 #include "api/field_trials.h" 20 #include "test/create_test_field_trials.h" 21 #include "test/gtest.h" 22 23 namespace webrtc { 24 namespace { 25 26 constexpr int kSampleRateHz = 16000; 27 constexpr int kPacketSizeMs = 30; 28 constexpr uint32_t kTimestampIncrement = 480; // 30 ms. 29 constexpr int64_t kShortRoundTripTimeMs = 1; 30 31 bool IsNackListCorrect(const std::vector<uint16_t>& nack_list, 32 const uint16_t* lost_sequence_numbers, 33 size_t num_lost_packets) { 34 if (nack_list.size() != num_lost_packets) 35 return false; 36 37 if (num_lost_packets == 0) 38 return true; 39 40 for (size_t k = 0; k < nack_list.size(); ++k) { 41 int seq_num = nack_list[k]; 42 bool seq_num_matched = false; 43 for (size_t n = 0; n < num_lost_packets; ++n) { 44 if (seq_num == lost_sequence_numbers[n]) { 45 seq_num_matched = true; 46 break; 47 } 48 } 49 if (!seq_num_matched) 50 return false; 51 } 52 return true; 53 } 54 55 } // namespace 56 57 TEST(NackTrackerTest, EmptyListWhenNoPacketLoss) { 58 FieldTrials field_trials = CreateTestFieldTrials(); 59 NackTracker nack(field_trials); 60 nack.UpdateSampleRate(kSampleRateHz); 61 62 int seq_num = 1; 63 uint32_t timestamp = 0; 64 65 std::vector<uint16_t> nack_list; 66 for (int n = 0; n < 100; n++) { 67 nack.UpdateLastReceivedPacket(seq_num, timestamp); 68 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 69 seq_num++; 70 timestamp += kTimestampIncrement; 71 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 72 EXPECT_TRUE(nack_list.empty()); 73 } 74 } 75 76 TEST(NackTrackerTest, LatePacketsMovedToNackThenNackListDoesNotChange) { 77 FieldTrials field_trials = CreateTestFieldTrials(); 78 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9}; 79 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / 80 sizeof(kSequenceNumberLostPackets[0]); 81 82 for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around. 83 NackTracker nack(field_trials); 84 nack.UpdateSampleRate(kSampleRateHz); 85 86 uint16_t sequence_num_lost_packets[kNumAllLostPackets]; 87 for (int n = 0; n < kNumAllLostPackets; n++) { 88 sequence_num_lost_packets[n] = 89 kSequenceNumberLostPackets[n] + 90 k * 65531; // Have wrap around in sequence numbers for |k == 1|. 91 } 92 uint16_t seq_num = sequence_num_lost_packets[0] - 1; 93 94 uint32_t timestamp = 0; 95 std::vector<uint16_t> nack_list; 96 97 nack.UpdateLastReceivedPacket(seq_num, timestamp); 98 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 99 EXPECT_TRUE(nack_list.empty()); 100 101 seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1; 102 timestamp += kTimestampIncrement * (kNumAllLostPackets + 1); 103 int num_lost_packets = std::max(0, kNumAllLostPackets); 104 105 nack.UpdateLastReceivedPacket(seq_num, timestamp); 106 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 107 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, 108 num_lost_packets)); 109 seq_num++; 110 timestamp += kTimestampIncrement; 111 num_lost_packets++; 112 113 for (int n = 0; n < 100; ++n) { 114 nack.UpdateLastReceivedPacket(seq_num, timestamp); 115 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 116 EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, 117 kNumAllLostPackets)); 118 seq_num++; 119 timestamp += kTimestampIncrement; 120 } 121 } 122 } 123 124 TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) { 125 FieldTrials field_trials = CreateTestFieldTrials(); 126 const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9}; 127 static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / 128 sizeof(kSequenceNumberLostPackets[0]); 129 130 for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around. 131 NackTracker nack(field_trials); 132 nack.UpdateSampleRate(kSampleRateHz); 133 134 uint16_t sequence_num_lost_packets[kNumAllLostPackets]; 135 for (int n = 0; n < kNumAllLostPackets; ++n) { 136 sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] + 137 k * 65531; // Wrap around for |k == 1|. 138 } 139 140 uint16_t seq_num = sequence_num_lost_packets[0] - 1; 141 uint32_t timestamp = 0; 142 143 nack.UpdateLastReceivedPacket(seq_num, timestamp); 144 std::vector<uint16_t> nack_list = nack.GetNackList(kShortRoundTripTimeMs); 145 EXPECT_TRUE(nack_list.empty()); 146 147 size_t index_retransmitted_rtp = 0; 148 uint32_t timestamp_retransmitted_rtp = timestamp + kTimestampIncrement; 149 150 seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1; 151 timestamp += kTimestampIncrement * (kNumAllLostPackets + 1); 152 size_t num_lost_packets = kNumAllLostPackets; 153 for (int n = 0; n < kNumAllLostPackets; ++n) { 154 // Number of lost packets does not change for the first 155 // |kNackThreshold + 1| packets, one is added to the list and one is 156 // removed. Thereafter, the list shrinks every iteration. 157 if (n >= 1) 158 num_lost_packets--; 159 160 nack.UpdateLastReceivedPacket(seq_num, timestamp); 161 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 162 EXPECT_TRUE(IsNackListCorrect( 163 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp], 164 num_lost_packets)); 165 seq_num++; 166 timestamp += kTimestampIncrement; 167 168 // Retransmission of a lost RTP. 169 nack.UpdateLastReceivedPacket( 170 sequence_num_lost_packets[index_retransmitted_rtp], 171 timestamp_retransmitted_rtp); 172 index_retransmitted_rtp++; 173 timestamp_retransmitted_rtp += kTimestampIncrement; 174 175 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 176 EXPECT_TRUE(IsNackListCorrect( 177 nack_list, &sequence_num_lost_packets[index_retransmitted_rtp], 178 num_lost_packets - 1)); // One less lost packet in the list. 179 } 180 ASSERT_TRUE(nack_list.empty()); 181 } 182 } 183 184 // Assess if estimation of timestamps and time-to-play is correct. Introduce all 185 // combinations that timestamps and sequence numbers might have wrap around. 186 TEST(NackTrackerTest, EstimateTimestampAndTimeToPlay) { 187 FieldTrials field_trials = CreateTestFieldTrials(); 188 const uint16_t kLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 189 9, 10, 11, 12, 13, 14, 15}; 190 static const int kNumAllLostPackets = 191 sizeof(kLostPackets) / sizeof(kLostPackets[0]); 192 193 for (int k = 0; k < 4; ++k) { 194 NackTracker nack(field_trials); 195 nack.UpdateSampleRate(kSampleRateHz); 196 197 // Sequence number wrap around if `k` is 2 or 3; 198 int seq_num_offset = (k < 2) ? 0 : 65531; 199 200 // Timestamp wrap around if `k` is 1 or 3. 201 uint32_t timestamp_offset = 202 (k & 0x1) ? static_cast<uint32_t>(0xffffffff) - 6 : 0; 203 204 uint32_t timestamp_lost_packets[kNumAllLostPackets]; 205 uint16_t seq_num_lost_packets[kNumAllLostPackets]; 206 for (int n = 0; n < kNumAllLostPackets; ++n) { 207 timestamp_lost_packets[n] = 208 timestamp_offset + kLostPackets[n] * kTimestampIncrement; 209 seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n]; 210 } 211 212 // We and to push two packets before lost burst starts. 213 uint16_t seq_num = seq_num_lost_packets[0] - 2; 214 uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement; 215 216 const uint16_t first_seq_num = seq_num; 217 const uint32_t first_timestamp = timestamp; 218 219 // Two consecutive packets to have a correct estimate of timestamp increase. 220 nack.UpdateLastReceivedPacket(seq_num, timestamp); 221 seq_num++; 222 timestamp += kTimestampIncrement; 223 nack.UpdateLastReceivedPacket(seq_num, timestamp); 224 225 // A packet after the last one which is supposed to be lost. 226 seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1; 227 timestamp = 228 timestamp_lost_packets[kNumAllLostPackets - 1] + kTimestampIncrement; 229 nack.UpdateLastReceivedPacket(seq_num, timestamp); 230 231 NackTracker::NackList nack_list = nack.GetNackList(); 232 EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size()); 233 234 // Pretend the first packet is decoded. 235 nack.UpdateLastDecodedPacket(first_seq_num, first_timestamp); 236 nack_list = nack.GetNackList(); 237 238 NackTracker::NackList::iterator it = nack_list.begin(); 239 while (it != nack_list.end()) { 240 seq_num = it->first - seq_num_offset; 241 int index = seq_num - kLostPackets[0]; 242 EXPECT_EQ(timestamp_lost_packets[index], it->second.estimated_timestamp); 243 EXPECT_EQ((index + 2) * kPacketSizeMs, it->second.time_to_play_ms); 244 ++it; 245 } 246 } 247 } 248 249 TEST(NackTrackerTest, 250 MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) { 251 FieldTrials field_trials = CreateTestFieldTrials(); 252 for (int m = 0; m < 2; ++m) { 253 uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if `m` is 1. 254 NackTracker nack(field_trials); 255 nack.UpdateSampleRate(kSampleRateHz); 256 257 // Two consecutive packets to have a correct estimate of timestamp increase. 258 uint16_t seq_num = 0; 259 nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, 260 seq_num * kTimestampIncrement); 261 seq_num++; 262 nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, 263 seq_num * kTimestampIncrement); 264 265 // Skip 10 packets (larger than NACK threshold). 266 const int kNumLostPackets = 10; 267 seq_num += kNumLostPackets + 1; 268 nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, 269 seq_num * kTimestampIncrement); 270 271 const size_t kExpectedListSize = kNumLostPackets; 272 std::vector<uint16_t> nack_list = nack.GetNackList(kShortRoundTripTimeMs); 273 EXPECT_EQ(kExpectedListSize, nack_list.size()); 274 275 for (int k = 0; k < 2; ++k) { 276 // Decoding of the first and the second arrived packets. 277 for (int n = 0; n < kPacketSizeMs / 10; ++n) { 278 nack.UpdateLastDecodedPacket(seq_num_offset + k, 279 k * kTimestampIncrement); 280 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 281 EXPECT_EQ(kExpectedListSize, nack_list.size()); 282 } 283 } 284 285 // Decoding of the last received packet. 286 nack.UpdateLastDecodedPacket(seq_num + seq_num_offset, 287 seq_num * kTimestampIncrement); 288 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 289 EXPECT_TRUE(nack_list.empty()); 290 291 // Make sure list of late packets is also empty. To check that, push few 292 // packets, if the late list is not empty its content will pop up in NACK 293 // list. 294 for (int n = 0; n < 10; ++n) { 295 seq_num++; 296 nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, 297 seq_num * kTimestampIncrement); 298 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 299 EXPECT_TRUE(nack_list.empty()); 300 } 301 } 302 } 303 304 TEST(NackTrackerTest, Reset) { 305 FieldTrials field_trials = CreateTestFieldTrials(); 306 NackTracker nack(field_trials); 307 nack.UpdateSampleRate(kSampleRateHz); 308 309 // Two consecutive packets to have a correct estimate of timestamp increase. 310 uint16_t seq_num = 0; 311 nack.UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); 312 seq_num++; 313 nack.UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); 314 315 // Skip 10 packets (larger than NACK threshold). 316 const int kNumLostPackets = 10; 317 seq_num += kNumLostPackets + 1; 318 nack.UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); 319 320 const size_t kExpectedListSize = kNumLostPackets; 321 std::vector<uint16_t> nack_list = nack.GetNackList(kShortRoundTripTimeMs); 322 EXPECT_EQ(kExpectedListSize, nack_list.size()); 323 324 nack.Reset(); 325 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 326 EXPECT_TRUE(nack_list.empty()); 327 } 328 329 TEST(NackTrackerTest, ListSizeAppliedFromBeginning) { 330 FieldTrials field_trials = CreateTestFieldTrials(); 331 const size_t kNackListSize = 10; 332 for (int m = 0; m < 2; ++m) { 333 uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if `m` is 1. 334 NackTracker nack(field_trials); 335 nack.UpdateSampleRate(kSampleRateHz); 336 nack.SetMaxNackListSize(kNackListSize); 337 338 uint16_t seq_num = seq_num_offset; 339 uint32_t timestamp = 0x12345678; 340 nack.UpdateLastReceivedPacket(seq_num, timestamp); 341 342 // Packet lost more than NACK-list size limit. 343 uint16_t num_lost_packets = kNackListSize + 5; 344 345 seq_num += num_lost_packets + 1; 346 timestamp += (num_lost_packets + 1) * kTimestampIncrement; 347 nack.UpdateLastReceivedPacket(seq_num, timestamp); 348 349 std::vector<uint16_t> nack_list = nack.GetNackList(kShortRoundTripTimeMs); 350 EXPECT_EQ(kNackListSize, nack_list.size()); 351 } 352 } 353 354 TEST(NackTrackerTest, ChangeOfListSizeAppliedAndOldElementsRemoved) { 355 FieldTrials field_trials = CreateTestFieldTrials(); 356 const size_t kNackListSize = 10; 357 for (int m = 0; m < 2; ++m) { 358 uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if `m` is 1. 359 NackTracker nack(field_trials); 360 nack.UpdateSampleRate(kSampleRateHz); 361 362 uint16_t seq_num = seq_num_offset; 363 uint32_t timestamp = 0x87654321; 364 nack.UpdateLastReceivedPacket(seq_num, timestamp); 365 366 // Packet lost more than NACK-list size limit. 367 uint16_t num_lost_packets = kNackListSize + 5; 368 369 std::unique_ptr<uint16_t[]> seq_num_lost(new uint16_t[num_lost_packets]); 370 for (int n = 0; n < num_lost_packets; ++n) { 371 seq_num_lost[n] = ++seq_num; 372 } 373 374 ++seq_num; 375 timestamp += (num_lost_packets + 1) * kTimestampIncrement; 376 nack.UpdateLastReceivedPacket(seq_num, timestamp); 377 size_t expected_size = num_lost_packets; 378 379 std::vector<uint16_t> nack_list = nack.GetNackList(kShortRoundTripTimeMs); 380 EXPECT_EQ(expected_size, nack_list.size()); 381 382 nack.SetMaxNackListSize(kNackListSize); 383 expected_size = kNackListSize; 384 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 385 EXPECT_TRUE(IsNackListCorrect( 386 nack_list, &seq_num_lost[num_lost_packets - kNackListSize], 387 expected_size)); 388 389 // NACK list should shrink. 390 for (size_t n = 1; n < kNackListSize; ++n) { 391 ++seq_num; 392 timestamp += kTimestampIncrement; 393 nack.UpdateLastReceivedPacket(seq_num, timestamp); 394 --expected_size; 395 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 396 EXPECT_TRUE(IsNackListCorrect( 397 nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n], 398 expected_size)); 399 } 400 401 // After this packet, NACK list should be empty. 402 ++seq_num; 403 timestamp += kTimestampIncrement; 404 nack.UpdateLastReceivedPacket(seq_num, timestamp); 405 nack_list = nack.GetNackList(kShortRoundTripTimeMs); 406 EXPECT_TRUE(nack_list.empty()); 407 } 408 } 409 410 TEST(NackTrackerTest, RoudTripTimeIsApplied) { 411 FieldTrials field_trials = CreateTestFieldTrials(); 412 const int kNackListSize = 200; 413 NackTracker nack(field_trials); 414 nack.UpdateSampleRate(kSampleRateHz); 415 nack.SetMaxNackListSize(kNackListSize); 416 417 uint16_t seq_num = 0; 418 uint32_t timestamp = 0x87654321; 419 nack.UpdateLastReceivedPacket(seq_num, timestamp); 420 421 // Packet lost more than NACK-list size limit. 422 uint16_t kNumLostPackets = 5; 423 424 seq_num += (1 + kNumLostPackets); 425 timestamp += (1 + kNumLostPackets) * kTimestampIncrement; 426 nack.UpdateLastReceivedPacket(seq_num, timestamp); 427 428 // Expected time-to-play are: 429 // kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ... 430 // 431 // sequence number: 1, 2, 3, 4, 5 432 // time-to-play: 20, 50, 80, 110, 140 433 // 434 std::vector<uint16_t> nack_list = nack.GetNackList(100); 435 ASSERT_EQ(2u, nack_list.size()); 436 EXPECT_EQ(4, nack_list[0]); 437 EXPECT_EQ(5, nack_list[1]); 438 } 439 440 // Set never_nack_multiple_times to true with a field trial and verify that 441 // packets are not nacked multiple times. 442 TEST(NackTrackerTest, DoNotNackMultipleTimes) { 443 FieldTrials field_trials = CreateTestFieldTrials( 444 "WebRTC-Audio-NetEqNackTrackerConfig/" 445 "packet_loss_forget_factor:0.996,ms_per_loss_percent:20," 446 "never_nack_multiple_times:true/"); 447 const int kNackListSize = 200; 448 NackTracker nack(field_trials); 449 nack.UpdateSampleRate(kSampleRateHz); 450 nack.SetMaxNackListSize(kNackListSize); 451 452 uint16_t seq_num = 0; 453 uint32_t timestamp = 0x87654321; 454 nack.UpdateLastReceivedPacket(seq_num, timestamp); 455 456 uint16_t kNumLostPackets = 3; 457 458 seq_num += (1 + kNumLostPackets); 459 timestamp += (1 + kNumLostPackets) * kTimestampIncrement; 460 nack.UpdateLastReceivedPacket(seq_num, timestamp); 461 462 std::vector<uint16_t> nack_list = nack.GetNackList(10); 463 ASSERT_EQ(3u, nack_list.size()); 464 EXPECT_EQ(1, nack_list[0]); 465 EXPECT_EQ(2, nack_list[1]); 466 EXPECT_EQ(3, nack_list[2]); 467 // When we get the nack list again, it should be empty. 468 std::vector<uint16_t> nack_list2 = nack.GetNackList(10); 469 EXPECT_TRUE(nack_list2.empty()); 470 } 471 472 // Test if estimated packet loss rate is correct. 473 TEST(NackTrackerTest, PacketLossRateCorrect) { 474 FieldTrials field_trials = CreateTestFieldTrials(); 475 const int kNackListSize = 200; 476 NackTracker nack(field_trials); 477 nack.UpdateSampleRate(kSampleRateHz); 478 nack.SetMaxNackListSize(kNackListSize); 479 uint16_t seq_num = 0; 480 uint32_t timestamp = 0x87654321; 481 auto add_packet = [&nack, &seq_num, ×tamp](bool received) { 482 if (received) { 483 nack.UpdateLastReceivedPacket(seq_num, timestamp); 484 } 485 seq_num++; 486 timestamp += kTimestampIncrement; 487 }; 488 // Add some packets, but every fourth packet is lost. 489 for (int i = 0; i < 300; i++) { 490 add_packet(true); 491 add_packet(true); 492 add_packet(true); 493 add_packet(false); 494 } 495 // 1 << 28 is 0.25 in Q30. We expect the packet loss estimate to be within 496 // 0.01 of that. 497 EXPECT_NEAR(nack.GetPacketLossRateForTest(), 1 << 28, (1 << 30) / 100); 498 } 499 500 TEST(NackTrackerTest, DoNotNackAfterDtx) { 501 FieldTrials field_trials = CreateTestFieldTrials(); 502 const int kNackListSize = 200; 503 NackTracker nack(field_trials); 504 nack.UpdateSampleRate(kSampleRateHz); 505 nack.SetMaxNackListSize(kNackListSize); 506 uint16_t seq_num = 0; 507 uint32_t timestamp = 0x87654321; 508 nack.UpdateLastReceivedPacket(seq_num, timestamp); 509 EXPECT_TRUE(nack.GetNackList(0).empty()); 510 constexpr int kDtxPeriod = 400; 511 nack.UpdateLastReceivedPacket(seq_num + 2, 512 timestamp + kDtxPeriod * kSampleRateHz / 1000); 513 EXPECT_TRUE(nack.GetNackList(0).empty()); 514 } 515 516 TEST(NackTrackerTest, DoNotNackIfLossRateIsTooHigh) { 517 FieldTrials field_trials = CreateTestFieldTrials( 518 "WebRTC-Audio-NetEqNackTrackerConfig/max_loss_rate:0.4/"); 519 const int kNackListSize = 200; 520 NackTracker nack(field_trials); 521 nack.UpdateSampleRate(kSampleRateHz); 522 nack.SetMaxNackListSize(kNackListSize); 523 uint16_t seq_num = 0; 524 uint32_t timestamp = 0x87654321; 525 auto add_packet = [&nack, &seq_num, ×tamp](bool received) { 526 if (received) { 527 nack.UpdateLastReceivedPacket(seq_num, timestamp); 528 } 529 seq_num++; 530 timestamp += kTimestampIncrement; 531 }; 532 for (int i = 0; i < 500; i++) { 533 add_packet(true); 534 add_packet(false); 535 } 536 // Expect 50% loss rate which is higher that the configured maximum 40%. 537 EXPECT_NEAR(nack.GetPacketLossRateForTest(), 1 << 29, (1 << 30) / 100); 538 EXPECT_TRUE(nack.GetNackList(0).empty()); 539 } 540 541 TEST(NackTrackerTest, OnlyNackIfRttIsValid) { 542 FieldTrials field_trials = CreateTestFieldTrials( 543 "WebRTC-Audio-NetEqNackTrackerConfig/require_valid_rtt:true/"); 544 const int kNackListSize = 200; 545 NackTracker nack(field_trials); 546 nack.UpdateSampleRate(kSampleRateHz); 547 nack.SetMaxNackListSize(kNackListSize); 548 uint16_t seq_num = 0; 549 uint32_t timestamp = 0x87654321; 550 auto add_packet = [&nack, &seq_num, ×tamp](bool received) { 551 if (received) { 552 nack.UpdateLastReceivedPacket(seq_num, timestamp); 553 } 554 seq_num++; 555 timestamp += kTimestampIncrement; 556 }; 557 add_packet(true); 558 add_packet(false); 559 add_packet(true); 560 EXPECT_TRUE(nack.GetNackList(0).empty()); 561 EXPECT_FALSE(nack.GetNackList(10).empty()); 562 } 563 564 } // namespace webrtc