blob: 17fef464648879f1d6eb8a6b854633400f84ba8b [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
henrik.lundin48ed9302015-10-29 05:36:24 -070011#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_
12#define WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_
turaj@webrtc.org7959e162013-09-12 18:30:26 +000013
14#include <vector>
15#include <map>
16
kwiberg@webrtc.org00b8f6b2015-02-26 14:34:55 +000017#include "webrtc/base/scoped_ptr.h"
kjellander3e6db232015-11-26 04:44:54 -080018#include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
turaj@webrtc.org7959e162013-09-12 18:30:26 +000019#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//
50namespace webrtc {
51
52class Nack {
53 public:
54 // A limit for the size of the NACK list.
55 static const size_t kNackListSizeLimit = 500; // 10 seconds for 20 ms frame
56 // packets.
57 // Factory method.
58 static Nack* Create(int nack_threshold_packets);
59
Karl Wiberg2519c452015-04-07 16:12:57 +020060 ~Nack();
turaj@webrtc.org7959e162013-09-12 18:30:26 +000061
62 // Set a maximum for the size of the NACK list. If the last received packet
63 // has sequence number of N, then NACK list will not contain any element
64 // with sequence number earlier than N - |max_nack_list_size|.
65 //
66 // The largest maximum size is defined by |kNackListSizeLimit|
henrik.lundin48ed9302015-10-29 05:36:24 -070067 void SetMaxNackListSize(size_t max_nack_list_size);
turaj@webrtc.org7959e162013-09-12 18:30:26 +000068
69 // Set the sampling rate.
70 //
71 // If associated sampling rate of the received packets is changed, call this
72 // function to update sampling rate. Note that if there is any change in
73 // received codec then NetEq will flush its buffer and NACK has to be reset.
74 // After Reset() is called sampling rate has to be set.
75 void UpdateSampleRate(int sample_rate_hz);
76
77 // Update the sequence number and the timestamp of the last decoded RTP. This
78 // API should be called every time 10 ms audio is pulled from NetEq.
79 void UpdateLastDecodedPacket(uint16_t sequence_number, uint32_t timestamp);
80
81 // Update the sequence number and the timestamp of the last received RTP. This
82 // API should be called every time a packet pushed into ACM.
83 void UpdateLastReceivedPacket(uint16_t sequence_number, uint32_t timestamp);
84
85 // Get a list of "missing" packets which have expected time-to-play larger
86 // than the given round-trip-time (in milliseconds).
87 // Note: Late packets are not included.
pkasting@chromium.org16825b12015-01-12 21:51:21 +000088 std::vector<uint16_t> GetNackList(int64_t round_trip_time_ms) const;
turaj@webrtc.org7959e162013-09-12 18:30:26 +000089
90 // Reset to default values. The NACK list is cleared.
91 // |nack_threshold_packets_| & |max_nack_list_size_| preserve their values.
92 void Reset();
93
94 private:
95 // This test need to access the private method GetNackList().
96 FRIEND_TEST_ALL_PREFIXES(NackTest, EstimateTimestampAndTimeToPlay);
97
98 struct NackElement {
pkasting@chromium.org16825b12015-01-12 21:51:21 +000099 NackElement(int64_t initial_time_to_play_ms,
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000100 uint32_t initial_timestamp,
101 bool missing)
102 : time_to_play_ms(initial_time_to_play_ms),
103 estimated_timestamp(initial_timestamp),
104 is_missing(missing) {}
105
106 // Estimated time (ms) left for this packet to be decoded. This estimate is
107 // updated every time jitter buffer decodes a packet.
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000108 int64_t time_to_play_ms;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000109
110 // A guess about the timestamp of the missing packet, it is used for
111 // estimation of |time_to_play_ms|. The estimate might be slightly wrong if
112 // there has been frame-size change since the last received packet and the
113 // missing packet. However, the risk of this is low, and in case of such
114 // errors, there will be a minor misestimation in time-to-play of missing
115 // packets. This will have a very minor effect on NACK performance.
116 uint32_t estimated_timestamp;
117
118 // True if the packet is considered missing. Otherwise indicates packet is
119 // late.
120 bool is_missing;
121 };
122
123 class NackListCompare {
124 public:
henrik.lundin48ed9302015-10-29 05:36:24 -0700125 bool operator()(uint16_t sequence_number_old,
126 uint16_t sequence_number_new) const {
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000127 return IsNewerSequenceNumber(sequence_number_new, sequence_number_old);
128 }
129 };
130
131 typedef std::map<uint16_t, NackElement, NackListCompare> NackList;
132
133 // Constructor.
134 explicit Nack(int nack_threshold_packets);
135
136 // This API is used only for testing to assess whether time-to-play is
137 // computed correctly.
138 NackList GetNackList() const;
139
140 // Given the |sequence_number_current_received_rtp| of currently received RTP,
141 // recognize packets which are not arrive and add to the list.
142 void AddToList(uint16_t sequence_number_current_received_rtp);
143
144 // This function subtracts 10 ms of time-to-play for all packets in NACK list.
145 // This is called when 10 ms elapsed with no new RTP packet decoded.
146 void UpdateEstimatedPlayoutTimeBy10ms();
147
148 // Given the |sequence_number_current_received_rtp| and
149 // |timestamp_current_received_rtp| of currently received RTP update number
150 // of samples per packet.
151 void UpdateSamplesPerPacket(uint16_t sequence_number_current_received_rtp,
152 uint32_t timestamp_current_received_rtp);
153
154 // Given the |sequence_number_current_received_rtp| of currently received RTP
155 // update the list. That is; some packets will change from late to missing,
156 // some packets are inserted as missing and some inserted as late.
157 void UpdateList(uint16_t sequence_number_current_received_rtp);
158
159 // Packets which are considered late for too long (according to
160 // |nack_threshold_packets_|) are flagged as missing.
161 void ChangeFromLateToMissing(uint16_t sequence_number_current_received_rtp);
162
163 // Packets which have sequence number older that
164 // |sequence_num_last_received_rtp_| - |max_nack_list_size_| are removed
165 // from the NACK list.
166 void LimitNackListSize();
167
168 // Estimate timestamp of a missing packet given its sequence number.
169 uint32_t EstimateTimestamp(uint16_t sequence_number);
170
171 // Compute time-to-play given a timestamp.
pkasting@chromium.org16825b12015-01-12 21:51:21 +0000172 int64_t TimeToPlay(uint32_t timestamp) const;
turaj@webrtc.org7959e162013-09-12 18:30:26 +0000173
174 // If packet N is arrived, any packet prior to N - |nack_threshold_packets_|
175 // which is not arrived is considered missing, and should be in NACK list.
176 // Also any packet in the range of N-1 and N - |nack_threshold_packets_|,
177 // exclusive, which is not arrived is considered late, and should should be
178 // in the list of late packets.
179 const int nack_threshold_packets_;
180
181 // Valid if a packet is received.
182 uint16_t sequence_num_last_received_rtp_;
183 uint32_t timestamp_last_received_rtp_;
184 bool any_rtp_received_; // If any packet received.
185
186 // Valid if a packet is decoded.
187 uint16_t sequence_num_last_decoded_rtp_;
188 uint32_t timestamp_last_decoded_rtp_;
189 bool any_rtp_decoded_; // If any packet decoded.
190
191 int sample_rate_khz_; // Sample rate in kHz.
192
193 // Number of samples per packet. We update this every time we receive a
194 // packet, not only for consecutive packets.
195 int samples_per_packet_;
196
197 // A list of missing packets to be retransmitted. Components of the list
198 // contain the sequence number of missing packets and the estimated time that
199 // each pack is going to be played out.
200 NackList nack_list_;
201
202 // NACK list will not keep track of missing packets prior to
203 // |sequence_num_last_received_rtp_| - |max_nack_list_size_|.
204 size_t max_nack_list_size_;
205};
206
207} // namespace webrtc
208
henrik.lundin48ed9302015-10-29 05:36:24 -0700209#endif // WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_