blob: d7c6b084222cfc2b0c4fde77ee44cd5862276903 [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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#ifndef MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_
12#define MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_
turaj@webrtc.org7959e162013-09-12 18:30:26 +000013
Yves Gerey988cc082018-10-23 12:03:01 +020014#include <stddef.h>
15#include <stdint.h>
turaj@webrtc.org7959e162013-09-12 18:30:26 +000016#include <map>
Yves Gerey665174f2018-06-19 15:03:05 +020017#include <vector>
turaj@webrtc.org7959e162013-09-12 18:30:26 +000018
Yves Gerey988cc082018-10-23 12:03:01 +020019#include "modules/include/module_common_types_public.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "rtc_base/gtest_prod_util.h"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000021
22//
henrik.lundin91951862016-06-08 06:43:41 -070023// The NackTracker class keeps track of the lost packets, an estimate of
24// time-to-play for each packet is also given.
turaj@webrtc.org7959e162013-09-12 18:30:26 +000025//
26// Every time a packet is pushed into NetEq, LastReceivedPacket() has to be
27// called to update the NACK list.
28//
29// Every time 10ms audio is pulled from NetEq LastDecodedPacket() should be
30// called, and time-to-play is updated at that moment.
31//
32// If packet N is received, any packet prior to |N - NackThreshold| which is not
33// arrived is considered lost, and should be labeled as "missing" (the size of
34// the list might be limited and older packet eliminated from the list). Packets
35// |N - NackThreshold|, |N - NackThreshold + 1|, ..., |N - 1| are considered
36// "late." A "late" packet with sequence number K is changed to "missing" any
37// time a packet with sequence number newer than |K + NackList| is arrived.
38//
henrik.lundin91951862016-06-08 06:43:41 -070039// The NackTracker class has to know about the sample rate of the packets to
40// compute time-to-play. So sample rate should be set as soon as the first
41// packet is received. If there is a change in the receive codec (sender changes
42// codec) then NackTracker should be reset. This is because NetEQ would flush
43// its buffer and re-transmission is meaning less for old packet. Therefore, in
44// that case, after reset the sampling rate has to be updated.
turaj@webrtc.org7959e162013-09-12 18:30:26 +000045//
46// Thread Safety
47// =============
48// Please note that this class in not thread safe. The class must be protected
49// if different APIs are called from different threads.
50//
51namespace webrtc {
52
henrik.lundin91951862016-06-08 06:43:41 -070053class NackTracker {
turaj@webrtc.org7959e162013-09-12 18:30:26 +000054 public:
55 // A limit for the size of the NACK list.
56 static const size_t kNackListSizeLimit = 500; // 10 seconds for 20 ms frame
57 // packets.
58 // Factory method.
henrik.lundin91951862016-06-08 06:43:41 -070059 static NackTracker* Create(int nack_threshold_packets);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000060
henrik.lundin91951862016-06-08 06:43:41 -070061 ~NackTracker();
turaj@webrtc.org7959e162013-09-12 18:30:26 +000062
63 // Set a maximum for the size of the NACK list. If the last received packet
64 // has sequence number of N, then NACK list will not contain any element
65 // with sequence number earlier than N - |max_nack_list_size|.
66 //
67 // The largest maximum size is defined by |kNackListSizeLimit|
henrik.lundin48ed9302015-10-29 05:36:24 -070068 void SetMaxNackListSize(size_t max_nack_list_size);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000069
70 // Set the sampling rate.
71 //
72 // If associated sampling rate of the received packets is changed, call this
73 // function to update sampling rate. Note that if there is any change in
74 // received codec then NetEq will flush its buffer and NACK has to be reset.
75 // After Reset() is called sampling rate has to be set.
76 void UpdateSampleRate(int sample_rate_hz);
77
78 // Update the sequence number and the timestamp of the last decoded RTP. This
79 // API should be called every time 10 ms audio is pulled from NetEq.
80 void UpdateLastDecodedPacket(uint16_t sequence_number, uint32_t timestamp);
81
82 // Update the sequence number and the timestamp of the last received RTP. This
83 // API should be called every time a packet pushed into ACM.
84 void UpdateLastReceivedPacket(uint16_t sequence_number, uint32_t timestamp);
85
86 // Get a list of "missing" packets which have expected time-to-play larger
87 // than the given round-trip-time (in milliseconds).
88 // Note: Late packets are not included.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000089 std::vector<uint16_t> GetNackList(int64_t round_trip_time_ms) const;
turaj@webrtc.org7959e162013-09-12 18:30:26 +000090
91 // Reset to default values. The NACK list is cleared.
92 // |nack_threshold_packets_| & |max_nack_list_size_| preserve their values.
93 void Reset();
94
95 private:
96 // This test need to access the private method GetNackList().
henrik.lundin91951862016-06-08 06:43:41 -070097 FRIEND_TEST_ALL_PREFIXES(NackTrackerTest, EstimateTimestampAndTimeToPlay);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000098
99 struct NackElement {
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000100 NackElement(int64_t initial_time_to_play_ms,
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000101 uint32_t initial_timestamp,
102 bool missing)
103 : time_to_play_ms(initial_time_to_play_ms),
104 estimated_timestamp(initial_timestamp),
105 is_missing(missing) {}
106
107 // Estimated time (ms) left for this packet to be decoded. This estimate is
108 // updated every time jitter buffer decodes a packet.
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000109 int64_t time_to_play_ms;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000110
111 // A guess about the timestamp of the missing packet, it is used for
112 // estimation of |time_to_play_ms|. The estimate might be slightly wrong if
113 // there has been frame-size change since the last received packet and the
114 // missing packet. However, the risk of this is low, and in case of such
115 // errors, there will be a minor misestimation in time-to-play of missing
116 // packets. This will have a very minor effect on NACK performance.
117 uint32_t estimated_timestamp;
118
119 // True if the packet is considered missing. Otherwise indicates packet is
120 // late.
121 bool is_missing;
122 };
123
124 class NackListCompare {
125 public:
henrik.lundin48ed9302015-10-29 05:36:24 -0700126 bool operator()(uint16_t sequence_number_old,
127 uint16_t sequence_number_new) const {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000128 return IsNewerSequenceNumber(sequence_number_new, sequence_number_old);
129 }
130 };
131
132 typedef std::map<uint16_t, NackElement, NackListCompare> NackList;
133
134 // Constructor.
henrik.lundin91951862016-06-08 06:43:41 -0700135 explicit NackTracker(int nack_threshold_packets);
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000136
137 // This API is used only for testing to assess whether time-to-play is
138 // computed correctly.
139 NackList GetNackList() const;
140
141 // Given the |sequence_number_current_received_rtp| of currently received RTP,
142 // recognize packets which are not arrive and add to the list.
143 void AddToList(uint16_t sequence_number_current_received_rtp);
144
145 // This function subtracts 10 ms of time-to-play for all packets in NACK list.
146 // This is called when 10 ms elapsed with no new RTP packet decoded.
147 void UpdateEstimatedPlayoutTimeBy10ms();
148
149 // Given the |sequence_number_current_received_rtp| and
150 // |timestamp_current_received_rtp| of currently received RTP update number
151 // of samples per packet.
152 void UpdateSamplesPerPacket(uint16_t sequence_number_current_received_rtp,
153 uint32_t timestamp_current_received_rtp);
154
155 // Given the |sequence_number_current_received_rtp| of currently received RTP
156 // update the list. That is; some packets will change from late to missing,
157 // some packets are inserted as missing and some inserted as late.
158 void UpdateList(uint16_t sequence_number_current_received_rtp);
159
160 // Packets which are considered late for too long (according to
161 // |nack_threshold_packets_|) are flagged as missing.
162 void ChangeFromLateToMissing(uint16_t sequence_number_current_received_rtp);
163
164 // Packets which have sequence number older that
165 // |sequence_num_last_received_rtp_| - |max_nack_list_size_| are removed
166 // from the NACK list.
167 void LimitNackListSize();
168
169 // Estimate timestamp of a missing packet given its sequence number.
170 uint32_t EstimateTimestamp(uint16_t sequence_number);
171
172 // Compute time-to-play given a timestamp.
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000173 int64_t TimeToPlay(uint32_t timestamp) const;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000174
175 // If packet N is arrived, any packet prior to N - |nack_threshold_packets_|
176 // which is not arrived is considered missing, and should be in NACK list.
177 // Also any packet in the range of N-1 and N - |nack_threshold_packets_|,
178 // exclusive, which is not arrived is considered late, and should should be
179 // in the list of late packets.
180 const int nack_threshold_packets_;
181
182 // Valid if a packet is received.
183 uint16_t sequence_num_last_received_rtp_;
184 uint32_t timestamp_last_received_rtp_;
185 bool any_rtp_received_; // If any packet received.
186
187 // Valid if a packet is decoded.
188 uint16_t sequence_num_last_decoded_rtp_;
189 uint32_t timestamp_last_decoded_rtp_;
190 bool any_rtp_decoded_; // If any packet decoded.
191
192 int sample_rate_khz_; // Sample rate in kHz.
193
194 // Number of samples per packet. We update this every time we receive a
195 // packet, not only for consecutive packets.
196 int samples_per_packet_;
197
198 // A list of missing packets to be retransmitted. Components of the list
199 // contain the sequence number of missing packets and the estimated time that
200 // each pack is going to be played out.
201 NackList nack_list_;
202
203 // NACK list will not keep track of missing packets prior to
204 // |sequence_num_last_received_rtp_| - |max_nack_list_size_|.
205 size_t max_nack_list_size_;
206};
207
208} // namespace webrtc
209
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200210#endif // MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_