• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_
12 #define MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_
13 
14 #include <stddef.h>
15 #include <stdint.h>
16 
17 #include <map>
18 #include <vector>
19 
20 #include "modules/include/module_common_types_public.h"
21 #include "rtc_base/gtest_prod_util.h"
22 
23 //
24 // The NackTracker class keeps track of the lost packets, an estimate of
25 // time-to-play for each packet is also given.
26 //
27 // Every time a packet is pushed into NetEq, LastReceivedPacket() has to be
28 // called to update the NACK list.
29 //
30 // Every time 10ms audio is pulled from NetEq LastDecodedPacket() should be
31 // called, and time-to-play is updated at that moment.
32 //
33 // If packet N is received, any packet prior to |N - NackThreshold| which is not
34 // arrived is considered lost, and should be labeled as "missing" (the size of
35 // the list might be limited and older packet eliminated from the list). Packets
36 // |N - NackThreshold|, |N - NackThreshold + 1|, ..., |N - 1| are considered
37 // "late." A "late" packet with sequence number K is changed to "missing" any
38 // time a packet with sequence number newer than |K + NackList| is arrived.
39 //
40 // The NackTracker class has to know about the sample rate of the packets to
41 // compute time-to-play. So sample rate should be set as soon as the first
42 // packet is received. If there is a change in the receive codec (sender changes
43 // codec) then NackTracker should be reset. This is because NetEQ would flush
44 // its buffer and re-transmission is meaning less for old packet. Therefore, in
45 // that case, after reset the sampling rate has to be updated.
46 //
47 // Thread Safety
48 // =============
49 // Please note that this class in not thread safe. The class must be protected
50 // if different APIs are called from different threads.
51 //
52 namespace webrtc {
53 
54 class NackTracker {
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 NackTracker* Create(int nack_threshold_packets);
61 
62   ~NackTracker();
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   void 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(NackTrackerTest, EstimateTimestampAndTimeToPlay);
99 
100   struct NackElement {
NackElementNackElement101     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:
operator()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 NackTracker(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 webrtc
210 
211 #endif  // MODULES_AUDIO_CODING_NETEQ_NACK_TRACKER_H_
212