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()
     25   : peak_found_(false),
     26     peak_detection_threshold_(0),
     27     peak_period_counter_ms_(-1) {
     28 }
     29 
     30 void DelayPeakDetector::Reset() {
     31   peak_period_counter_ms_ = -1;  // Indicate that next peak is the first.
     32   peak_found_ = false;
     33   peak_history_.clear();
     34 }
     35 
     36 // Calculates the threshold in number of packets.
     37 void DelayPeakDetector::SetPacketAudioLength(int length_ms) {
     38   if (length_ms > 0) {
     39     peak_detection_threshold_ = kPeakHeightMs / length_ms;
     40   }
     41 }
     42 
     43 int DelayPeakDetector::MaxPeakHeight() const {
     44   int max_height = -1;  // Returns -1 for an empty history.
     45   std::list<Peak>::const_iterator it;
     46   for (it = peak_history_.begin(); it != peak_history_.end(); ++it) {
     47     max_height = std::max(max_height, it->peak_height_packets);
     48   }
     49   return max_height;
     50 }
     51 
     52 int DelayPeakDetector::MaxPeakPeriod() const {
     53   int max_period = -1;  // Returns -1 for an empty history.
     54   std::list<Peak>::const_iterator it;
     55   for (it = peak_history_.begin(); it != peak_history_.end(); ++it) {
     56     max_period = std::max(max_period, it->period_ms);
     57   }
     58   return max_period;
     59 }
     60 
     61 bool DelayPeakDetector::Update(int inter_arrival_time, int target_level) {
     62   if (inter_arrival_time > target_level + peak_detection_threshold_ ||
     63       inter_arrival_time > 2 * target_level) {
     64     // A delay peak is observed.
     65     if (peak_period_counter_ms_ == -1) {
     66       // This is the first peak. Reset the period counter.
     67       peak_period_counter_ms_ = 0;
     68     } else if (peak_period_counter_ms_ <= kMaxPeakPeriodMs) {
     69       // This is not the first peak, and the period is valid.
     70       // Store peak data in the vector.
     71       Peak peak_data;
     72       peak_data.period_ms = peak_period_counter_ms_;
     73       peak_data.peak_height_packets = inter_arrival_time;
     74       peak_history_.push_back(peak_data);
     75       while (peak_history_.size() > kMaxNumPeaks) {
     76         // Delete the oldest data point.
     77         peak_history_.pop_front();
     78       }
     79       peak_period_counter_ms_ = 0;
     80     } else if (peak_period_counter_ms_ <= 2 * kMaxPeakPeriodMs) {
     81       // Invalid peak due to too long period. Reset period counter and start
     82       // looking for next peak.
     83       peak_period_counter_ms_ = 0;
     84     } else {
     85       // More than 2 times the maximum period has elapsed since the last peak
     86       // was registered. It seams that the network conditions have changed.
     87       // Reset the peak statistics.
     88       Reset();
     89     }
     90   }
     91   return CheckPeakConditions();
     92 }
     93 
     94 void DelayPeakDetector::IncrementCounter(int inc_ms) {
     95   if (peak_period_counter_ms_ >= 0) {
     96     peak_period_counter_ms_ += inc_ms;
     97   }
     98 }
     99 
    100 bool DelayPeakDetector::CheckPeakConditions() {
    101   size_t s = peak_history_.size();
    102   if (s >= kMinPeaksToTrigger &&
    103       peak_period_counter_ms_ <= 2 * MaxPeakPeriod()) {
    104     peak_found_ = true;
    105   } else {
    106     peak_found_ = false;
    107   }
    108   return peak_found_;
    109 }
    110 }  // namespace webrtc
    111