neteq的peak detector解析

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();
      }
    }
  }
}
posted @ 2024-02-05 20:12  woder  阅读(42)  评论(0编辑  收藏  举报