neteq 中的峰值检测原理如下:
a) 当interval_arrival_iat_packet 超过 target_level + 2 || interval_arrival_iat_packet > 2 * target_level的时候,认为这是一个峰值点
b) 记录该峰值点的高度(iat_packet)和该峰值点离上一个峰值点的间隔(period), 然后放入记录数组
bool DelayPeakDetector::Update(uint16_t seq, int inter_arrival_time, bool reordered, int target_level) {
current_iat_ = inter_arrival_time;
iat_count++;
if (reordered) {
reordered_count++;
}
if (inter_arrival_time > max_peak_) {
max_peak_ = inter_arrival_time;
}
if (ignore_reordered_packets_ && reordered) {
return CheckPeakConditions();
}
int peak_height = -1;
if (inter_arrival_time > target_level + peak_detection_threshold_ || inter_arrival_time > 2 * target_level) {
// A delay peak is observed.
if (!peak_period_stopwatch_) {
// This is the first peak. Reset the period counter.
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
} else if (peak_period_stopwatch_->ElapsedMs() > 0) {
if (peak_period_stopwatch_->ElapsedMs() <= kMaxPeakPeriodMs) {
// This is not the first peak, and the period is valid.
// Store peak data in the vector.
peak_count++;
// 记录该峰值点的高度(iat_packet)和该峰值点离上一个峰值点的间隔(period), 然后放入记录数组
Peak peak_data;
peak_data.period_ms = peak_period_stopwatch_->ElapsedMs() > 1000 ? 1000 : peak_period_stopwatch_->ElapsedMs();
peak_data.peak_height_packets = inter_arrival_time;
peak_history_.push_back(peak_data);
peak_height = peak_data.peak_height_packets;
//LOGD("peak detect height %d,period %d", inter_arrival_time, peak_period_stopwatch_->ElapsedMs());
while (peak_history_.size() > kMaxNumPeaks) {
// Delete the oldest data point.
peak_history_.pop_front();
}
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
} else if (peak_period_stopwatch_->ElapsedMs() <= 2 * kMaxPeakPeriodMs) {
// Invalid peak due to too long period. Reset period counter and start
// looking for next peak.
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
} else {
// More than 2 times the maximum period has elapsed since the last peak
// was registered. It seams that the network conditions have changed.
// Reset the peak statistics.
Reset();
}
}
}
// LOGD("[Neteq] iat-peak seq %d,iat %d,peak %d", seq, inter_arrival_time, peak_height);
MakeSmoothPeak();
return CheckPeakConditions();
}
c) 当记录数组中出现了峰值点>2个,且此时离峰值点间隔没有超过 2倍的峰值点间隔,则认为还处于检测到峰值点的状态
bool DelayPeakDetector::CheckPeakConditions() {
size_t s = peak_history_.size();
if (s >= kMinPeaksToTrigger && peak_period_stopwatch_->ElapsedMs() <= 2 * MaxPeakPeriod()) {
peak_found_ = true;
} else {
peak_found_ = false;
}
return peak_found_;
}
d) 每个采样点进来后,会不断判断记录数组中的max_height和当前进来的点的iat,如果进来的采样点的iat比较小,会对记录数组做插值插入新的峰值点,本质是对峰值点做平滑衰减,将peak渐渐平滑下来,知道平滑到接近当前的iat水平后,记录数组不会在加入新的值,就会出发c)的逻辑判断,认为此时不再处于峰值范围
void DelayPeakDetector::MakeSmoothPeak() {
if (peak_found_) {
if (peak_period_stopwatch_->ElapsedMs() >= MaxPeakPeriod()) {
int maxPeakHeight = MaxPeakHeight();
if (maxPeakHeight > (current_iat_ * 3 / 2) && current_iat_ != 0) {
// 不断的对历史最高峰值点进行平滑衰减,插入新的峰值点
// 直到不在高于 1.5的当前iat,既认为接近当前的iat时候,不再插值
// peak_period_stopwatch_将不再更新,则CheckPeakConditions()认为
// 不再判定最近有峰值点,脱离峰值状态
Peak peak_data;
peak_data.period_ms = peak_period_stopwatch_->ElapsedMs() >= 800 ? 800 : peak_period_stopwatch_->ElapsedMs();//todo 800?hardcode
peak_data.peak_height_packets = maxPeakHeight * 1 / 2;
peak_history_.push_back(peak_data);
// LOGD("[DelayPeakDetector] MakeAutoSmoothPeak peak %d,make peakHeight %d,period %d, ElapsedMs %d",
// maxPeakHeight,
// peak_data.peak_height_packets,
// peak_data.period_ms,
// peak_period_stopwatch_->ElapsedMs());
while (peak_history_.size() > kMaxNumPeaks) {
// Delete the oldest data point.
peak_history_.pop_front();
}
peak_period_stopwatch_ = tick_timer_->GetNewStopwatch();
}
}
}
}
标签:ElapsedMs,period,_-,peak,stopwatch,iat,detector,neteq
From: https://www.cnblogs.com/ishen/p/18008749