Home | History | Annotate | Download | only in neteq
      1 /*
      2  *  Copyright (c) 2012 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/delay_peak_detector.h"
     12 
     13 #include <algorithm>  // max
     14 
     15 namespace webrtc {
     16 
     17 // The DelayPeakDetector keeps track of severe inter-arrival times, called
     18 // delay peaks. When a peak is observed, the "height" (the time elapsed since
     19 // the previous packet arrival) and the peak "period" (the time since the last
     20 // observed peak) is recorded in a vector. When enough peaks have been observed,
     21 // peak-mode is engaged and the DelayManager asks the DelayPeakDetector for
     22 // the worst peak height.
     23 
     24 DelayPeakDetector::~DelayPeakDetector() = default;
     25 
     26 DelayPeakDetector::DelayPeakDetector()
     27   : peak_found_(false),
     28     peak_detection_threshold_(0),
     29     peak_period_counter_ms_(-1) {
     30 }
     31 
     32 void DelayPeakDetector::Reset() {
     33   peak_period_counter_ms_ = -1;  // Indicate that next peak is the first.
     34   peak_found_ = false;
     35   peak_history_.clear();
     36 }
     37 
     38 // Calculates the threshold in number of packets.
     39 void DelayPeakDetector::SetPacketAudioLength(int length_ms) {
     40   if (length_ms > 0) {
     41     peak_detection_threshold_ = kPeakHeightMs / length_ms;
     42   }
     43 }
     44 
     45 bool DelayPeakDetector::peak_found() {
     46   return peak_found_;
     47 }
     48 
     49 int DelayPeakDetector::MaxPeakHeight() const {
     50   int max_height = -1;  // Returns -1 for an empty history.
     51   std::list<Peak>::const_iterator it;
     52   for (it = peak_history_.begin(); it != peak_history_.end(); ++it) {
     53     max_height = std::max(max_height, it->peak_height_packets);
     54   }
     55   return max_height;
     56 }
     57 
     58 int DelayPeakDetector::MaxPeakPeriod() const {
     59   int max_period = -1;  // Returns -1 for an empty history.
     60   std::list<Peak>::const_iterator it;
     61   for (it = peak_history_.begin(); it != peak_history_.end(); ++it) {
     62     max_period = std::max(max_period, it->period_ms);
     63   }
     64   return max_period;
     65 }
     66 
     67 bool DelayPeakDetector::Update(int inter_arrival_time, int target_level) {
     68   if (inter_arrival_time > target_level + peak_detection_threshold_ ||
     69       inter_arrival_time > 2 * target_level) {
     70     // A delay peak is observed.
     71     if (peak_period_counter_ms_ == -1) {
     72       // This is the first peak. Reset the period counter.
     73       peak_period_counter_ms_ = 0;
     74     } else if (peak_period_counter_ms_ <= kMaxPeakPeriodMs) {
     75       // This is not the first peak, and the period is valid.
     76       // Store peak data in the vector.
     77       Peak peak_data;
     78       peak_data.period_ms = peak_period_counter_ms_;
     79       peak_data.peak_height_packets = inter_arrival_time;
     80       peak_history_.push_back(peak_data);
     81       while (peak_history_.size() > kMaxNumPeaks) {
     82         // Delete the oldest data point.
     83         peak_history_.pop_front();
     84       }
     85       peak_period_counter_ms_ = 0;
     86     } else if (peak_period_counter_ms_ <= 2 * kMaxPeakPeriodMs) {
     87       // Invalid peak due to too long period. Reset period counter and start
     88       // looking for next peak.
     89       peak_period_counter_ms_ = 0;
     90     } else {
     91       // More than 2 times the maximum period has elapsed since the last peak
     92       // was registered. It seams that the network conditions have changed.
     93       // Reset the peak statistics.
     94       Reset();
     95     }
     96   }
     97   return CheckPeakConditions();
     98 }
     99 
    100 void DelayPeakDetector::IncrementCounter(int inc_ms) {
    101   if (peak_period_counter_ms_ >= 0) {
    102     peak_period_counter_ms_ += inc_ms;
    103   }
    104 }
    105 
    106 bool DelayPeakDetector::CheckPeakConditions() {
    107   size_t s = peak_history_.size();
    108   if (s >= kMinPeaksToTrigger &&
    109       peak_period_counter_ms_ <= 2 * MaxPeakPeriod()) {
    110     peak_found_ = true;
    111   } else {
    112     peak_found_ = false;
    113   }
    114   return peak_found_;
    115 }
    116 }  // namespace webrtc
    117