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