Home | History | Annotate | Download | only in acm2
      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