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