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/main/acm2/initial_delay_manager.h" 12 13 namespace webrtc { 14 15 namespace acm2 { 16 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 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 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 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 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 230 void InitialDelayManager::DisableBuffering() { 231 buffering_ = false; 232 } 233 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