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 #include "webrtc/modules/audio_coding/acm2/initial_delay_manager.h"
12
13 namespace webrtc {
14
15 namespace acm2 {
16
InitialDelayManager(int initial_delay_ms,int late_packet_threshold)17 InitialDelayManager::InitialDelayManager(int initial_delay_ms,
18 int late_packet_threshold)
19 : last_packet_type_(kUndefinedPacket),
20 last_receive_timestamp_(0),
21 timestamp_step_(0),
22 audio_payload_type_(kInvalidPayloadType),
23 initial_delay_ms_(initial_delay_ms),
24 buffered_audio_ms_(0),
25 buffering_(true),
26 playout_timestamp_(0),
27 late_packet_threshold_(late_packet_threshold) {
28 last_packet_rtp_info_.header.payloadType = kInvalidPayloadType;
29 last_packet_rtp_info_.header.ssrc = 0;
30 last_packet_rtp_info_.header.sequenceNumber = 0;
31 last_packet_rtp_info_.header.timestamp = 0;
32 }
33
UpdateLastReceivedPacket(const WebRtcRTPHeader & rtp_info,uint32_t receive_timestamp,PacketType type,bool new_codec,int sample_rate_hz,SyncStream * sync_stream)34 void InitialDelayManager::UpdateLastReceivedPacket(
35 const WebRtcRTPHeader& rtp_info,
36 uint32_t receive_timestamp,
37 PacketType type,
38 bool new_codec,
39 int sample_rate_hz,
40 SyncStream* sync_stream) {
41 assert(sync_stream);
42
43 // If payload of audio packets is changing |new_codec| has to be true.
44 assert(!(!new_codec && type == kAudioPacket &&
45 rtp_info.header.payloadType != audio_payload_type_));
46
47 // Just shorthands.
48 const RTPHeader* current_header = &rtp_info.header;
49 RTPHeader* last_header = &last_packet_rtp_info_.header;
50
51 // Don't do anything if getting DTMF. The chance of DTMF in applications where
52 // initial delay is required is very low (we don't know of any). This avoids a
53 // lot of corner cases. The effect of ignoring DTMF packet is minimal. Note
54 // that DTMFs are inserted into NetEq just not accounted here.
55 if (type == kAvtPacket ||
56 (last_packet_type_ != kUndefinedPacket &&
57 !IsNewerSequenceNumber(current_header->sequenceNumber,
58 last_header->sequenceNumber))) {
59 sync_stream->num_sync_packets = 0;
60 return;
61 }
62
63 // Either if it is a new packet or the first packet record and set variables.
64 if (new_codec ||
65 last_packet_rtp_info_.header.payloadType == kInvalidPayloadType) {
66 timestamp_step_ = 0;
67 if (type == kAudioPacket)
68 audio_payload_type_ = rtp_info.header.payloadType;
69 else
70 audio_payload_type_ = kInvalidPayloadType; // Invalid.
71
72 RecordLastPacket(rtp_info, receive_timestamp, type);
73 sync_stream->num_sync_packets = 0;
74 buffered_audio_ms_ = 0;
75 buffering_ = true;
76
77 // If |buffering_| is set then |playout_timestamp_| should have correct
78 // value.
79 UpdatePlayoutTimestamp(*current_header, sample_rate_hz);
80 return;
81 }
82
83 uint32_t timestamp_increase = current_header->timestamp -
84 last_header->timestamp;
85
86 // |timestamp_increase| is invalid if this is the first packet. The effect is
87 // that |buffered_audio_ms_| is not increased.
88 if (last_packet_type_ == kUndefinedPacket) {
89 timestamp_increase = 0;
90 }
91
92 if (buffering_) {
93 buffered_audio_ms_ += timestamp_increase * 1000 / sample_rate_hz;
94
95 // A timestamp that reflects the initial delay, while buffering.
96 UpdatePlayoutTimestamp(*current_header, sample_rate_hz);
97
98 if (buffered_audio_ms_ >= initial_delay_ms_)
99 buffering_ = false;
100 }
101
102 if (current_header->sequenceNumber == last_header->sequenceNumber + 1) {
103 // Two consecutive audio packets, the previous packet-type is audio, so we
104 // can update |timestamp_step_|.
105 if (last_packet_type_ == kAudioPacket)
106 timestamp_step_ = timestamp_increase;
107 RecordLastPacket(rtp_info, receive_timestamp, type);
108 sync_stream->num_sync_packets = 0;
109 return;
110 }
111
112 uint16_t packet_gap = current_header->sequenceNumber -
113 last_header->sequenceNumber - 1;
114
115 // For smooth transitions leave a gap between audio and sync packets.
116 sync_stream->num_sync_packets = last_packet_type_ == kSyncPacket ?
117 packet_gap - 1 : packet_gap - 2;
118
119 // Do nothing if we haven't received any audio packet.
120 if (sync_stream->num_sync_packets > 0 &&
121 audio_payload_type_ != kInvalidPayloadType) {
122 if (timestamp_step_ == 0) {
123 // Make an estimate for |timestamp_step_| if it is not updated, yet.
124 assert(packet_gap > 0);
125 timestamp_step_ = timestamp_increase / (packet_gap + 1);
126 }
127 sync_stream->timestamp_step = timestamp_step_;
128
129 // Build the first sync-packet based on the current received packet.
130 memcpy(&sync_stream->rtp_info, &rtp_info, sizeof(rtp_info));
131 sync_stream->rtp_info.header.payloadType = audio_payload_type_;
132
133 uint16_t sequence_number_update = sync_stream->num_sync_packets + 1;
134 uint32_t timestamp_update = timestamp_step_ * sequence_number_update;
135
136 // Rewind sequence number and timestamps. This will give a more accurate
137 // description of the missing packets.
138 //
139 // Note that we leave a gap between the last packet in sync-stream and the
140 // current received packet, so it should be compensated for in the following
141 // computation of timestamps and sequence number.
142 sync_stream->rtp_info.header.sequenceNumber -= sequence_number_update;
143 sync_stream->receive_timestamp = receive_timestamp - timestamp_update;
144 sync_stream->rtp_info.header.timestamp -= timestamp_update;
145 sync_stream->rtp_info.header.payloadType = audio_payload_type_;
146 } else {
147 sync_stream->num_sync_packets = 0;
148 }
149
150 RecordLastPacket(rtp_info, receive_timestamp, type);
151 return;
152 }
153
RecordLastPacket(const WebRtcRTPHeader & rtp_info,uint32_t receive_timestamp,PacketType type)154 void InitialDelayManager::RecordLastPacket(const WebRtcRTPHeader& rtp_info,
155 uint32_t receive_timestamp,
156 PacketType type) {
157 last_packet_type_ = type;
158 last_receive_timestamp_ = receive_timestamp;
159 memcpy(&last_packet_rtp_info_, &rtp_info, sizeof(rtp_info));
160 }
161
LatePackets(uint32_t timestamp_now,SyncStream * sync_stream)162 void InitialDelayManager::LatePackets(
163 uint32_t timestamp_now, SyncStream* sync_stream) {
164 assert(sync_stream);
165 sync_stream->num_sync_packets = 0;
166
167 // If there is no estimate of timestamp increment, |timestamp_step_|, then
168 // we cannot estimate the number of late packets.
169 // If the last packet has been CNG, estimating late packets is not meaningful,
170 // as a CNG packet is on unknown length.
171 // We can set a higher threshold if the last packet is CNG and continue
172 // execution, but this is how ACM1 code was written.
173 if (timestamp_step_ <= 0 ||
174 last_packet_type_ == kCngPacket ||
175 last_packet_type_ == kUndefinedPacket ||
176 audio_payload_type_ == kInvalidPayloadType) // No audio packet received.
177 return;
178
179 int num_late_packets = (timestamp_now - last_receive_timestamp_) /
180 timestamp_step_;
181
182 if (num_late_packets < late_packet_threshold_)
183 return;
184
185 int sync_offset = 1; // One gap at the end of the sync-stream.
186 if (last_packet_type_ != kSyncPacket) {
187 ++sync_offset; // One more gap at the beginning of the sync-stream.
188 --num_late_packets;
189 }
190 uint32_t timestamp_update = sync_offset * timestamp_step_;
191
192 sync_stream->num_sync_packets = num_late_packets;
193 if (num_late_packets == 0)
194 return;
195
196 // Build the first sync-packet in the sync-stream.
197 memcpy(&sync_stream->rtp_info, &last_packet_rtp_info_,
198 sizeof(last_packet_rtp_info_));
199
200 // Increase sequence number and timestamps.
201 sync_stream->rtp_info.header.sequenceNumber += sync_offset;
202 sync_stream->rtp_info.header.timestamp += timestamp_update;
203 sync_stream->receive_timestamp = last_receive_timestamp_ + timestamp_update;
204 sync_stream->timestamp_step = timestamp_step_;
205
206 // Sync-packets have audio payload-type.
207 sync_stream->rtp_info.header.payloadType = audio_payload_type_;
208
209 uint16_t sequence_number_update = num_late_packets + sync_offset - 1;
210 timestamp_update = sequence_number_update * timestamp_step_;
211
212 // Fake the last RTP, assuming the caller will inject the whole sync-stream.
213 last_packet_rtp_info_.header.timestamp += timestamp_update;
214 last_packet_rtp_info_.header.sequenceNumber += sequence_number_update;
215 last_packet_rtp_info_.header.payloadType = audio_payload_type_;
216 last_receive_timestamp_ += timestamp_update;
217
218 last_packet_type_ = kSyncPacket;
219 return;
220 }
221
GetPlayoutTimestamp(uint32_t * playout_timestamp)222 bool InitialDelayManager::GetPlayoutTimestamp(uint32_t* playout_timestamp) {
223 if (!buffering_) {
224 return false;
225 }
226 *playout_timestamp = playout_timestamp_;
227 return true;
228 }
229
DisableBuffering()230 void InitialDelayManager::DisableBuffering() {
231 buffering_ = false;
232 }
233
UpdatePlayoutTimestamp(const RTPHeader & current_header,int sample_rate_hz)234 void InitialDelayManager::UpdatePlayoutTimestamp(
235 const RTPHeader& current_header, int sample_rate_hz) {
236 playout_timestamp_ = current_header.timestamp - static_cast<uint32_t>(
237 initial_delay_ms_ * sample_rate_hz / 1000);
238 }
239
240 } // namespace acm2
241
242 } // namespace webrtc
243