diff --git a/modules/audio_coding/neteq/nack_tracker.cc b/modules/audio_coding/neteq/nack_tracker.cc index 1df07c970f..0edefa58df 100644 --- a/modules/audio_coding/neteq/nack_tracker.cc +++ b/modules/audio_coding/neteq/nack_tracker.cc @@ -43,9 +43,8 @@ NackTracker::Config::Config() { << never_nack_multiple_times; } -NackTracker::NackTracker(int nack_threshold_packets) - : nack_threshold_packets_(nack_threshold_packets), - sequence_num_last_received_rtp_(0), +NackTracker::NackTracker() + : sequence_num_last_received_rtp_(0), timestamp_last_received_rtp_(0), any_rtp_received_(false), sequence_num_last_decoded_rtp_(0), @@ -56,10 +55,6 @@ NackTracker::NackTracker(int nack_threshold_packets) NackTracker::~NackTracker() = default; -NackTracker* NackTracker::Create(int nack_threshold_packets) { - return new NackTracker(nack_threshold_packets); -} - void NackTracker::UpdateSampleRate(int sample_rate_hz) { RTC_DCHECK_GT(sample_rate_hz, 0); sample_rate_khz_ = sample_rate_hz / 1000; @@ -120,33 +115,10 @@ absl::optional NackTracker::GetSamplesPerPacket( void NackTracker::UpdateList(uint16_t sequence_number_current_received_rtp, uint32_t timestamp_current_received_rtp) { - // Some of the packets which were considered late, now are considered missing. - ChangeFromLateToMissing(sequence_number_current_received_rtp); - - if (IsNewerSequenceNumber(sequence_number_current_received_rtp, - sequence_num_last_received_rtp_ + 1)) - AddToList(sequence_number_current_received_rtp, - timestamp_current_received_rtp); -} - -void NackTracker::ChangeFromLateToMissing( - uint16_t sequence_number_current_received_rtp) { - NackList::const_iterator lower_bound = - nack_list_.lower_bound(static_cast( - sequence_number_current_received_rtp - nack_threshold_packets_)); - - for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it) - it->second.is_missing = true; -} - -uint32_t NackTracker::EstimateTimestamp(uint16_t sequence_num, - int samples_per_packet) { - uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_; - return sequence_num_diff * samples_per_packet + timestamp_last_received_rtp_; -} - -void NackTracker::AddToList(uint16_t sequence_number_current_received_rtp, - uint32_t timestamp_current_received_rtp) { + if (!IsNewerSequenceNumber(sequence_number_current_received_rtp, + sequence_num_last_received_rtp_ + 1)) { + return; + } RTC_DCHECK(!any_rtp_decoded_ || IsNewerSequenceNumber(sequence_number_current_received_rtp, sequence_num_last_decoded_rtp_)); @@ -157,20 +129,20 @@ void NackTracker::AddToList(uint16_t sequence_number_current_received_rtp, return; } - // Packets with sequence numbers older than `upper_bound_missing` are - // considered missing, and the rest are considered late. - uint16_t upper_bound_missing = - sequence_number_current_received_rtp - nack_threshold_packets_; - for (uint16_t n = sequence_num_last_received_rtp_ + 1; IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n) { - bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n); uint32_t timestamp = EstimateTimestamp(n, *samples_per_packet); - NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing); + NackElement nack_element(TimeToPlay(timestamp), timestamp); nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element)); } } +uint32_t NackTracker::EstimateTimestamp(uint16_t sequence_num, + int samples_per_packet) { + uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_; + return sequence_num_diff * samples_per_packet + timestamp_last_received_rtp_; +} + void NackTracker::UpdateEstimatedPlayoutTimeBy10ms() { while (!nack_list_.empty() && nack_list_.begin()->second.time_to_play_ms <= 10) @@ -260,9 +232,8 @@ std::vector NackTracker::GetNackList(int64_t round_trip_time_ms) { int64_t time_since_packet_ms = (timestamp_last_received_rtp_ - it->second.estimated_timestamp) / sample_rate_khz_; - if (it->second.is_missing && - (it->second.time_to_play_ms > round_trip_time_ms || - time_since_packet_ms + round_trip_time_ms < max_wait_ms)) + if (it->second.time_to_play_ms > round_trip_time_ms || + time_since_packet_ms + round_trip_time_ms < max_wait_ms) sequence_numbers.push_back(it->first); } if (config_.never_nack_multiple_times) { diff --git a/modules/audio_coding/neteq/nack_tracker.h b/modules/audio_coding/neteq/nack_tracker.h index 34e4de6ae6..f95aa0b490 100644 --- a/modules/audio_coding/neteq/nack_tracker.h +++ b/modules/audio_coding/neteq/nack_tracker.h @@ -31,12 +31,9 @@ // Every time 10ms audio is pulled from NetEq LastDecodedPacket() should be // called, and time-to-play is updated at that moment. // -// If packet N is received, any packet prior to |N - NackThreshold| which is not -// arrived is considered lost, and should be labeled as "missing" (the size of -// the list might be limited and older packet eliminated from the list). Packets -// |N - NackThreshold|, |N - NackThreshold + 1|, ..., |N - 1| are considered -// "late." A "late" packet with sequence number K is changed to "missing" any -// time a packet with sequence number newer than |K + NackList| is arrived. +// If packet N is received, any packet prior to N which has not arrived is +// considered lost, and should be labeled as "missing" (the size of +// the list might be limited and older packet eliminated from the list). // // The NackTracker class has to know about the sample rate of the packets to // compute time-to-play. So sample rate should be set as soon as the first @@ -57,9 +54,7 @@ class NackTracker { // A limit for the size of the NACK list. static const size_t kNackListSizeLimit = 500; // 10 seconds for 20 ms frame // packets. - // Factory method. - static NackTracker* Create(int nack_threshold_packets); - + NackTracker(); ~NackTracker(); // Set a maximum for the size of the NACK list. If the last received packet @@ -93,7 +88,7 @@ class NackTracker { std::vector GetNackList(int64_t round_trip_time_ms); // Reset to default values. The NACK list is cleared. - // `nack_threshold_packets_` & `max_nack_list_size_` preserve their values. + // `max_nack_list_size_` preserves its value. void Reset(); // Returns the estimated packet loss rate in Q30, for testing only. @@ -117,12 +112,9 @@ class NackTracker { }; struct NackElement { - NackElement(int64_t initial_time_to_play_ms, - uint32_t initial_timestamp, - bool missing) + NackElement(int64_t initial_time_to_play_ms, uint32_t initial_timestamp) : time_to_play_ms(initial_time_to_play_ms), - estimated_timestamp(initial_timestamp), - is_missing(missing) {} + estimated_timestamp(initial_timestamp) {} // Estimated time (ms) left for this packet to be decoded. This estimate is // updated every time jitter buffer decodes a packet. @@ -135,10 +127,6 @@ class NackTracker { // errors, there will be a minor misestimation in time-to-play of missing // packets. This will have a very minor effect on NACK performance. uint32_t estimated_timestamp; - - // True if the packet is considered missing. Otherwise indicates packet is - // late. - bool is_missing; }; class NackListCompare { @@ -151,18 +139,10 @@ class NackTracker { typedef std::map NackList; - // Constructor. - explicit NackTracker(int nack_threshold_packets); - // This API is used only for testing to assess whether time-to-play is // computed correctly. NackList GetNackList() const; - // Given the `sequence_number_current_received_rtp` of currently received RTP, - // recognize packets which are not arrive and add to the list. - void AddToList(uint16_t sequence_number_current_received_rtp, - uint32_t timestamp_current_received_rtp); - // This function subtracts 10 ms of time-to-play for all packets in NACK list. // This is called when 10 ms elapsed with no new RTP packet decoded. void UpdateEstimatedPlayoutTimeBy10ms(); @@ -174,15 +154,11 @@ class NackTracker { uint32_t timestamp_current_received_rtp) const; // Given the `sequence_number_current_received_rtp` of currently received RTP - // update the list. That is; some packets will change from late to missing, - // some packets are inserted as missing and some inserted as late. + // update the list. Packets that are older than the received packet are added + // to the nack list. void UpdateList(uint16_t sequence_number_current_received_rtp, uint32_t timestamp_current_received_rtp); - // Packets which are considered late for too long (according to - // `nack_threshold_packets_`) are flagged as missing. - void ChangeFromLateToMissing(uint16_t sequence_number_current_received_rtp); - // Packets which have sequence number older that // `sequence_num_last_received_rtp_` - `max_nack_list_size_` are removed // from the NACK list. @@ -199,13 +175,6 @@ class NackTracker { const Config config_; - // If packet N is arrived, any packet prior to N - `nack_threshold_packets_` - // which is not arrived is considered missing, and should be in NACK list. - // Also any packet in the range of N-1 and N - `nack_threshold_packets_`, - // exclusive, which is not arrived is considered late, and should should be - // in the list of late packets. - const int nack_threshold_packets_; - // Valid if a packet is received. uint16_t sequence_num_last_received_rtp_; uint32_t timestamp_last_received_rtp_; diff --git a/modules/audio_coding/neteq/nack_tracker_unittest.cc b/modules/audio_coding/neteq/nack_tracker_unittest.cc index 9fc3ae224f..4639727cad 100644 --- a/modules/audio_coding/neteq/nack_tracker_unittest.cc +++ b/modules/audio_coding/neteq/nack_tracker_unittest.cc @@ -22,7 +22,6 @@ namespace webrtc { namespace { -const int kNackThreshold = 3; const int kSampleRateHz = 16000; const int kPacketSizeMs = 30; const uint32_t kTimestampIncrement = 480; // 30 ms. @@ -55,55 +54,31 @@ bool IsNackListCorrect(const std::vector& nack_list, } // namespace TEST(NackTrackerTest, EmptyListWhenNoPacketLoss) { - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); int seq_num = 1; uint32_t timestamp = 0; std::vector nack_list; for (int n = 0; n < 100; n++) { - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); seq_num++; timestamp += kTimestampIncrement; - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); } } -TEST(NackTrackerTest, NoNackIfReorderWithinNackThreshold) { - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); - - int seq_num = 1; - uint32_t timestamp = 0; - std::vector nack_list; - - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); - EXPECT_TRUE(nack_list.empty()); - int num_late_packets = kNackThreshold + 1; - - // Push in reverse order - while (num_late_packets > 0) { - nack->UpdateLastReceivedPacket( - seq_num + num_late_packets, - timestamp + num_late_packets * kTimestampIncrement); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); - EXPECT_TRUE(nack_list.empty()); - num_late_packets--; - } -} - TEST(NackTrackerTest, LatePacketsMovedToNackThenNackListDoesNotChange) { const uint16_t kSequenceNumberLostPackets[] = {2, 3, 4, 5, 6, 7, 8, 9}; static const int kNumAllLostPackets = sizeof(kSequenceNumberLostPackets) / sizeof(kSequenceNumberLostPackets[0]); for (int k = 0; k < 2; k++) { // Two iteration with/without wrap around. - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); uint16_t sequence_num_lost_packets[kNumAllLostPackets]; for (int n = 0; n < kNumAllLostPackets; n++) { @@ -116,27 +91,25 @@ TEST(NackTrackerTest, LatePacketsMovedToNackThenNackListDoesNotChange) { uint32_t timestamp = 0; std::vector nack_list; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1; timestamp += kTimestampIncrement * (kNumAllLostPackets + 1); - int num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold); + int num_lost_packets = std::max(0, kNumAllLostPackets); - for (int n = 0; n < kNackThreshold + 1; ++n) { - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); - EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, - num_lost_packets)); - seq_num++; - timestamp += kTimestampIncrement; - num_lost_packets++; - } + nack.UpdateLastReceivedPacket(seq_num, timestamp); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); + EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, + num_lost_packets)); + seq_num++; + timestamp += kTimestampIncrement; + num_lost_packets++; for (int n = 0; n < 100; ++n) { - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(IsNackListCorrect(nack_list, sequence_num_lost_packets, kNumAllLostPackets)); seq_num++; @@ -151,8 +124,8 @@ TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) { sizeof(kSequenceNumberLostPackets[0]); for (int k = 0; k < 2; ++k) { // Two iteration with/without wrap around. - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); uint16_t sequence_num_lost_packets[kNumAllLostPackets]; for (int n = 0; n < kNumAllLostPackets; ++n) { @@ -163,8 +136,8 @@ TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) { uint16_t seq_num = sequence_num_lost_packets[0] - 1; uint32_t timestamp = 0; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - std::vector nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + std::vector nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); size_t index_retransmitted_rtp = 0; @@ -172,16 +145,16 @@ TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) { seq_num = sequence_num_lost_packets[kNumAllLostPackets - 1] + 1; timestamp += kTimestampIncrement * (kNumAllLostPackets + 1); - size_t num_lost_packets = std::max(0, kNumAllLostPackets - kNackThreshold); + size_t num_lost_packets = kNumAllLostPackets; for (int n = 0; n < kNumAllLostPackets; ++n) { // Number of lost packets does not change for the first // |kNackThreshold + 1| packets, one is added to the list and one is // removed. Thereafter, the list shrinks every iteration. - if (n >= kNackThreshold + 1) + if (n >= 1) num_lost_packets--; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(IsNackListCorrect( nack_list, &sequence_num_lost_packets[index_retransmitted_rtp], num_lost_packets)); @@ -189,13 +162,13 @@ TEST(NackTrackerTest, ArrivedPacketsAreRemovedFromNackList) { timestamp += kTimestampIncrement; // Retransmission of a lost RTP. - nack->UpdateLastReceivedPacket( + nack.UpdateLastReceivedPacket( sequence_num_lost_packets[index_retransmitted_rtp], timestamp_retransmitted_rtp); index_retransmitted_rtp++; timestamp_retransmitted_rtp += kTimestampIncrement; - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(IsNackListCorrect( nack_list, &sequence_num_lost_packets[index_retransmitted_rtp], num_lost_packets - 1)); // One less lost packet in the list. @@ -213,8 +186,8 @@ TEST(NackTrackerTest, EstimateTimestampAndTimeToPlay) { sizeof(kLostPackets) / sizeof(kLostPackets[0]); for (int k = 0; k < 4; ++k) { - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); // Sequence number wrap around if `k` is 2 or 3; int seq_num_offset = (k < 2) ? 0 : 65531; @@ -239,23 +212,23 @@ TEST(NackTrackerTest, EstimateTimestampAndTimeToPlay) { const uint32_t first_timestamp = timestamp; // Two consecutive packets to have a correct estimate of timestamp increase. - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); seq_num++; timestamp += kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); // A packet after the last one which is supposed to be lost. seq_num = seq_num_lost_packets[kNumAllLostPackets - 1] + 1; timestamp = timestamp_lost_packets[kNumAllLostPackets - 1] + kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); - NackTracker::NackList nack_list = nack->GetNackList(); + NackTracker::NackList nack_list = nack.GetNackList(); EXPECT_EQ(static_cast(kNumAllLostPackets), nack_list.size()); // Pretend the first packet is decoded. - nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp); - nack_list = nack->GetNackList(); + nack.UpdateLastDecodedPacket(first_seq_num, first_timestamp); + nack_list = nack.GetNackList(); NackTracker::NackList::iterator it = nack_list.begin(); while (it != nack_list.end()) { @@ -269,8 +242,8 @@ TEST(NackTrackerTest, EstimateTimestampAndTimeToPlay) { // Pretend 10 ms is passed, and we had pulled audio from NetEq, it still // reports the same sequence number as decoded, time-to-play should be // updated by 10 ms. - nack->UpdateLastDecodedPacket(first_seq_num, first_timestamp); - nack_list = nack->GetNackList(); + nack.UpdateLastDecodedPacket(first_seq_num, first_timestamp); + nack_list = nack.GetNackList(); it = nack_list.begin(); while (it != nack_list.end()) { seq_num = it->first - seq_num_offset; @@ -285,77 +258,77 @@ TEST(NackTrackerTest, MissingPacketsPriorToLastDecodedRtpShouldNotBeInNackList) { for (int m = 0; m < 2; ++m) { uint16_t seq_num_offset = (m == 0) ? 0 : 65531; // Wrap around if `m` is 1. - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); // Two consecutive packets to have a correct estimate of timestamp increase. uint16_t seq_num = 0; - nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, - seq_num * kTimestampIncrement); + nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, + seq_num * kTimestampIncrement); seq_num++; - nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, - seq_num * kTimestampIncrement); + nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, + seq_num * kTimestampIncrement); // Skip 10 packets (larger than NACK threshold). const int kNumLostPackets = 10; seq_num += kNumLostPackets + 1; - nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, - seq_num * kTimestampIncrement); + nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, + seq_num * kTimestampIncrement); - const size_t kExpectedListSize = kNumLostPackets - kNackThreshold; - std::vector nack_list = nack->GetNackList(kShortRoundTripTimeMs); + const size_t kExpectedListSize = kNumLostPackets; + std::vector nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_EQ(kExpectedListSize, nack_list.size()); for (int k = 0; k < 2; ++k) { // Decoding of the first and the second arrived packets. for (int n = 0; n < kPacketSizeMs / 10; ++n) { - nack->UpdateLastDecodedPacket(seq_num_offset + k, - k * kTimestampIncrement); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastDecodedPacket(seq_num_offset + k, + k * kTimestampIncrement); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_EQ(kExpectedListSize, nack_list.size()); } } // Decoding of the last received packet. - nack->UpdateLastDecodedPacket(seq_num + seq_num_offset, - seq_num * kTimestampIncrement); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastDecodedPacket(seq_num + seq_num_offset, + seq_num * kTimestampIncrement); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); // Make sure list of late packets is also empty. To check that, push few // packets, if the late list is not empty its content will pop up in NACK // list. - for (int n = 0; n < kNackThreshold + 10; ++n) { + for (int n = 0; n < 10; ++n) { seq_num++; - nack->UpdateLastReceivedPacket(seq_num_offset + seq_num, - seq_num * kTimestampIncrement); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num_offset + seq_num, + seq_num * kTimestampIncrement); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); } } } TEST(NackTrackerTest, Reset) { - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); // Two consecutive packets to have a correct estimate of timestamp increase. uint16_t seq_num = 0; - nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); + nack.UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); seq_num++; - nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); + nack.UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); // Skip 10 packets (larger than NACK threshold). const int kNumLostPackets = 10; seq_num += kNumLostPackets + 1; - nack->UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); + nack.UpdateLastReceivedPacket(seq_num, seq_num * kTimestampIncrement); - const size_t kExpectedListSize = kNumLostPackets - kNackThreshold; - std::vector nack_list = nack->GetNackList(kShortRoundTripTimeMs); + const size_t kExpectedListSize = kNumLostPackets; + std::vector nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_EQ(kExpectedListSize, nack_list.size()); - nack->Reset(); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.Reset(); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); } @@ -363,23 +336,23 @@ TEST(NackTrackerTest, ListSizeAppliedFromBeginning) { const size_t kNackListSize = 10; for (int m = 0; m < 2; ++m) { uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if `m` is 1. - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); - nack->SetMaxNackListSize(kNackListSize); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); + nack.SetMaxNackListSize(kNackListSize); uint16_t seq_num = seq_num_offset; uint32_t timestamp = 0x12345678; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); // Packet lost more than NACK-list size limit. - uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5; + uint16_t num_lost_packets = kNackListSize + 5; seq_num += num_lost_packets + 1; timestamp += (num_lost_packets + 1) * kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); - std::vector nack_list = nack->GetNackList(kShortRoundTripTimeMs); - EXPECT_EQ(kNackListSize - kNackThreshold, nack_list.size()); + std::vector nack_list = nack.GetNackList(kShortRoundTripTimeMs); + EXPECT_EQ(kNackListSize, nack_list.size()); } } @@ -387,15 +360,15 @@ TEST(NackTrackerTest, ChangeOfListSizeAppliedAndOldElementsRemoved) { const size_t kNackListSize = 10; for (int m = 0; m < 2; ++m) { uint16_t seq_num_offset = (m == 0) ? 0 : 65525; // Wrap around if `m` is 1. - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); uint16_t seq_num = seq_num_offset; uint32_t timestamp = 0x87654321; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); // Packet lost more than NACK-list size limit. - uint16_t num_lost_packets = kNackThreshold + kNackListSize + 5; + uint16_t num_lost_packets = kNackListSize + 5; std::unique_ptr seq_num_lost(new uint16_t[num_lost_packets]); for (int n = 0; n < num_lost_packets; ++n) { @@ -404,39 +377,26 @@ TEST(NackTrackerTest, ChangeOfListSizeAppliedAndOldElementsRemoved) { ++seq_num; timestamp += (num_lost_packets + 1) * kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - size_t expected_size = num_lost_packets - kNackThreshold; + nack.UpdateLastReceivedPacket(seq_num, timestamp); + size_t expected_size = num_lost_packets; - std::vector nack_list = nack->GetNackList(kShortRoundTripTimeMs); + std::vector nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_EQ(expected_size, nack_list.size()); - nack->SetMaxNackListSize(kNackListSize); - expected_size = kNackListSize - kNackThreshold; - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.SetMaxNackListSize(kNackListSize); + expected_size = kNackListSize; + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(IsNackListCorrect( nack_list, &seq_num_lost[num_lost_packets - kNackListSize], expected_size)); - // NACK list does not change size but the content is changing. The oldest - // element is removed and one from late list is inserted. - size_t n; - for (n = 1; n <= static_cast(kNackThreshold); ++n) { - ++seq_num; - timestamp += kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); - EXPECT_TRUE(IsNackListCorrect( - nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n], - expected_size)); - } - // NACK list should shrink. - for (; n < kNackListSize; ++n) { + for (size_t n = 1; n < kNackListSize; ++n) { ++seq_num; timestamp += kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); --expected_size; - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(IsNackListCorrect( nack_list, &seq_num_lost[num_lost_packets - kNackListSize + n], expected_size)); @@ -445,28 +405,28 @@ TEST(NackTrackerTest, ChangeOfListSizeAppliedAndOldElementsRemoved) { // After this packet, NACK list should be empty. ++seq_num; timestamp += kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - nack_list = nack->GetNackList(kShortRoundTripTimeMs); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + nack_list = nack.GetNackList(kShortRoundTripTimeMs); EXPECT_TRUE(nack_list.empty()); } } TEST(NackTrackerTest, RoudTripTimeIsApplied) { const int kNackListSize = 200; - std::unique_ptr nack(NackTracker::Create(kNackThreshold)); - nack->UpdateSampleRate(kSampleRateHz); - nack->SetMaxNackListSize(kNackListSize); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); + nack.SetMaxNackListSize(kNackListSize); uint16_t seq_num = 0; uint32_t timestamp = 0x87654321; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); // Packet lost more than NACK-list size limit. - uint16_t kNumLostPackets = kNackThreshold + 5; + uint16_t kNumLostPackets = 5; seq_num += (1 + kNumLostPackets); timestamp += (1 + kNumLostPackets) * kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); // Expected time-to-play are: // kPacketSizeMs - 10, 2*kPacketSizeMs - 10, 3*kPacketSizeMs - 10, ... @@ -474,7 +434,7 @@ TEST(NackTrackerTest, RoudTripTimeIsApplied) { // sequence number: 1, 2, 3, 4, 5 // time-to-play: 20, 50, 80, 110, 140 // - std::vector nack_list = nack->GetNackList(100); + std::vector nack_list = nack.GetNackList(100); ASSERT_EQ(2u, nack_list.size()); EXPECT_EQ(4, nack_list[0]); EXPECT_EQ(5, nack_list[1]); @@ -488,40 +448,40 @@ TEST(NackTrackerTest, DoNotNackMultipleTimes) { "packet_loss_forget_factor:0.996,ms_per_loss_percent:20," "never_nack_multiple_times:true/"); const int kNackListSize = 200; - std::unique_ptr nack(NackTracker::Create(0)); - nack->UpdateSampleRate(kSampleRateHz); - nack->SetMaxNackListSize(kNackListSize); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); + nack.SetMaxNackListSize(kNackListSize); uint16_t seq_num = 0; uint32_t timestamp = 0x87654321; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); uint16_t kNumLostPackets = 3; seq_num += (1 + kNumLostPackets); timestamp += (1 + kNumLostPackets) * kTimestampIncrement; - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); - std::vector nack_list = nack->GetNackList(10); + std::vector nack_list = nack.GetNackList(10); ASSERT_EQ(3u, nack_list.size()); EXPECT_EQ(1, nack_list[0]); EXPECT_EQ(2, nack_list[1]); EXPECT_EQ(3, nack_list[2]); // When we get the nack list again, it should be empty. - std::vector nack_list2 = nack->GetNackList(10); + std::vector nack_list2 = nack.GetNackList(10); EXPECT_TRUE(nack_list2.empty()); } // Test if estimated packet loss rate is correct. TEST(NackTrackerTest, PacketLossRateCorrect) { const int kNackListSize = 200; - std::unique_ptr nack(NackTracker::Create(0)); - nack->UpdateSampleRate(kSampleRateHz); - nack->SetMaxNackListSize(kNackListSize); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); + nack.SetMaxNackListSize(kNackListSize); uint16_t seq_num = 0; uint32_t timestamp = 0x87654321; auto add_packet = [&nack, &seq_num, ×tamp] { - nack->UpdateLastReceivedPacket(seq_num, timestamp); + nack.UpdateLastReceivedPacket(seq_num, timestamp); seq_num++; timestamp += kTimestampIncrement; }; @@ -536,22 +496,22 @@ TEST(NackTrackerTest, PacketLossRateCorrect) { } // 1 << 28 is 0.25 in Q30. We expect the packet loss estimate to be within // 0.01 of that. - EXPECT_NEAR(nack->GetPacketLossRateForTest(), 1 << 28, (1 << 30) / 100); + EXPECT_NEAR(nack.GetPacketLossRateForTest(), 1 << 28, (1 << 30) / 100); } TEST(NackTrackerTest, DoNotNackAfterDtx) { const int kNackListSize = 200; - std::unique_ptr nack(NackTracker::Create(0)); - nack->UpdateSampleRate(kSampleRateHz); - nack->SetMaxNackListSize(kNackListSize); + NackTracker nack; + nack.UpdateSampleRate(kSampleRateHz); + nack.SetMaxNackListSize(kNackListSize); uint16_t seq_num = 0; uint32_t timestamp = 0x87654321; - nack->UpdateLastReceivedPacket(seq_num, timestamp); - EXPECT_TRUE(nack->GetNackList(0).empty()); + nack.UpdateLastReceivedPacket(seq_num, timestamp); + EXPECT_TRUE(nack.GetNackList(0).empty()); constexpr int kDtxPeriod = 400; - nack->UpdateLastReceivedPacket(seq_num + 2, - timestamp + kDtxPeriod * kSampleRateHz / 1000); - EXPECT_TRUE(nack->GetNackList(0).empty()); + nack.UpdateLastReceivedPacket(seq_num + 2, + timestamp + kDtxPeriod * kSampleRateHz / 1000); + EXPECT_TRUE(nack.GetNackList(0).empty()); } } // namespace webrtc diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc index ae79960305..45c52298fb 100644 --- a/modules/audio_coding/neteq/neteq_impl.cc +++ b/modules/audio_coding/neteq/neteq_impl.cc @@ -10,12 +10,12 @@ #include "modules/audio_coding/neteq/neteq_impl.h" - #include #include #include #include #include +#include #include #include @@ -514,8 +514,7 @@ void NetEqImpl::FlushBuffers() { void NetEqImpl::EnableNack(size_t max_nack_list_size) { MutexLock lock(&mutex_); if (!nack_enabled_) { - const int kNackThresholdPackets = 0; - nack_.reset(NackTracker::Create(kNackThresholdPackets)); + nack_ = std::make_unique(); nack_enabled_ = true; nack_->UpdateSampleRate(fs_hz_); }