17959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org/*
27959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
37959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *
47959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *  Use of this source code is governed by a BSD-style license
57959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *  that can be found in the LICENSE file in the root of the source
67959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *  tree. An additional intellectual property rights grant can be found
77959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *  in the file PATENTS.  All contributing project authors may
87959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
97959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org */
107959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1148ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin#include "webrtc/modules/audio_coding/neteq/nack.h"
127959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
137959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org#include <stdint.h>
147959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
157959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org#include <algorithm>
167959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
173c0aae17f0e3a70fe90ecc6835926b66a3de18fbkjellander@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
1800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org#include "webrtc/base/scoped_ptr.h"
197959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org#include "webrtc/typedefs.h"
203e6db2321ccdc8738c9cecbe9bdab13d4f0f658dkjellander#include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
217959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
227959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgnamespace webrtc {
237959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgnamespace {
247959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
257959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgconst int kNackThreshold = 3;
267959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgconst int kSampleRateHz = 16000;
277959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgconst int kPacketSizeMs = 30;
287959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgconst uint32_t kTimestampIncrement = 480;  // 30 ms.
2916825b1a828bb4ff40f7682040e43a239b7b8ca3pkasting@chromium.orgconst int64_t kShortRoundTripTimeMs = 1;
307959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
317959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgbool IsNackListCorrect(const std::vector<uint16_t>& nack_list,
327959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org                       const uint16_t* lost_sequence_numbers,
337959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org                       size_t num_lost_packets) {
347959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  if (nack_list.size() != num_lost_packets)
357959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    return false;
367959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
377959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  if (num_lost_packets == 0)
387959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    return true;
397959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
407959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (size_t k = 0; k < nack_list.size(); ++k) {
417959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    int seq_num = nack_list[k];
427959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    bool seq_num_matched = false;
437959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (size_t n = 0; n < num_lost_packets; ++n) {
447959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      if (seq_num == lost_sequence_numbers[n]) {
457959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        seq_num_matched = true;
467959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        break;
477959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      }
487959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
497959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    if (!seq_num_matched)
507959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      return false;
517959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
527959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  return true;
537959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
547959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
557959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}  // namespace
567959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
577959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, EmptyListWhenNoPacketLoss) {
5800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
597959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateSampleRate(kSampleRateHz);
607959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
617959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  int seq_num = 1;
627959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  uint32_t timestamp = 0;
637959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
647959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  std::vector<uint16_t> nack_list;
657959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int n = 0; n < 100; n++) {
667959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
677959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
687959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num++;
697959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += kTimestampIncrement;
707959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
717959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(nack_list.empty());
727959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
737959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
747959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
757959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, NoNackIfReorderWithinNackThreshold) {
7600b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
777959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateSampleRate(kSampleRateHz);
787959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
797959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  int seq_num = 1;
807959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  uint32_t timestamp = 0;
817959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  std::vector<uint16_t> nack_list;
827959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
837959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateLastReceivedPacket(seq_num, timestamp);
847959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack_list = nack->GetNackList(kShortRoundTripTimeMs);
857959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  EXPECT_TRUE(nack_list.empty());
867959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  int num_late_packets = kNackThreshold + 1;
877959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
887959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // Push in reverse order
897959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  while (num_late_packets > 0) {
9048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin    nack->UpdateLastReceivedPacket(
9148ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin        seq_num + num_late_packets,
9248ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin        timestamp + num_late_packets * kTimestampIncrement);
937959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
947959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(nack_list.empty());
957959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    num_late_packets--;
967959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
977959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
987959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
997959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, LatePacketsMovedToNackThenNackListDoesNotChange) {
10048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin  const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9};
1017959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
10248ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                        sizeof(kSequenceNumberLostPackets[0]);
1037959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1047959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int k = 0; k < 2; k++) {  // Two iteration with/without wrap around.
10500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
1067959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateSampleRate(kSampleRateHz);
1077959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1087959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t sequence_num_lost_packets[kNumAllLostPackets];
1097959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < kNumAllLostPackets; n++) {
11048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin      sequence_num_lost_packets[n] =
11148ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin          kSequenceNumberLostPackets[n] +
11248ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin          k * 65531;  // Have wrap around in sequence numbers for |k == 1|.
1137959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
1147959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num = sequence_num_lost_packets[0] - 1;
1157959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1167959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp = 0;
1177959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    std::vector<uint16_t> nack_list;
1187959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1197959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
1207959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
1217959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(nack_list.empty());
1227959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1237959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
1247959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
1257959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    int num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
1267959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1277959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < kNackThreshold + 1; ++n) {
1287959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(seq_num, timestamp);
1297959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
1307959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
1317959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org                                    num_lost_packets));
1327959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num++;
1337959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      timestamp += kTimestampIncrement;
1347959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      num_lost_packets++;
1357959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
1367959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1377959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < 100; ++n) {
1387959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(seq_num, timestamp);
1397959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
1407959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets,
1417959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org                                    kNumAllLostPackets));
1427959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num++;
1437959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      timestamp += kTimestampIncrement;
1447959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
1457959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
1467959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
1477959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1487959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, ArrivedPacketsAreRemovedFromNackList) {
14948ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin  const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9};
1507959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) /
15148ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                        sizeof(kSequenceNumberLostPackets[0]);
1527959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1537959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int k = 0; k < 2; ++k) {  // Two iteration with/without wrap around.
15400b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
1557959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateSampleRate(kSampleRateHz);
1567959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1577959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t sequence_num_lost_packets[kNumAllLostPackets];
1587959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < kNumAllLostPackets; ++n) {
15948ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin      sequence_num_lost_packets[n] = kSequenceNumberLostPackets[n] +
16048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                     k * 65531;  // Wrap around for |k == 1|.
1617959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
1627959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1637959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num = sequence_num_lost_packets[0] - 1;
1647959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp = 0;
1657959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1667959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
1677959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
1687959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(nack_list.empty());
1697959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1707959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    size_t index_retransmitted_rtp = 0;
1717959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp_retransmitted_rtp = timestamp + kTimestampIncrement;
1727959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1737959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1;
1747959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += kTimestampIncrement * (kNumAllLostPackets + 1);
1757959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    size_t num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold);
1767959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < kNumAllLostPackets; ++n) {
1777959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      // Number of lost packets does not change for the first
1787959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      // |kNackThreshold + 1| packets, one is added to the list and one is
1797959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      // removed. Thereafter, the list shrinks every iteration.
1807959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      if (n >= kNackThreshold + 1)
1817959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        num_lost_packets--;
1827959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1837959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(seq_num, timestamp);
1847959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
1857959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(IsNackListCorrect(
1867959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
1877959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          num_lost_packets));
1887959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num++;
1897959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      timestamp += kTimestampIncrement;
1907959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1917959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      // Retransmission of a lost RTP.
1927959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(
1937959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          sequence_num_lost_packets[index_retransmitted_rtp],
1947959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          timestamp_retransmitted_rtp);
1957959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      index_retransmitted_rtp++;
1967959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      timestamp_retransmitted_rtp += kTimestampIncrement;
1977959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
1987959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
1997959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(IsNackListCorrect(
2007959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          nack_list, &sequence_num_lost_packets[index_retransmitted_rtp],
2017959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          num_lost_packets - 1));  // One less lost packet in the list.
2027959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
2037959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    ASSERT_TRUE(nack_list.empty());
2047959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
2057959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
2067959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2077959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org// Assess if estimation of timestamps and time-to-play is correct. Introduce all
2087959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org// combinations that timestamps and sequence numbers might have wrap around.
2097959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, EstimateTimestampAndTimeToPlay) {
21048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin  const uint16_t kLostPackets[] = {2, 3,  4,  5,  6,  7,  8,
21148ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                   9, 10, 11, 12, 13, 14, 15};
21248ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin  static const int kNumAllLostPackets =
21348ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin      sizeof(kLostPackets) / sizeof(kLostPackets[0]);
2147959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2157959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int k = 0; k < 4; ++k) {
21600b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
2177959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateSampleRate(kSampleRateHz);
2187959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2197959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Sequence number wrap around if |k| is 2 or 3;
2207959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    int seq_num_offset = (k < 2) ? 0 : 65531;
2217959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2227959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Timestamp wrap around if |k| is 1 or 3.
22348ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin    uint32_t timestamp_offset =
22448ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin        (k & 0x1) ? static_cast<uint32_t>(0xffffffff) - 6 : 0;
2257959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2267959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp_lost_packets[kNumAllLostPackets];
2277959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num_lost_packets[kNumAllLostPackets];
2287959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < kNumAllLostPackets; ++n) {
22948ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin      timestamp_lost_packets[n] =
23048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin          timestamp_offset + kLostPackets[n] * kTimestampIncrement;
2317959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num_lost_packets[n] = seq_num_offset + kLostPackets[n];
2327959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
2337959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2347959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // We and to push two packets before lost burst starts.
2357959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num = seq_num_lost_packets[0] - 2;
2367959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp = timestamp_lost_packets[0] - 2 * kTimestampIncrement;
2377959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2387959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    const uint16_t first_seq_num = seq_num;
2397959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    const uint32_t first_timestamp = timestamp;
2407959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2417959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Two consecutive packets to have a correct estimate of timestamp increase.
2427959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
2437959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num++;
2447959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += kTimestampIncrement;
2457959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
2467959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2477959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // A packet after the last one which is supposed to be lost.
2487959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1;
24948ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin    timestamp =
25048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin        timestamp_lost_packets[kNumAllLostPackets - 1] + kTimestampIncrement;
2517959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
2527959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2537959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    Nack::NackList nack_list = nack->GetNackList();
2547959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_EQ(static_cast<size_t>(kNumAllLostPackets), nack_list.size());
2557959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2567959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Pretend the first packet is decoded.
2577959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
2587959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList();
2597959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2607959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    Nack::NackList::iterator it = nack_list.begin();
2617959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    while (it != nack_list.end()) {
2627959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num = it->first - seq_num_offset;
2637959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      int index = seq_num - kLostPackets[0];
2647959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_EQ(timestamp_lost_packets[index], it->second.estimated_timestamp);
2657959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_EQ((index + 2) * kPacketSizeMs, it->second.time_to_play_ms);
2667959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      ++it;
2677959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
2687959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2697959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Pretend 10 ms is passed, and we had pulled audio from NetEq, it still
2707959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // reports the same sequence number as decoded, time-to-play should be
2717959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // updated by 10 ms.
2727959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp);
2737959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList();
2747959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    it = nack_list.begin();
2757959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    while (it != nack_list.end()) {
2767959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num = it->first - seq_num_offset;
2777959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      int index = seq_num - kLostPackets[0];
2787959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_EQ((index + 2) * kPacketSizeMs - 10, it->second.time_to_play_ms);
2797959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      ++it;
2807959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
2817959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
2827959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
2837959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2847959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) {
2857959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int m = 0; m < 2; ++m) {
2867959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num_offset = (m == 0) ? 0 : 65531;  // Wrap around if |m| is 1.
28700b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
2887959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateSampleRate(kSampleRateHz);
2897959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2907959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Two consecutive packets to have a correct estimate of timestamp increase.
2917959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num = 0;
2927959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
29348ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                   seq_num * kTimestampIncrement);
2947959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num++;
2957959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
29648ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                   seq_num * kTimestampIncrement);
2977959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
2987959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Skip 10 packets (larger than NACK threshold).
2997959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    const int kNumLostPackets = 10;
3007959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num += kNumLostPackets + 1;
3017959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
30248ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                   seq_num * kTimestampIncrement);
3037959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3047959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
3057959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3067959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_EQ(kExpectedListSize, nack_list.size());
3077959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3087959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int k = 0; k < 2; ++k) {
3097959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      // Decoding of the first and the second arrived packets.
3107959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      for (int n = 0; n < kPacketSizeMs / 10; ++n) {
3117959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        nack->UpdateLastDecodedPacket(seq_num_offset + k,
3127959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org                                      k * kTimestampIncrement);
3137959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3147959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        EXPECT_EQ(kExpectedListSize, nack_list.size());
3157959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      }
3167959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
3177959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3187959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Decoding of the last received packet.
3197959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastDecodedPacket(seq_num + seq_num_offset,
32048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                  seq_num * kTimestampIncrement);
3217959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3227959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(nack_list.empty());
3237959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3247959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Make sure list of late packets is also empty. To check that, push few
3257959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // packets, if the late list is not empty its content will pop up in NACK
3267959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // list.
3277959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < kNackThreshold + 10; ++n) {
3287959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num++;
3297959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(seq_num_offset + seq_num,
33048ed930975ef7e84023044ed584c4eff914e6c9ahenrik.lundin                                     seq_num * kTimestampIncrement);
3317959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3327959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(nack_list.empty());
3337959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
3347959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
3357959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
3367959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3377959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, Reset) {
33800b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
3397959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateSampleRate(kSampleRateHz);
3407959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3417959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // Two consecutive packets to have a correct estimate of timestamp increase.
3427959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  uint16_t seq_num = 0;
3437959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
3447959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  seq_num++;
3457959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
3467959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3477959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // Skip 10 packets (larger than NACK threshold).
3487959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  const int kNumLostPackets = 10;
3497959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  seq_num += kNumLostPackets + 1;
3507959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement);
3517959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3527959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  const size_t kExpectedListSize = kNumLostPackets - kNackThreshold;
3537959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3547959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  EXPECT_EQ(kExpectedListSize, nack_list.size());
3557959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3567959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->Reset();
3577959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3587959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  EXPECT_TRUE(nack_list.empty());
3597959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
3607959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3617959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, ListSizeAppliedFromBeginning) {
3627959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  const size_t kNackListSize = 10;
3637959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int m = 0; m < 2; ++m) {
3647959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num_offset = (m == 0) ? 0 : 65525;  // Wrap around if |m| is 1.
36500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
3667959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateSampleRate(kSampleRateHz);
3677959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->SetMaxNackListSize(kNackListSize);
3687959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3697959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num = seq_num_offset;
3707959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp = 0x12345678;
3717959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
3727959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3737959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Packet lost more than NACK-list size limit.
3747959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
3757959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3767959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    seq_num += num_lost_packets + 1;
3777959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += (num_lost_packets + 1) * kTimestampIncrement;
3787959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
3797959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3807959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
3817959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_EQ(kNackListSize - kNackThreshold, nack_list.size());
3827959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
3837959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
3847959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3857959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, ChangeOfListSizeAppliedAndOldElementsRemoved) {
3867959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  const size_t kNackListSize = 10;
3877959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  for (int m = 0; m < 2; ++m) {
3887959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num_offset = (m == 0) ? 0 : 65525;  // Wrap around if |m| is 1.
38900b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
3907959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateSampleRate(kSampleRateHz);
3917959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3927959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t seq_num = seq_num_offset;
3937959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint32_t timestamp = 0x87654321;
3947959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
3957959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
3967959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // Packet lost more than NACK-list size limit.
3977959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5;
3987959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
39900b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org    rtc::scoped_ptr<uint16_t[]> seq_num_lost(new uint16_t[num_lost_packets]);
4007959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (int n = 0; n < num_lost_packets; ++n) {
4017959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      seq_num_lost[n] = ++seq_num;
4027959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
4037959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4047959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    ++seq_num;
4057959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += (num_lost_packets + 1) * kTimestampIncrement;
4067959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
4077959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    size_t expected_size = num_lost_packets - kNackThreshold;
4087959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4097959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    std::vector<uint16_t> nack_list = nack->GetNackList(kShortRoundTripTimeMs);
4107959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_EQ(expected_size, nack_list.size());
4117959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4127959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->SetMaxNackListSize(kNackListSize);
4137959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    expected_size = kNackListSize - kNackThreshold;
4147959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
4157959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(IsNackListCorrect(
4167959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        nack_list, &seq_num_lost[num_lost_packets - kNackListSize],
4177959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org        expected_size));
4187959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4197959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // NACK list does not change size but the content is changing. The oldest
4207959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // element is removed and one from late list is inserted.
4217959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    size_t n;
4227959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (n = 1; n <= static_cast<size_t>(kNackThreshold); ++n) {
4237959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      ++seq_num;
4247959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      timestamp += kTimestampIncrement;
4257959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(seq_num, timestamp);
4267959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
4277959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(IsNackListCorrect(
4287959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
4297959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          expected_size));
4307959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
4317959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4327959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // NACK list should shrink.
4337959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    for (; n < kNackListSize; ++n) {
4347959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      ++seq_num;
4357959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      timestamp += kTimestampIncrement;
4367959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack->UpdateLastReceivedPacket(seq_num, timestamp);
4377959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      --expected_size;
4387959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      nack_list = nack->GetNackList(kShortRoundTripTimeMs);
4397959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org      EXPECT_TRUE(IsNackListCorrect(
4407959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n],
4417959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org          expected_size));
4427959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    }
4437959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4447959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    // After this packet, NACK list should be empty.
4457959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    ++seq_num;
4467959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    timestamp += kTimestampIncrement;
4477959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack->UpdateLastReceivedPacket(seq_num, timestamp);
4487959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    nack_list = nack->GetNackList(kShortRoundTripTimeMs);
4497959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org    EXPECT_TRUE(nack_list.empty());
4507959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  }
4517959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
4527959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4537959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.orgTEST(NackTest, RoudTripTimeIsApplied) {
4547959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  const int kNackListSize = 200;
45500b8f6b3643332cce1ee711715f7fbb824d793cakwiberg@webrtc.org  rtc::scoped_ptr<Nack> nack(Nack::Create(kNackThreshold));
4567959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateSampleRate(kSampleRateHz);
4577959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->SetMaxNackListSize(kNackListSize);
4587959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4597959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  uint16_t seq_num = 0;
4607959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  uint32_t timestamp = 0x87654321;
4617959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateLastReceivedPacket(seq_num, timestamp);
4627959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4637959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // Packet lost more than NACK-list size limit.
4647959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  uint16_t kNumLostPackets = kNackThreshold + 5;
4657959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4667959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  seq_num += (1 + kNumLostPackets);
4677959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  timestamp += (1 + kNumLostPackets) * kTimestampIncrement;
4687959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  nack->UpdateLastReceivedPacket(seq_num, timestamp);
4697959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4707959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // Expected time-to-play are:
4717959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ...
4727959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  //
4737959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // sequence number:  1,  2,  3,   4,   5
4747959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  // time-to-play:    20, 50, 80, 110, 140
4757959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  //
4767959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  std::vector<uint16_t> nack_list = nack->GetNackList(100);
4777959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  ASSERT_EQ(2u, nack_list.size());
4787959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  EXPECT_EQ(4, nack_list[0]);
4797959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org  EXPECT_EQ(5, nack_list[1]);
4807959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}
4817959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org
4827959e16cc2da9ebf5eda61bdf0eb423d8d3006baturaj@webrtc.org}  // namespace webrtc
483