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