• 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 #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