diff --git a/src/modules/rtp_rtcp/source/overuse_detector.cc b/src/modules/rtp_rtcp/source/overuse_detector.cc index 4cffb0f655..be609eeca4 100644 --- a/src/modules/rtp_rtcp/source/overuse_detector.cc +++ b/src/modules/rtp_rtcp/source/overuse_detector.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -8,19 +8,19 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include +#include // abs #if _WIN32 #include #endif -#include "trace.h" -#include "overuse_detector.h" -#include "remote_rate_control.h" -#include "rtp_utility.h" -#include -#include //abs +#include "modules/rtp_rtcp/source/overuse_detector.h" +#include "modules/rtp_rtcp/source/remote_rate_control.h" +#include "modules/rtp_rtcp/source/rtp_utility.h" +#include "system_wrappers/interface/trace.h" #ifdef WEBRTC_BWE_MATLAB -extern MatlabEngine eng; // global variable defined elsewhere +extern MatlabEngine eng; // global variable defined elsewhere #endif #define INIT_CAPACITY_SLOPE 8.0/512.0 @@ -30,421 +30,394 @@ extern MatlabEngine eng; // global variable defined elsewhere namespace webrtc { OverUseDetector::OverUseDetector() -: -_firstPacket(true), -_currentFrame(), -_prevFrame(), -_numOfDeltas(0), -_slope(INIT_CAPACITY_SLOPE), -_offset(0), -_E(), -_processNoise(), -_avgNoise(0.0), -_varNoise(500), -_threshold(DETECTOR_THRESHOLD), -_tsDeltaHist(), -_prevOffset(0.0), -_timeOverUsing(-1), -_overUseCounter(0), -_hypothesis(kBwNormal) -#ifdef WEBRTC_BWE_MATLAB -,_plot1(NULL), -_plot2(NULL), -_plot3(NULL), -_plot4(NULL) + : firstPacket_(true), + currentFrame_(), + prevFrame_(), + numOfDeltas_(0), + slope_(INIT_CAPACITY_SLOPE), + offset_(0), + E_(), + processNoise_(), + avgNoise_(0.0), + varNoise_(500), + threshold_(DETECTOR_THRESHOLD), + tsDeltaHist_(), + prevOffset_(0.0), + timeOverUsing_(-1), + overUseCounter_(0), +#ifndef WEBRTC_BWE_MATLAB + hypothesis_(kBwNormal) { +#else + plot1_(NULL), + plot2_(NULL), + plot3_(NULL), + plot4_(NULL) { #endif -{ - _E[0][0] = 100; - _E[1][1] = 1e-1; - _E[0][1] = _E[1][0] = 0; - _processNoise[0] = 1e-10; - _processNoise[1] = 1e-2; + E_[0][0] = 100; + E_[1][1] = 1e-1; + E_[0][1] = E_[1][0] = 0; + processNoise_[0] = 1e-10; + processNoise_[1] = 1e-2; } -OverUseDetector::~OverUseDetector() -{ +OverUseDetector::~OverUseDetector() { #ifdef WEBRTC_BWE_MATLAB - if (_plot1) - { - eng.DeletePlot(_plot1); - _plot1 = NULL; - } - if (_plot2) - { - eng.DeletePlot(_plot2); - _plot2 = NULL; - } - if (_plot3) - { - eng.DeletePlot(_plot3); - _plot3 = NULL; - } - if (_plot4) - { - eng.DeletePlot(_plot4); - _plot4 = NULL; - } + if (plot1_) { + eng.DeletePlot(plot1_); + plot1_ = NULL; + } + if (plot2_) { + eng.DeletePlot(plot2_); + plot2_ = NULL; + } + if (plot3_) { + eng.DeletePlot(plot3_); + plot3_ = NULL; + } + if (plot4_) { + eng.DeletePlot(plot4_); + plot4_ = NULL; + } #endif - _tsDeltaHist.clear(); + tsDeltaHist_.clear(); } -void OverUseDetector::Reset() -{ - _firstPacket = true; - _currentFrame._size = 0; - _currentFrame._completeTimeMs = -1; - _currentFrame._timestamp = -1; - _prevFrame._size = 0; - _prevFrame._completeTimeMs = -1; - _prevFrame._timestamp = -1; - _numOfDeltas = 0; - _slope = INIT_CAPACITY_SLOPE; - _offset = 0; - _E[0][0] = 100; - _E[1][1] = 1e-1; - _E[0][1] = _E[1][0] = 0; - _processNoise[0] = 1e-10; - _processNoise[1] = 1e-2; - _avgNoise = 0.0; - _varNoise = 500; - _threshold = DETECTOR_THRESHOLD; - _prevOffset = 0.0; - _timeOverUsing = -1; - _overUseCounter = 0; - _hypothesis = kBwNormal; - _tsDeltaHist.clear(); +void OverUseDetector::Reset() { + firstPacket_ = true; + currentFrame_.size_ = 0; + currentFrame_.completeTimeMs_ = -1; + currentFrame_.timestamp_ = -1; + prevFrame_.size_ = 0; + prevFrame_.completeTimeMs_ = -1; + prevFrame_.timestamp_ = -1; + numOfDeltas_ = 0; + slope_ = INIT_CAPACITY_SLOPE; + offset_ = 0; + E_[0][0] = 100; + E_[1][1] = 1e-1; + E_[0][1] = E_[1][0] = 0; + processNoise_[0] = 1e-10; + processNoise_[1] = 1e-2; + avgNoise_ = 0.0; + varNoise_ = 500; + threshold_ = DETECTOR_THRESHOLD; + prevOffset_ = 0.0; + timeOverUsing_ = -1; + overUseCounter_ = 0; + hypothesis_ = kBwNormal; + tsDeltaHist_.clear(); } bool OverUseDetector::Update(const WebRtcRTPHeader& rtpHeader, const WebRtc_UWord16 packetSize, - const WebRtc_Word64 nowMS) -{ + const WebRtc_Word64 nowMS) { #ifdef WEBRTC_BWE_MATLAB - // Create plots - const WebRtc_Word64 startTimeMs = nowMS; - if (_plot1 == NULL) - { - _plot1 = eng.NewPlot(new MatlabPlot()); - _plot1->AddLine(1000, "b.", "scatter"); - } - if (_plot2 == NULL) - { - _plot2 = eng.NewPlot(new MatlabPlot()); - _plot2->AddTimeLine(30, "b", "offset", startTimeMs); - _plot2->AddTimeLine(30, "r--", "limitPos", startTimeMs); - _plot2->AddTimeLine(30, "k.", "trigger", startTimeMs); - _plot2->AddTimeLine(30, "ko", "detection", startTimeMs); - //_plot2->AddTimeLine(30, "g", "slowMean", startTimeMs); - } - if (_plot3 == NULL) - { - _plot3 = eng.NewPlot(new MatlabPlot()); - _plot3->AddTimeLine(30, "b", "noiseVar", startTimeMs); - } - if (_plot4 == NULL) - { - _plot4 = eng.NewPlot(new MatlabPlot()); - //_plot4->AddTimeLine(60, "b", "p11", startTimeMs); - //_plot4->AddTimeLine(60, "r", "p12", startTimeMs); - _plot4->AddTimeLine(60, "g", "p22", startTimeMs); - //_plot4->AddTimeLine(60, "g--", "p22_hat", startTimeMs); - //_plot4->AddTimeLine(30, "b.-", "deltaFs", startTimeMs); - } + // Create plots + const WebRtc_Word64 startTimeMs = nowMS; + if (plot1_ == NULL) { + plot1_ = eng.NewPlot(new MatlabPlot()); + plot1_->AddLine(1000, "b.", "scatter"); + } + if (plot2_ == NULL) { + plot2_ = eng.NewPlot(new MatlabPlot()); + plot2_->AddTimeLine(30, "b", "offset", startTimeMs); + plot2_->AddTimeLine(30, "r--", "limitPos", startTimeMs); + plot2_->AddTimeLine(30, "k.", "trigger", startTimeMs); + plot2_->AddTimeLine(30, "ko", "detection", startTimeMs); + // plot2_->AddTimeLine(30, "g", "slowMean", startTimeMs); + } + if (plot3_ == NULL) { + plot3_ = eng.NewPlot(new MatlabPlot()); + plot3_->AddTimeLine(30, "b", "noiseVar", startTimeMs); + } + if (plot4_ == NULL) { + plot4_ = eng.NewPlot(new MatlabPlot()); + // plot4_->AddTimeLine(60, "b", "p11", startTimeMs); + // plot4_->AddTimeLine(60, "r", "p12", startTimeMs); + plot4_->AddTimeLine(60, "g", "p22", startTimeMs); + // plot4_->AddTimeLine(60, "g--", "p22_hat", startTimeMs); + // plot4_->AddTimeLine(30, "b.-", "deltaFs", startTimeMs); + } #endif - bool wrapped = false; - bool completeFrame = false; - if (_currentFrame._timestamp == -1) - { - _currentFrame._timestamp = rtpHeader.header.timestamp; - } - else if (ModuleRTPUtility::OldTimestamp( - rtpHeader.header.timestamp, - static_cast(_currentFrame._timestamp), - &wrapped)) - { - // Don't update with old data - return completeFrame; - } - else if (rtpHeader.header.timestamp != _currentFrame._timestamp) - { - // First packet of a later frame, the previous frame sample is ready - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "Frame complete at %I64i", _currentFrame._completeTimeMs); - if (_prevFrame._completeTimeMs >= 0) // This is our second frame - { - WebRtc_Word64 tDelta = 0; - double tsDelta = 0; - // Check for wrap - ModuleRTPUtility::OldTimestamp( - static_cast(_prevFrame._timestamp), - static_cast(_currentFrame._timestamp), - &wrapped); - CompensatedTimeDelta(_currentFrame, _prevFrame, tDelta, tsDelta, wrapped); - UpdateKalman(tDelta, tsDelta, _currentFrame._size, _prevFrame._size); - } - // The new timestamp is now the current frame, - // and the old timestamp becomes the previous frame. - _prevFrame = _currentFrame; - _currentFrame._timestamp = rtpHeader.header.timestamp; - _currentFrame._size = 0; - _currentFrame._completeTimeMs = -1; - completeFrame = true; - } - // Accumulate the frame size - _currentFrame._size += packetSize; - _currentFrame._completeTimeMs = nowMS; + bool wrapped = false; + bool completeFrame = false; + if (currentFrame_.timestamp_ == -1) { + currentFrame_.timestamp_ = rtpHeader.header.timestamp; + } else if (ModuleRTPUtility::OldTimestamp( + rtpHeader.header.timestamp, + static_cast(currentFrame_.timestamp_), + &wrapped)) { + // Don't update with old data return completeFrame; + } else if (rtpHeader.header.timestamp != currentFrame_.timestamp_) { + // First packet of a later frame, the previous frame sample is ready + WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, + "Frame complete at %I64i", currentFrame_.completeTimeMs_); + if (prevFrame_.completeTimeMs_ >= 0) { // This is our second frame + WebRtc_Word64 tDelta = 0; + double tsDelta = 0; + // Check for wrap + ModuleRTPUtility::OldTimestamp( + static_cast(prevFrame_.timestamp_), + static_cast(currentFrame_.timestamp_), + &wrapped); + CompensatedTimeDelta(currentFrame_, prevFrame_, tDelta, tsDelta, + wrapped); + UpdateKalman(tDelta, tsDelta, currentFrame_.size_, + prevFrame_.size_); + } + // The new timestamp is now the current frame, + // and the old timestamp becomes the previous frame. + prevFrame_ = currentFrame_; + currentFrame_.timestamp_ = rtpHeader.header.timestamp; + currentFrame_.size_ = 0; + currentFrame_.completeTimeMs_ = -1; + completeFrame = true; + } + // Accumulate the frame size + currentFrame_.size_ += packetSize; + currentFrame_.completeTimeMs_ = nowMS; + return completeFrame; } -BandwidthUsage OverUseDetector::State() const -{ - return _hypothesis; +BandwidthUsage OverUseDetector::State() const { + return hypothesis_; } -double OverUseDetector::NoiseVar() const -{ - return _varNoise; +double OverUseDetector::NoiseVar() const { + return varNoise_; } -void OverUseDetector::SetRateControlRegion(RateControlRegion region) -{ - switch (region) - { - case kRcMaxUnknown: - { - _threshold = DETECTOR_THRESHOLD; - break; - } +void OverUseDetector::SetRateControlRegion(RateControlRegion region) { + switch (region) { + case kRcMaxUnknown: { + threshold_ = DETECTOR_THRESHOLD; + break; + } case kRcAboveMax: - case kRcNearMax: - { - _threshold = DETECTOR_THRESHOLD / 2; - break; - } + case kRcNearMax: { + threshold_ = DETECTOR_THRESHOLD / 2; + break; } + } } -void OverUseDetector::CompensatedTimeDelta(const FrameSample& currentFrame, const FrameSample& prevFrame, WebRtc_Word64& tDelta, - double& tsDelta, bool wrapped) -{ - _numOfDeltas++; - if (_numOfDeltas > 1000) - { - _numOfDeltas = 1000; - } - // Add wrap-around compensation - WebRtc_Word64 wrapCompensation = 0; - if (wrapped) - { - wrapCompensation = static_cast(1)<<32; - } - tsDelta = (currentFrame._timestamp + wrapCompensation - prevFrame._timestamp) / 90.0; - tDelta = currentFrame._completeTimeMs - prevFrame._completeTimeMs; - assert(tsDelta > 0); +void OverUseDetector::CompensatedTimeDelta(const FrameSample& currentFrame, + const FrameSample& prevFrame, + WebRtc_Word64& tDelta, + double& tsDelta, + bool wrapped) { + numOfDeltas_++; + if (numOfDeltas_ > 1000) { + numOfDeltas_ = 1000; + } + // Add wrap-around compensation + WebRtc_Word64 wrapCompensation = 0; + if (wrapped) { + wrapCompensation = static_cast(1)<<32; + } + tsDelta = (currentFrame.timestamp_ + + wrapCompensation + - prevFrame.timestamp_) / 90.0; + tDelta = currentFrame.completeTimeMs_ - prevFrame.completeTimeMs_; + assert(tsDelta > 0); } -double OverUseDetector::CurrentDrift() -{ - return 1.0; +double OverUseDetector::CurrentDrift() { + return 1.0; } -void OverUseDetector::UpdateKalman(WebRtc_Word64 tDelta, double tsDelta, WebRtc_UWord32 frameSize, WebRtc_UWord32 prevFrameSize) -{ - const double minFramePeriod = UpdateMinFramePeriod(tsDelta); - const double drift = CurrentDrift(); - // Compensate for drift - const double tTsDelta = tDelta - tsDelta / drift; - double fsDelta = static_cast(frameSize) - prevFrameSize; +void OverUseDetector::UpdateKalman(WebRtc_Word64 tDelta, + double tsDelta, + WebRtc_UWord32 frameSize, + WebRtc_UWord32 prevFrameSize) { + const double minFramePeriod = UpdateMinFramePeriod(tsDelta); + const double drift = CurrentDrift(); + // Compensate for drift + const double tTsDelta = tDelta - tsDelta / drift; + double fsDelta = static_cast(frameSize) - prevFrameSize; - // Update the Kalman filter - const double scaleFactor = minFramePeriod / (1000.0 / 30.0); - _E[0][0] += _processNoise[0] * scaleFactor; - _E[1][1] += _processNoise[1] * scaleFactor; + // Update the Kalman filter + const double scaleFactor = minFramePeriod / (1000.0 / 30.0); + E_[0][0] += processNoise_[0] * scaleFactor; + E_[1][1] += processNoise_[1] * scaleFactor; - if ((_hypothesis == kBwOverusing && _offset < _prevOffset) || - (_hypothesis == kBwUnderUsing && _offset > _prevOffset)) - { - _E[1][1] += 10 * _processNoise[1] * scaleFactor; - } + if ((hypothesis_ == kBwOverusing && offset_ < prevOffset_) || + (hypothesis_ == kBwUnderUsing && offset_ > prevOffset_)) { + E_[1][1] += 10 * processNoise_[1] * scaleFactor; + } - const double h[2] = {fsDelta, 1.0}; - const double Eh[2] = {_E[0][0]*h[0] + _E[0][1]*h[1], - _E[1][0]*h[0] + _E[1][1]*h[1]}; + const double h[2] = {fsDelta, 1.0}; + const double Eh[2] = {E_[0][0]*h[0] + E_[0][1]*h[1], + E_[1][0]*h[0] + E_[1][1]*h[1]}; - const double residual = tTsDelta - _slope*h[0] - _offset; + const double residual = tTsDelta - slope_*h[0] - offset_; - const bool stableState = (BWE_MIN(_numOfDeltas, 60) * abs(_offset) < _threshold); - // We try to filter out very late frames. For instance periodic key - // frames doesn't fit the Gaussian model well. - if (abs(residual) < 3 * sqrt(_varNoise)) - { - UpdateNoiseEstimate(residual, minFramePeriod, stableState); - } - else - { - UpdateNoiseEstimate(3 * sqrt(_varNoise), minFramePeriod, stableState); - } + const bool stableState = + (BWE_MIN(numOfDeltas_, 60) * abs(offset_) < threshold_); + // We try to filter out very late frames. For instance periodic key + // frames doesn't fit the Gaussian model well. + if (abs(residual) < 3 * sqrt(varNoise_)) { + UpdateNoiseEstimate(residual, minFramePeriod, stableState); + } else { + UpdateNoiseEstimate(3 * sqrt(varNoise_), minFramePeriod, stableState); + } - const double denom = _varNoise + h[0]*Eh[0] + h[1]*Eh[1]; + const double denom = varNoise_ + h[0]*Eh[0] + h[1]*Eh[1]; - const double K[2] = {Eh[0] / denom, - Eh[1] / denom}; + const double K[2] = {Eh[0] / denom, + Eh[1] / denom}; - const double IKh[2][2] = {{1.0 - K[0]*h[0], -K[0]*h[1]}, - {-K[1]*h[0], 1.0 - K[1]*h[1]}}; - const double e00 = _E[0][0]; - const double e01 = _E[0][1]; + const double IKh[2][2] = {{1.0 - K[0]*h[0], -K[0]*h[1]}, + {-K[1]*h[0], 1.0 - K[1]*h[1]}}; + const double e00 = E_[0][0]; + const double e01 = E_[0][1]; - // Update state - _E[0][0] = e00 * IKh[0][0] + _E[1][0] * IKh[0][1]; - _E[0][1] = e01 * IKh[0][0] + _E[1][1] * IKh[0][1]; - _E[1][0] = e00 * IKh[1][0] + _E[1][0] * IKh[1][1]; - _E[1][1] = e01 * IKh[1][0] + _E[1][1] * IKh[1][1]; + // Update state + E_[0][0] = e00 * IKh[0][0] + E_[1][0] * IKh[0][1]; + E_[0][1] = e01 * IKh[0][0] + E_[1][1] * IKh[0][1]; + E_[1][0] = e00 * IKh[1][0] + E_[1][0] * IKh[1][1]; + E_[1][1] = e01 * IKh[1][0] + E_[1][1] * IKh[1][1]; - // Covariance matrix, must be positive semi-definite - assert(_E[0][0] + _E[1][1] >= 0 && - _E[0][0] * _E[1][1] - _E[0][1] * _E[1][0] >= 0 && - _E[0][0] >= 0); + // Covariance matrix, must be positive semi-definite + assert(E_[0][0] + E_[1][1] >= 0 && + E_[0][0] * E_[1][1] - E_[0][1] * E_[1][0] >= 0 && + E_[0][0] >= 0); #ifdef WEBRTC_BWE_MATLAB - //_plot4->Append("p11",_E[0][0]); - //_plot4->Append("p12",_E[0][1]); - _plot4->Append("p22",_E[1][1]); - //_plot4->Append("p22_hat", 0.5*(_processNoise[1] + - // sqrt(_processNoise[1]*(_processNoise[1] + 4*_varNoise)))); - //_plot4->Append("deltaFs", fsDelta); - _plot4->Plot(); + // plot4_->Append("p11",E_[0][0]); + // plot4_->Append("p12",E_[0][1]); + plot4_->Append("p22", E_[1][1]); + // plot4_->Append("p22_hat", 0.5*(processNoise_[1] + + // sqrt(processNoise_[1]*(processNoise_[1] + 4*varNoise_)))); + // plot4_->Append("deltaFs", fsDelta); + plot4_->Plot(); #endif - _slope = _slope + K[0] * residual; - _prevOffset = _offset; - _offset = _offset + K[1] * residual; + slope_ = slope_ + K[0] * residual; + prevOffset_ = offset_; + offset_ = offset_ + K[1] * residual; - Detect(tsDelta); + Detect(tsDelta); #ifdef WEBRTC_BWE_MATLAB - _plot1->Append("scatter", static_cast(_currentFrame._size) - _prevFrame._size, - static_cast(tDelta-tsDelta)); - _plot1->MakeTrend("scatter", "slope", _slope, _offset, "k-"); - _plot1->MakeTrend("scatter", "thresholdPos", _slope, _offset + 2 * sqrt(_varNoise), "r-"); - _plot1->MakeTrend("scatter", "thresholdNeg", _slope, _offset - 2 * sqrt(_varNoise), "r-"); - _plot1->Plot(); + plot1_->Append("scatter", + static_cast(currentFrame_.size_) - prevFrame_.size_, + static_cast(tDelta-tsDelta)); + plot1_->MakeTrend("scatter", "slope", slope_, offset_, "k-"); + plot1_->MakeTrend("scatter", "thresholdPos", + slope_, offset_ + 2 * sqrt(varNoise_), "r-"); + plot1_->MakeTrend("scatter", "thresholdNeg", + slope_, offset_ - 2 * sqrt(varNoise_), "r-"); + plot1_->Plot(); - _plot2->Append("offset", _offset); - _plot2->Append("limitPos", _threshold/BWE_MIN(_numOfDeltas, 60)); - _plot2->Plot(); + plot2_->Append("offset", offset_); + plot2_->Append("limitPos", threshold_/BWE_MIN(numOfDeltas_, 60)); + plot2_->Plot(); - _plot3->Append("noiseVar", _varNoise); - _plot3->Plot(); + plot3_->Append("noiseVar", varNoise_); + plot3_->Plot(); #endif } double OverUseDetector::UpdateMinFramePeriod(double tsDelta) { double minFramePeriod = tsDelta; - if (_tsDeltaHist.size() >= MIN_FRAME_PERIOD_HISTORY_LEN) { - std::list::iterator firstItem = _tsDeltaHist.begin(); - _tsDeltaHist.erase(firstItem); + if (tsDeltaHist_.size() >= MIN_FRAME_PERIOD_HISTORY_LEN) { + std::list::iterator firstItem = tsDeltaHist_.begin(); + tsDeltaHist_.erase(firstItem); } - std::list::iterator it = _tsDeltaHist.begin(); - for (; it != _tsDeltaHist.end(); it++) { + std::list::iterator it = tsDeltaHist_.begin(); + for (; it != tsDeltaHist_.end(); it++) { minFramePeriod = BWE_MIN(*it, minFramePeriod); } - _tsDeltaHist.push_back(tsDelta); + tsDeltaHist_.push_back(tsDelta); return minFramePeriod; } -void OverUseDetector::UpdateNoiseEstimate(double residual, double tsDelta, bool stableState) -{ - if (!stableState) - { - return; - } - // Faster filter during startup to faster adapt to the jitter level of the network - // alpha is tuned for 30 frames per second, but - double alpha = 0.01; - if (_numOfDeltas > 10*30) - { - alpha = 0.002; - } - // Only update the noise estimate if we're not over-using - // beta is a function of alpha and the time delta since - // the previous update. - const double beta = pow(1 - alpha, tsDelta * 30.0 / 1000.0); - _avgNoise = beta * _avgNoise + (1 - beta) * residual; - _varNoise = beta * _varNoise + (1 - beta) * (_avgNoise - residual) * (_avgNoise - residual); - if (_varNoise < 1e-7) - { - _varNoise = 1e-7; - } +void OverUseDetector::UpdateNoiseEstimate(double residual, + double tsDelta, + bool stableState) { + if (!stableState) { + return; + } + // Faster filter during startup to faster adapt to the jitter level + // of the network alpha is tuned for 30 frames per second, but + double alpha = 0.01; + if (numOfDeltas_ > 10*30) { + alpha = 0.002; + } + // Only update the noise estimate if we're not over-using + // beta is a function of alpha and the time delta since + // the previous update. + const double beta = pow(1 - alpha, tsDelta * 30.0 / 1000.0); + avgNoise_ = beta * avgNoise_ + + (1 - beta) * residual; + varNoise_ = beta * varNoise_ + + (1 - beta) * (avgNoise_ - residual) * (avgNoise_ - residual); + if (varNoise_ < 1e-7) { + varNoise_ = 1e-7; + } } -BandwidthUsage OverUseDetector::Detect(double tsDelta) -{ - if (_numOfDeltas < 2) - { - return kBwNormal; - } - const double T = BWE_MIN(_numOfDeltas, 60) * _offset; - if (abs(T) > _threshold) - { - if (_offset > 0) - { - if (_timeOverUsing == -1) - { - // Initialize the timer. Assume that we've been - // over-using half of the time since the previous - // sample. - _timeOverUsing = tsDelta / 2; - } - else - { - // Increment timer - _timeOverUsing += tsDelta; - } - _overUseCounter++; - if (_timeOverUsing > OVER_USING_TIME_THRESHOLD && _overUseCounter > 1) - { - if (_offset >= _prevOffset) - { +BandwidthUsage OverUseDetector::Detect(double tsDelta) { + if (numOfDeltas_ < 2) { + return kBwNormal; + } + const double T = BWE_MIN(numOfDeltas_, 60) * offset_; + if (abs(T) > threshold_) { + if (offset_ > 0) { + if (timeOverUsing_ == -1) { + // Initialize the timer. Assume that we've been + // over-using half of the time since the previous + // sample. + timeOverUsing_ = tsDelta / 2; + } else { + // Increment timer + timeOverUsing_ += tsDelta; + } + overUseCounter_++; + if (timeOverUsing_ > OVER_USING_TIME_THRESHOLD + && overUseCounter_ > 1) { + if (offset_ >= prevOffset_) { #ifdef _DEBUG - if (_hypothesis != kBwOverusing) - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwOverusing"); + if (hypothesis_ != kBwOverusing) { + WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwOverusing"); + } #endif - _timeOverUsing = 0; - _overUseCounter = 0; - _hypothesis = kBwOverusing; + timeOverUsing_ = 0; + overUseCounter_ = 0; + hypothesis_ = kBwOverusing; #ifdef WEBRTC_BWE_MATLAB - _plot2->Append("detection",_offset); // plot it later -#endif - } - } -#ifdef WEBRTC_BWE_MATLAB - _plot2->Append("trigger",_offset); // plot it later + plot2_->Append("detection", offset_); // plot it later #endif } - else - { -#ifdef _DEBUG - if (_hypothesis != kBwUnderUsing) - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwUnderUsing"); + } +#ifdef WEBRTC_BWE_MATLAB + plot2_->Append("trigger", offset_); // plot it later #endif - _timeOverUsing = -1; - _overUseCounter = 0; - _hypothesis = kBwUnderUsing; - } - } - else - { + } else { #ifdef _DEBUG - if (_hypothesis != kBwNormal) - WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwNormal"); + if (hypothesis_ != kBwUnderUsing) { + WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwUnderUsing"); + } #endif - _timeOverUsing = -1; - _overUseCounter = 0; - _hypothesis = kBwNormal; + timeOverUsing_ = -1; + overUseCounter_ = 0; + hypothesis_ = kBwUnderUsing; } - return _hypothesis; + } else { +#ifdef _DEBUG + if (hypothesis_ != kBwNormal) { + WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwNormal"); + } +#endif + timeOverUsing_ = -1; + overUseCounter_ = 0; + hypothesis_ = kBwNormal; + } + return hypothesis_; } -} // namespace webrtc +} // namespace webrtc diff --git a/src/modules/rtp_rtcp/source/overuse_detector.h b/src/modules/rtp_rtcp/source/overuse_detector.h index b250e01684..3b432fb0fb 100644 --- a/src/modules/rtp_rtcp/source/overuse_detector.h +++ b/src/modules/rtp_rtcp/source/overuse_detector.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source @@ -7,15 +7,14 @@ * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ - #ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_OVERUSE_DETECTOR_H_ #define WEBRTC_MODULES_RTP_RTCP_SOURCE_OVERUSE_DETECTOR_H_ #include -#include "bwe_defines.h" -#include "module_common_types.h" -#include "typedefs.h" +#include "modules/interface/module_common_types.h" +#include "modules/rtp_rtcp/source/bwe_defines.h" +#include "typedefs.h" // NOLINT(build/include) #ifdef WEBRTC_BWE_MATLAB #include "../test/BWEStandAlone/MatlabPlot.h" @@ -24,67 +23,65 @@ namespace webrtc { enum RateControlRegion; -class OverUseDetector -{ -public: - OverUseDetector(); - ~OverUseDetector(); - bool Update(const WebRtcRTPHeader& rtpHeader, - const WebRtc_UWord16 packetSize, - const WebRtc_Word64 nowMS); - BandwidthUsage State() const; - void Reset(); - double NoiseVar() const; - void SetRateControlRegion(RateControlRegion region); +class OverUseDetector { + public: + OverUseDetector(); + ~OverUseDetector(); + bool Update(const WebRtcRTPHeader& rtpHeader, + const WebRtc_UWord16 packetSize, + const WebRtc_Word64 nowMS); + BandwidthUsage State() const; + void Reset(); + double NoiseVar() const; + void SetRateControlRegion(RateControlRegion region); -private: - struct FrameSample - { - FrameSample() : _size(0), _completeTimeMs(-1), _timestamp(-1) {} + private: + struct FrameSample { + FrameSample() : size_(0), completeTimeMs_(-1), timestamp_(-1) {} - WebRtc_UWord32 _size; - WebRtc_Word64 _completeTimeMs; - WebRtc_Word64 _timestamp; - }; + WebRtc_UWord32 size_; + WebRtc_Word64 completeTimeMs_; + WebRtc_Word64 timestamp_; + }; - void CompensatedTimeDelta(const FrameSample& currentFrame, - const FrameSample& prevFrame, - WebRtc_Word64& tDelta, - double& tsDelta, - bool wrapped); - void UpdateKalman(WebRtc_Word64 tDelta, - double tsDelta, - WebRtc_UWord32 frameSize, - WebRtc_UWord32 prevFrameSize); - double UpdateMinFramePeriod(double tsDelta); - void UpdateNoiseEstimate(double residual, double tsDelta, bool stableState); - BandwidthUsage Detect(double tsDelta); - double CurrentDrift(); + void CompensatedTimeDelta(const FrameSample& currentFrame, + const FrameSample& prevFrame, + WebRtc_Word64& tDelta, + double& tsDelta, + bool wrapped); + void UpdateKalman(WebRtc_Word64 tDelta, + double tsDelta, + WebRtc_UWord32 frameSize, + WebRtc_UWord32 prevFrameSize); + double UpdateMinFramePeriod(double tsDelta); + void UpdateNoiseEstimate(double residual, double tsDelta, bool stableState); + BandwidthUsage Detect(double tsDelta); + double CurrentDrift(); - bool _firstPacket; - FrameSample _currentFrame; - FrameSample _prevFrame; - WebRtc_UWord16 _numOfDeltas; - double _slope; - double _offset; - double _E[2][2]; - double _processNoise[2]; - double _avgNoise; - double _varNoise; - double _threshold; - std::list _tsDeltaHist; - double _prevOffset; - double _timeOverUsing; - WebRtc_UWord16 _overUseCounter; - BandwidthUsage _hypothesis; + bool firstPacket_; + FrameSample currentFrame_; + FrameSample prevFrame_; + WebRtc_UWord16 numOfDeltas_; + double slope_; + double offset_; + double E_[2][2]; + double processNoise_[2]; + double avgNoise_; + double varNoise_; + double threshold_; + std::list tsDeltaHist_; + double prevOffset_; + double timeOverUsing_; + WebRtc_UWord16 overUseCounter_; + BandwidthUsage hypothesis_; #ifdef WEBRTC_BWE_MATLAB - MatlabPlot* _plot1; - MatlabPlot* _plot2; - MatlabPlot* _plot3; - MatlabPlot* _plot4; + MatlabPlot* plot1_; + MatlabPlot* plot2_; + MatlabPlot* plot3_; + MatlabPlot* plot4_; #endif }; -} // namespace webrtc +} // namespace webrtc -#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_OVERUSE_DETECTOR_H_ +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_OVERUSE_DETECTOR_H_