• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
DelayPeakDetector()24 DelayPeakDetector::DelayPeakDetector()
25   : peak_found_(false),
26     peak_detection_threshold_(0),
27     peak_period_counter_ms_(-1) {
28 }
29 
Reset()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.
SetPacketAudioLength(int length_ms)37 void DelayPeakDetector::SetPacketAudioLength(int length_ms) {
38   if (length_ms > 0) {
39     peak_detection_threshold_ = kPeakHeightMs / length_ms;
40   }
41 }
42 
MaxPeakHeight() const43 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 
MaxPeakPeriod() const52 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 
Update(int inter_arrival_time,int target_level)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 
IncrementCounter(int inc_ms)94 void DelayPeakDetector::IncrementCounter(int inc_ms) {
95   if (peak_period_counter_ms_ >= 0) {
96     peak_period_counter_ms_ += inc_ms;
97   }
98 }
99 
CheckPeakConditions()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