Home | History | Annotate | Download | only in neteq
      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 #ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_
     12 #define WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_
     13 
     14 #include <vector>
     15 #include <map>
     16 
     17 #include "webrtc/base/scoped_ptr.h"
     18 #include "webrtc/modules/audio_coding/include/audio_coding_module_typedefs.h"
     19 #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 //
     50 namespace webrtc {
     51 
     52 class 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 
     60   ~Nack();
     61 
     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|
     67   void SetMaxNackListSize(size_t max_nack_list_size);
     68 
     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.
     88   std::vector<uint16_t> GetNackList(int64_t round_trip_time_ms) const;
     89 
     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 {
     99     NackElement(int64_t initial_time_to_play_ms,
    100                 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.
    108     int64_t time_to_play_ms;
    109 
    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:
    125     bool operator()(uint16_t sequence_number_old,
    126                     uint16_t sequence_number_new) const {
    127       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.
    172   int64_t TimeToPlay(uint32_t timestamp) const;
    173 
    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 
    209 #endif  // WEBRTC_MODULES_AUDIO_CODING_NETEQ_NACK_H_
    210