blob: 62cb2ec958af6b355bfb76325c101451988d5bfd [file] [log] [blame]
turaj@webrtc.org7959e162013-09-12 18:30:26 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
henrik.lundin91951862016-06-08 06:43:41 -070011#include "webrtc/modules/audio_coding/neteq/nack_tracker.h"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000012
13#include <assert.h> // For assert.
14
15#include <algorithm> // For std::max.
16
henrik.lundin48ed9302015-10-29 05:36:24 -070017#include "webrtc/base/checks.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010018#include "webrtc/modules/include/module_common_types.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010019#include "webrtc/system_wrappers/include/logging.h"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000020
21namespace webrtc {
turaj@webrtc.org7959e162013-09-12 18:30:26 +000022namespace {
23
24const int kDefaultSampleRateKhz = 48;
25const int kDefaultPacketSizeMs = 20;
26
27} // namespace
28
henrik.lundin91951862016-06-08 06:43:41 -070029NackTracker::NackTracker(int nack_threshold_packets)
turaj@webrtc.org7959e162013-09-12 18:30:26 +000030 : nack_threshold_packets_(nack_threshold_packets),
31 sequence_num_last_received_rtp_(0),
32 timestamp_last_received_rtp_(0),
33 any_rtp_received_(false),
34 sequence_num_last_decoded_rtp_(0),
35 timestamp_last_decoded_rtp_(0),
36 any_rtp_decoded_(false),
37 sample_rate_khz_(kDefaultSampleRateKhz),
38 samples_per_packet_(sample_rate_khz_ * kDefaultPacketSizeMs),
39 max_nack_list_size_(kNackListSizeLimit) {}
40
henrik.lundin91951862016-06-08 06:43:41 -070041NackTracker::~NackTracker() = default;
Karl Wiberg2519c452015-04-07 16:12:57 +020042
henrik.lundin91951862016-06-08 06:43:41 -070043NackTracker* NackTracker::Create(int nack_threshold_packets) {
44 return new NackTracker(nack_threshold_packets);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000045}
46
henrik.lundin91951862016-06-08 06:43:41 -070047void NackTracker::UpdateSampleRate(int sample_rate_hz) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +000048 assert(sample_rate_hz > 0);
49 sample_rate_khz_ = sample_rate_hz / 1000;
50}
51
henrik.lundin91951862016-06-08 06:43:41 -070052void NackTracker::UpdateLastReceivedPacket(uint16_t sequence_number,
53 uint32_t timestamp) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +000054 // Just record the value of sequence number and timestamp if this is the
55 // first packet.
56 if (!any_rtp_received_) {
57 sequence_num_last_received_rtp_ = sequence_number;
58 timestamp_last_received_rtp_ = timestamp;
59 any_rtp_received_ = true;
60 // If no packet is decoded, to have a reasonable estimate of time-to-play
61 // use the given values.
62 if (!any_rtp_decoded_) {
63 sequence_num_last_decoded_rtp_ = sequence_number;
64 timestamp_last_decoded_rtp_ = timestamp;
65 }
66 return;
67 }
68
69 if (sequence_number == sequence_num_last_received_rtp_)
70 return;
71
72 // Received RTP should not be in the list.
73 nack_list_.erase(sequence_number);
74
75 // If this is an old sequence number, no more action is required, return.
76 if (IsNewerSequenceNumber(sequence_num_last_received_rtp_, sequence_number))
77 return;
78
79 UpdateSamplesPerPacket(sequence_number, timestamp);
80
81 UpdateList(sequence_number);
82
83 sequence_num_last_received_rtp_ = sequence_number;
84 timestamp_last_received_rtp_ = timestamp;
85 LimitNackListSize();
86}
87
henrik.lundin91951862016-06-08 06:43:41 -070088void NackTracker::UpdateSamplesPerPacket(
89 uint16_t sequence_number_current_received_rtp,
90 uint32_t timestamp_current_received_rtp) {
henrik.lundin48ed9302015-10-29 05:36:24 -070091 uint32_t timestamp_increase =
92 timestamp_current_received_rtp - timestamp_last_received_rtp_;
93 uint16_t sequence_num_increase =
94 sequence_number_current_received_rtp - sequence_num_last_received_rtp_;
turaj@webrtc.org7959e162013-09-12 18:30:26 +000095
96 samples_per_packet_ = timestamp_increase / sequence_num_increase;
97}
98
henrik.lundin91951862016-06-08 06:43:41 -070099void NackTracker::UpdateList(uint16_t sequence_number_current_received_rtp) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000100 // Some of the packets which were considered late, now are considered missing.
101 ChangeFromLateToMissing(sequence_number_current_received_rtp);
102
103 if (IsNewerSequenceNumber(sequence_number_current_received_rtp,
104 sequence_num_last_received_rtp_ + 1))
105 AddToList(sequence_number_current_received_rtp);
106}
107
henrik.lundin91951862016-06-08 06:43:41 -0700108void NackTracker::ChangeFromLateToMissing(
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000109 uint16_t sequence_number_current_received_rtp) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700110 NackList::const_iterator lower_bound =
111 nack_list_.lower_bound(static_cast<uint16_t>(
112 sequence_number_current_received_rtp - nack_threshold_packets_));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000113
114 for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it)
115 it->second.is_missing = true;
116}
117
henrik.lundin91951862016-06-08 06:43:41 -0700118uint32_t NackTracker::EstimateTimestamp(uint16_t sequence_num) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000119 uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_;
120 return sequence_num_diff * samples_per_packet_ + timestamp_last_received_rtp_;
121}
122
henrik.lundin91951862016-06-08 06:43:41 -0700123void NackTracker::AddToList(uint16_t sequence_number_current_received_rtp) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700124 assert(!any_rtp_decoded_ ||
125 IsNewerSequenceNumber(sequence_number_current_received_rtp,
126 sequence_num_last_decoded_rtp_));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000127
128 // Packets with sequence numbers older than |upper_bound_missing| are
129 // considered missing, and the rest are considered late.
henrik.lundin48ed9302015-10-29 05:36:24 -0700130 uint16_t upper_bound_missing =
131 sequence_number_current_received_rtp - nack_threshold_packets_;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000132
133 for (uint16_t n = sequence_num_last_received_rtp_ + 1;
henrik.lundin48ed9302015-10-29 05:36:24 -0700134 IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000135 bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n);
136 uint32_t timestamp = EstimateTimestamp(n);
137 NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing);
138 nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element));
139 }
140}
141
henrik.lundin91951862016-06-08 06:43:41 -0700142void NackTracker::UpdateEstimatedPlayoutTimeBy10ms() {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000143 while (!nack_list_.empty() &&
henrik.lundin48ed9302015-10-29 05:36:24 -0700144 nack_list_.begin()->second.time_to_play_ms <= 10)
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000145 nack_list_.erase(nack_list_.begin());
146
147 for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end(); ++it)
148 it->second.time_to_play_ms -= 10;
149}
150
henrik.lundin91951862016-06-08 06:43:41 -0700151void NackTracker::UpdateLastDecodedPacket(uint16_t sequence_number,
152 uint32_t timestamp) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000153 if (IsNewerSequenceNumber(sequence_number, sequence_num_last_decoded_rtp_) ||
154 !any_rtp_decoded_) {
155 sequence_num_last_decoded_rtp_ = sequence_number;
156 timestamp_last_decoded_rtp_ = timestamp;
157 // Packets in the list with sequence numbers less than the
158 // sequence number of the decoded RTP should be removed from the lists.
159 // They will be discarded by the jitter buffer if they arrive.
henrik.lundin48ed9302015-10-29 05:36:24 -0700160 nack_list_.erase(nack_list_.begin(),
161 nack_list_.upper_bound(sequence_num_last_decoded_rtp_));
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000162
163 // Update estimated time-to-play.
164 for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end();
henrik.lundin48ed9302015-10-29 05:36:24 -0700165 ++it)
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000166 it->second.time_to_play_ms = TimeToPlay(it->second.estimated_timestamp);
167 } else {
168 assert(sequence_number == sequence_num_last_decoded_rtp_);
169
170 // Same sequence number as before. 10 ms is elapsed, update estimations for
171 // time-to-play.
172 UpdateEstimatedPlayoutTimeBy10ms();
173
174 // Update timestamp for better estimate of time-to-play, for packets which
175 // are added to NACK list later on.
176 timestamp_last_decoded_rtp_ += sample_rate_khz_ * 10;
177 }
178 any_rtp_decoded_ = true;
179}
180
henrik.lundin91951862016-06-08 06:43:41 -0700181NackTracker::NackList NackTracker::GetNackList() const {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000182 return nack_list_;
183}
184
henrik.lundin91951862016-06-08 06:43:41 -0700185void NackTracker::Reset() {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000186 nack_list_.clear();
187
188 sequence_num_last_received_rtp_ = 0;
189 timestamp_last_received_rtp_ = 0;
190 any_rtp_received_ = false;
191 sequence_num_last_decoded_rtp_ = 0;
192 timestamp_last_decoded_rtp_ = 0;
193 any_rtp_decoded_ = false;
194 sample_rate_khz_ = kDefaultSampleRateKhz;
195 samples_per_packet_ = sample_rate_khz_ * kDefaultPacketSizeMs;
196}
197
henrik.lundin91951862016-06-08 06:43:41 -0700198void NackTracker::SetMaxNackListSize(size_t max_nack_list_size) {
henrik.lundin48ed9302015-10-29 05:36:24 -0700199 RTC_CHECK_GT(max_nack_list_size, 0u);
200 // Ugly hack to get around the problem of passing static consts by reference.
henrik.lundin91951862016-06-08 06:43:41 -0700201 const size_t kNackListSizeLimitLocal = NackTracker::kNackListSizeLimit;
henrik.lundin48ed9302015-10-29 05:36:24 -0700202 RTC_CHECK_LE(max_nack_list_size, kNackListSizeLimitLocal);
203
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000204 max_nack_list_size_ = max_nack_list_size;
205 LimitNackListSize();
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000206}
207
henrik.lundin91951862016-06-08 06:43:41 -0700208void NackTracker::LimitNackListSize() {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000209 uint16_t limit = sequence_num_last_received_rtp_ -
henrik.lundin48ed9302015-10-29 05:36:24 -0700210 static_cast<uint16_t>(max_nack_list_size_) - 1;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000211 nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(limit));
212}
213
henrik.lundin91951862016-06-08 06:43:41 -0700214int64_t NackTracker::TimeToPlay(uint32_t timestamp) const {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000215 uint32_t timestamp_increase = timestamp - timestamp_last_decoded_rtp_;
216 return timestamp_increase / sample_rate_khz_;
217}
218
219// We don't erase elements with time-to-play shorter than round-trip-time.
henrik.lundin91951862016-06-08 06:43:41 -0700220std::vector<uint16_t> NackTracker::GetNackList(
221 int64_t round_trip_time_ms) const {
henrik.lundin48ed9302015-10-29 05:36:24 -0700222 RTC_DCHECK_GE(round_trip_time_ms, 0);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000223 std::vector<uint16_t> sequence_numbers;
224 for (NackList::const_iterator it = nack_list_.begin(); it != nack_list_.end();
henrik.lundin48ed9302015-10-29 05:36:24 -0700225 ++it) {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000226 if (it->second.is_missing &&
227 it->second.time_to_play_ms > round_trip_time_ms)
228 sequence_numbers.push_back(it->first);
229 }
230 return sequence_numbers;
231}
232
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000233} // namespace webrtc