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