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