Line data Source code
1 : /*
2 : * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 : *
4 : * Use of this source code is governed by a BSD-style license
5 : * that can be found in the LICENSE file in the root of the source
6 : * tree. An additional intellectual property rights grant can be found
7 : * in the file PATENTS. All contributing project authors may
8 : * be found in the AUTHORS file in the root of the source tree.
9 : */
10 :
11 : #include "webrtc/modules/audio_coding/neteq/nack_tracker.h"
12 :
13 : #include <assert.h> // For assert.
14 :
15 : #include <algorithm> // For std::max.
16 :
17 : #include "webrtc/base/checks.h"
18 : #include "webrtc/modules/include/module_common_types.h"
19 : #include "webrtc/system_wrappers/include/logging.h"
20 :
21 : namespace webrtc {
22 : namespace {
23 :
24 : const int kDefaultSampleRateKhz = 48;
25 : const int kDefaultPacketSizeMs = 20;
26 :
27 : } // namespace
28 :
29 0 : NackTracker::NackTracker(int nack_threshold_packets)
30 : : 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 0 : samples_per_packet_(sample_rate_khz_ * kDefaultPacketSizeMs),
39 0 : max_nack_list_size_(kNackListSizeLimit) {}
40 :
41 : NackTracker::~NackTracker() = default;
42 :
43 0 : NackTracker* NackTracker::Create(int nack_threshold_packets) {
44 0 : return new NackTracker(nack_threshold_packets);
45 : }
46 :
47 0 : void NackTracker::UpdateSampleRate(int sample_rate_hz) {
48 0 : assert(sample_rate_hz > 0);
49 0 : sample_rate_khz_ = sample_rate_hz / 1000;
50 0 : }
51 :
52 0 : void NackTracker::UpdateLastReceivedPacket(uint16_t sequence_number,
53 : uint32_t timestamp) {
54 : // Just record the value of sequence number and timestamp if this is the
55 : // first packet.
56 0 : if (!any_rtp_received_) {
57 0 : sequence_num_last_received_rtp_ = sequence_number;
58 0 : timestamp_last_received_rtp_ = timestamp;
59 0 : 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 0 : if (!any_rtp_decoded_) {
63 0 : sequence_num_last_decoded_rtp_ = sequence_number;
64 0 : timestamp_last_decoded_rtp_ = timestamp;
65 : }
66 0 : return;
67 : }
68 :
69 0 : if (sequence_number == sequence_num_last_received_rtp_)
70 0 : return;
71 :
72 : // Received RTP should not be in the list.
73 0 : nack_list_.erase(sequence_number);
74 :
75 : // If this is an old sequence number, no more action is required, return.
76 0 : if (IsNewerSequenceNumber(sequence_num_last_received_rtp_, sequence_number))
77 0 : return;
78 :
79 0 : UpdateSamplesPerPacket(sequence_number, timestamp);
80 :
81 0 : UpdateList(sequence_number);
82 :
83 0 : sequence_num_last_received_rtp_ = sequence_number;
84 0 : timestamp_last_received_rtp_ = timestamp;
85 0 : LimitNackListSize();
86 : }
87 :
88 0 : void NackTracker::UpdateSamplesPerPacket(
89 : uint16_t sequence_number_current_received_rtp,
90 : uint32_t timestamp_current_received_rtp) {
91 : uint32_t timestamp_increase =
92 0 : timestamp_current_received_rtp - timestamp_last_received_rtp_;
93 : uint16_t sequence_num_increase =
94 0 : sequence_number_current_received_rtp - sequence_num_last_received_rtp_;
95 :
96 0 : samples_per_packet_ = timestamp_increase / sequence_num_increase;
97 0 : }
98 :
99 0 : void NackTracker::UpdateList(uint16_t sequence_number_current_received_rtp) {
100 : // Some of the packets which were considered late, now are considered missing.
101 0 : ChangeFromLateToMissing(sequence_number_current_received_rtp);
102 :
103 0 : if (IsNewerSequenceNumber(sequence_number_current_received_rtp,
104 0 : sequence_num_last_received_rtp_ + 1))
105 0 : AddToList(sequence_number_current_received_rtp);
106 0 : }
107 :
108 0 : void NackTracker::ChangeFromLateToMissing(
109 : uint16_t sequence_number_current_received_rtp) {
110 : NackList::const_iterator lower_bound =
111 0 : nack_list_.lower_bound(static_cast<uint16_t>(
112 0 : sequence_number_current_received_rtp - nack_threshold_packets_));
113 :
114 0 : for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it)
115 0 : it->second.is_missing = true;
116 0 : }
117 :
118 0 : uint32_t NackTracker::EstimateTimestamp(uint16_t sequence_num) {
119 0 : uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_;
120 0 : return sequence_num_diff * samples_per_packet_ + timestamp_last_received_rtp_;
121 : }
122 :
123 0 : void NackTracker::AddToList(uint16_t sequence_number_current_received_rtp) {
124 0 : assert(!any_rtp_decoded_ ||
125 : IsNewerSequenceNumber(sequence_number_current_received_rtp,
126 : sequence_num_last_decoded_rtp_));
127 :
128 : // Packets with sequence numbers older than |upper_bound_missing| are
129 : // considered missing, and the rest are considered late.
130 : uint16_t upper_bound_missing =
131 0 : sequence_number_current_received_rtp - nack_threshold_packets_;
132 :
133 0 : for (uint16_t n = sequence_num_last_received_rtp_ + 1;
134 0 : IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n) {
135 0 : bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n);
136 0 : uint32_t timestamp = EstimateTimestamp(n);
137 0 : NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing);
138 0 : nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element));
139 : }
140 0 : }
141 :
142 0 : void NackTracker::UpdateEstimatedPlayoutTimeBy10ms() {
143 0 : while (!nack_list_.empty() &&
144 0 : nack_list_.begin()->second.time_to_play_ms <= 10)
145 0 : nack_list_.erase(nack_list_.begin());
146 :
147 0 : for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end(); ++it)
148 0 : it->second.time_to_play_ms -= 10;
149 0 : }
150 :
151 0 : void NackTracker::UpdateLastDecodedPacket(uint16_t sequence_number,
152 : uint32_t timestamp) {
153 0 : if (IsNewerSequenceNumber(sequence_number, sequence_num_last_decoded_rtp_) ||
154 0 : !any_rtp_decoded_) {
155 0 : sequence_num_last_decoded_rtp_ = sequence_number;
156 0 : 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.
160 0 : nack_list_.erase(nack_list_.begin(),
161 0 : nack_list_.upper_bound(sequence_num_last_decoded_rtp_));
162 :
163 : // Update estimated time-to-play.
164 0 : for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end();
165 : ++it)
166 0 : it->second.time_to_play_ms = TimeToPlay(it->second.estimated_timestamp);
167 : } else {
168 0 : 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 0 : UpdateEstimatedPlayoutTimeBy10ms();
173 :
174 : // Update timestamp for better estimate of time-to-play, for packets which
175 : // are added to NACK list later on.
176 0 : timestamp_last_decoded_rtp_ += sample_rate_khz_ * 10;
177 : }
178 0 : any_rtp_decoded_ = true;
179 0 : }
180 :
181 0 : NackTracker::NackList NackTracker::GetNackList() const {
182 0 : return nack_list_;
183 : }
184 :
185 0 : void NackTracker::Reset() {
186 0 : nack_list_.clear();
187 :
188 0 : sequence_num_last_received_rtp_ = 0;
189 0 : timestamp_last_received_rtp_ = 0;
190 0 : any_rtp_received_ = false;
191 0 : sequence_num_last_decoded_rtp_ = 0;
192 0 : timestamp_last_decoded_rtp_ = 0;
193 0 : any_rtp_decoded_ = false;
194 0 : sample_rate_khz_ = kDefaultSampleRateKhz;
195 0 : samples_per_packet_ = sample_rate_khz_ * kDefaultPacketSizeMs;
196 0 : }
197 :
198 0 : void NackTracker::SetMaxNackListSize(size_t max_nack_list_size) {
199 0 : RTC_CHECK_GT(max_nack_list_size, 0);
200 : // Ugly hack to get around the problem of passing static consts by reference.
201 0 : const size_t kNackListSizeLimitLocal = NackTracker::kNackListSizeLimit;
202 0 : RTC_CHECK_LE(max_nack_list_size, kNackListSizeLimitLocal);
203 :
204 0 : max_nack_list_size_ = max_nack_list_size;
205 0 : LimitNackListSize();
206 0 : }
207 :
208 0 : void NackTracker::LimitNackListSize() {
209 0 : uint16_t limit = sequence_num_last_received_rtp_ -
210 0 : static_cast<uint16_t>(max_nack_list_size_) - 1;
211 0 : nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(limit));
212 0 : }
213 :
214 0 : int64_t NackTracker::TimeToPlay(uint32_t timestamp) const {
215 0 : uint32_t timestamp_increase = timestamp - timestamp_last_decoded_rtp_;
216 0 : return timestamp_increase / sample_rate_khz_;
217 : }
218 :
219 : // We don't erase elements with time-to-play shorter than round-trip-time.
220 0 : std::vector<uint16_t> NackTracker::GetNackList(
221 : int64_t round_trip_time_ms) const {
222 0 : RTC_DCHECK_GE(round_trip_time_ms, 0);
223 0 : std::vector<uint16_t> sequence_numbers;
224 0 : for (NackList::const_iterator it = nack_list_.begin(); it != nack_list_.end();
225 : ++it) {
226 0 : if (it->second.is_missing &&
227 0 : it->second.time_to_play_ms > round_trip_time_ms)
228 0 : sequence_numbers.push_back(it->first);
229 : }
230 0 : return sequence_numbers;
231 : }
232 :
233 : } // namespace webrtc
|