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