LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/modules/audio_coding/neteq - nack_tracker.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 115 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 17 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/neteq/nack_tracker.h"
      12             : 
      13             : #include <assert.h>  // For assert.
      14             : 
      15             : #include <algorithm>  // For std::max.
      16             : 
      17             : #include "webrtc/base/checks.h"
      18             : #include "webrtc/modules/include/module_common_types.h"
      19             : #include "webrtc/system_wrappers/include/logging.h"
      20             : 
      21             : namespace webrtc {
      22             : namespace {
      23             : 
      24             : const int kDefaultSampleRateKhz = 48;
      25             : const int kDefaultPacketSizeMs = 20;
      26             : 
      27             : }  // namespace
      28             : 
      29           0 : NackTracker::NackTracker(int nack_threshold_packets)
      30             :     : nack_threshold_packets_(nack_threshold_packets),
      31             :       sequence_num_last_received_rtp_(0),
      32             :       timestamp_last_received_rtp_(0),
      33             :       any_rtp_received_(false),
      34             :       sequence_num_last_decoded_rtp_(0),
      35             :       timestamp_last_decoded_rtp_(0),
      36             :       any_rtp_decoded_(false),
      37             :       sample_rate_khz_(kDefaultSampleRateKhz),
      38           0 :       samples_per_packet_(sample_rate_khz_ * kDefaultPacketSizeMs),
      39           0 :       max_nack_list_size_(kNackListSizeLimit) {}
      40             : 
      41             : NackTracker::~NackTracker() = default;
      42             : 
      43           0 : NackTracker* NackTracker::Create(int nack_threshold_packets) {
      44           0 :   return new NackTracker(nack_threshold_packets);
      45             : }
      46             : 
      47           0 : void NackTracker::UpdateSampleRate(int sample_rate_hz) {
      48           0 :   assert(sample_rate_hz > 0);
      49           0 :   sample_rate_khz_ = sample_rate_hz / 1000;
      50           0 : }
      51             : 
      52           0 : void NackTracker::UpdateLastReceivedPacket(uint16_t sequence_number,
      53             :                                            uint32_t timestamp) {
      54             :   // Just record the value of sequence number and timestamp if this is the
      55             :   // first packet.
      56           0 :   if (!any_rtp_received_) {
      57           0 :     sequence_num_last_received_rtp_ = sequence_number;
      58           0 :     timestamp_last_received_rtp_ = timestamp;
      59           0 :     any_rtp_received_ = true;
      60             :     // If no packet is decoded, to have a reasonable estimate of time-to-play
      61             :     // use the given values.
      62           0 :     if (!any_rtp_decoded_) {
      63           0 :       sequence_num_last_decoded_rtp_ = sequence_number;
      64           0 :       timestamp_last_decoded_rtp_ = timestamp;
      65             :     }
      66           0 :     return;
      67             :   }
      68             : 
      69           0 :   if (sequence_number == sequence_num_last_received_rtp_)
      70           0 :     return;
      71             : 
      72             :   // Received RTP should not be in the list.
      73           0 :   nack_list_.erase(sequence_number);
      74             : 
      75             :   // If this is an old sequence number, no more action is required, return.
      76           0 :   if (IsNewerSequenceNumber(sequence_num_last_received_rtp_, sequence_number))
      77           0 :     return;
      78             : 
      79           0 :   UpdateSamplesPerPacket(sequence_number, timestamp);
      80             : 
      81           0 :   UpdateList(sequence_number);
      82             : 
      83           0 :   sequence_num_last_received_rtp_ = sequence_number;
      84           0 :   timestamp_last_received_rtp_ = timestamp;
      85           0 :   LimitNackListSize();
      86             : }
      87             : 
      88           0 : void NackTracker::UpdateSamplesPerPacket(
      89             :     uint16_t sequence_number_current_received_rtp,
      90             :     uint32_t timestamp_current_received_rtp) {
      91             :   uint32_t timestamp_increase =
      92           0 :       timestamp_current_received_rtp - timestamp_last_received_rtp_;
      93             :   uint16_t sequence_num_increase =
      94           0 :       sequence_number_current_received_rtp - sequence_num_last_received_rtp_;
      95             : 
      96           0 :   samples_per_packet_ = timestamp_increase / sequence_num_increase;
      97           0 : }
      98             : 
      99           0 : void NackTracker::UpdateList(uint16_t sequence_number_current_received_rtp) {
     100             :   // Some of the packets which were considered late, now are considered missing.
     101           0 :   ChangeFromLateToMissing(sequence_number_current_received_rtp);
     102             : 
     103           0 :   if (IsNewerSequenceNumber(sequence_number_current_received_rtp,
     104           0 :                             sequence_num_last_received_rtp_ + 1))
     105           0 :     AddToList(sequence_number_current_received_rtp);
     106           0 : }
     107             : 
     108           0 : void NackTracker::ChangeFromLateToMissing(
     109             :     uint16_t sequence_number_current_received_rtp) {
     110             :   NackList::const_iterator lower_bound =
     111           0 :       nack_list_.lower_bound(static_cast<uint16_t>(
     112           0 :           sequence_number_current_received_rtp - nack_threshold_packets_));
     113             : 
     114           0 :   for (NackList::iterator it = nack_list_.begin(); it != lower_bound; ++it)
     115           0 :     it->second.is_missing = true;
     116           0 : }
     117             : 
     118           0 : uint32_t NackTracker::EstimateTimestamp(uint16_t sequence_num) {
     119           0 :   uint16_t sequence_num_diff = sequence_num - sequence_num_last_received_rtp_;
     120           0 :   return sequence_num_diff * samples_per_packet_ + timestamp_last_received_rtp_;
     121             : }
     122             : 
     123           0 : void NackTracker::AddToList(uint16_t sequence_number_current_received_rtp) {
     124           0 :   assert(!any_rtp_decoded_ ||
     125             :          IsNewerSequenceNumber(sequence_number_current_received_rtp,
     126             :                                sequence_num_last_decoded_rtp_));
     127             : 
     128             :   // Packets with sequence numbers older than |upper_bound_missing| are
     129             :   // considered missing, and the rest are considered late.
     130             :   uint16_t upper_bound_missing =
     131           0 :       sequence_number_current_received_rtp - nack_threshold_packets_;
     132             : 
     133           0 :   for (uint16_t n = sequence_num_last_received_rtp_ + 1;
     134           0 :        IsNewerSequenceNumber(sequence_number_current_received_rtp, n); ++n) {
     135           0 :     bool is_missing = IsNewerSequenceNumber(upper_bound_missing, n);
     136           0 :     uint32_t timestamp = EstimateTimestamp(n);
     137           0 :     NackElement nack_element(TimeToPlay(timestamp), timestamp, is_missing);
     138           0 :     nack_list_.insert(nack_list_.end(), std::make_pair(n, nack_element));
     139             :   }
     140           0 : }
     141             : 
     142           0 : void NackTracker::UpdateEstimatedPlayoutTimeBy10ms() {
     143           0 :   while (!nack_list_.empty() &&
     144           0 :          nack_list_.begin()->second.time_to_play_ms <= 10)
     145           0 :     nack_list_.erase(nack_list_.begin());
     146             : 
     147           0 :   for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end(); ++it)
     148           0 :     it->second.time_to_play_ms -= 10;
     149           0 : }
     150             : 
     151           0 : void NackTracker::UpdateLastDecodedPacket(uint16_t sequence_number,
     152             :                                           uint32_t timestamp) {
     153           0 :   if (IsNewerSequenceNumber(sequence_number, sequence_num_last_decoded_rtp_) ||
     154           0 :       !any_rtp_decoded_) {
     155           0 :     sequence_num_last_decoded_rtp_ = sequence_number;
     156           0 :     timestamp_last_decoded_rtp_ = timestamp;
     157             :     // Packets in the list with sequence numbers less than the
     158             :     // sequence number of the decoded RTP should be removed from the lists.
     159             :     // They will be discarded by the jitter buffer if they arrive.
     160           0 :     nack_list_.erase(nack_list_.begin(),
     161           0 :                      nack_list_.upper_bound(sequence_num_last_decoded_rtp_));
     162             : 
     163             :     // Update estimated time-to-play.
     164           0 :     for (NackList::iterator it = nack_list_.begin(); it != nack_list_.end();
     165             :          ++it)
     166           0 :       it->second.time_to_play_ms = TimeToPlay(it->second.estimated_timestamp);
     167             :   } else {
     168           0 :     assert(sequence_number == sequence_num_last_decoded_rtp_);
     169             : 
     170             :     // Same sequence number as before. 10 ms is elapsed, update estimations for
     171             :     // time-to-play.
     172           0 :     UpdateEstimatedPlayoutTimeBy10ms();
     173             : 
     174             :     // Update timestamp for better estimate of time-to-play, for packets which
     175             :     // are added to NACK list later on.
     176           0 :     timestamp_last_decoded_rtp_ += sample_rate_khz_ * 10;
     177             :   }
     178           0 :   any_rtp_decoded_ = true;
     179           0 : }
     180             : 
     181           0 : NackTracker::NackList NackTracker::GetNackList() const {
     182           0 :   return nack_list_;
     183             : }
     184             : 
     185           0 : void NackTracker::Reset() {
     186           0 :   nack_list_.clear();
     187             : 
     188           0 :   sequence_num_last_received_rtp_ = 0;
     189           0 :   timestamp_last_received_rtp_ = 0;
     190           0 :   any_rtp_received_ = false;
     191           0 :   sequence_num_last_decoded_rtp_ = 0;
     192           0 :   timestamp_last_decoded_rtp_ = 0;
     193           0 :   any_rtp_decoded_ = false;
     194           0 :   sample_rate_khz_ = kDefaultSampleRateKhz;
     195           0 :   samples_per_packet_ = sample_rate_khz_ * kDefaultPacketSizeMs;
     196           0 : }
     197             : 
     198           0 : void NackTracker::SetMaxNackListSize(size_t max_nack_list_size) {
     199           0 :   RTC_CHECK_GT(max_nack_list_size, 0);
     200             :   // Ugly hack to get around the problem of passing static consts by reference.
     201           0 :   const size_t kNackListSizeLimitLocal = NackTracker::kNackListSizeLimit;
     202           0 :   RTC_CHECK_LE(max_nack_list_size, kNackListSizeLimitLocal);
     203             : 
     204           0 :   max_nack_list_size_ = max_nack_list_size;
     205           0 :   LimitNackListSize();
     206           0 : }
     207             : 
     208           0 : void NackTracker::LimitNackListSize() {
     209           0 :   uint16_t limit = sequence_num_last_received_rtp_ -
     210           0 :                    static_cast<uint16_t>(max_nack_list_size_) - 1;
     211           0 :   nack_list_.erase(nack_list_.begin(), nack_list_.upper_bound(limit));
     212           0 : }
     213             : 
     214           0 : int64_t NackTracker::TimeToPlay(uint32_t timestamp) const {
     215           0 :   uint32_t timestamp_increase = timestamp - timestamp_last_decoded_rtp_;
     216           0 :   return timestamp_increase / sample_rate_khz_;
     217             : }
     218             : 
     219             : // We don't erase elements with time-to-play shorter than round-trip-time.
     220           0 : std::vector<uint16_t> NackTracker::GetNackList(
     221             :     int64_t round_trip_time_ms) const {
     222           0 :   RTC_DCHECK_GE(round_trip_time_ms, 0);
     223           0 :   std::vector<uint16_t> sequence_numbers;
     224           0 :   for (NackList::const_iterator it = nack_list_.begin(); it != nack_list_.end();
     225             :        ++it) {
     226           0 :     if (it->second.is_missing &&
     227           0 :         it->second.time_to_play_ms > round_trip_time_ms)
     228           0 :       sequence_numbers.push_back(it->first);
     229             :   }
     230           0 :   return sequence_numbers;
     231             : }
     232             : 
     233             : }  // namespace webrtc

Generated by: LCOV version 1.13