Style guide reformatting of overuse_detector.{h,cc}
Review URL: https://webrtc-codereview.appspot.com/575006 git-svn-id: http://webrtc.googlecode.com/svn/trunk@2268 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
bd48e71058
commit
e231c61ba7
@ -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 <math.h>
|
||||
#include <stdlib.h> // abs
|
||||
#if _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "trace.h"
|
||||
#include "overuse_detector.h"
|
||||
#include "remote_rate_control.h"
|
||||
#include "rtp_utility.h"
|
||||
#include <math.h>
|
||||
#include <stdlib.h> //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<WebRtc_UWord32>(_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<WebRtc_UWord32>(_prevFrame._timestamp),
|
||||
static_cast<WebRtc_UWord32>(_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<WebRtc_UWord32>(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<WebRtc_UWord32>(prevFrame_.timestamp_),
|
||||
static_cast<WebRtc_UWord32>(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<WebRtc_Word64>(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<WebRtc_Word64>(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<double>(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<double>(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<double>(_currentFrame._size) - _prevFrame._size,
|
||||
static_cast<double>(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<double>(currentFrame_.size_) - prevFrame_.size_,
|
||||
static_cast<double>(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<double>::iterator firstItem = _tsDeltaHist.begin();
|
||||
_tsDeltaHist.erase(firstItem);
|
||||
if (tsDeltaHist_.size() >= MIN_FRAME_PERIOD_HISTORY_LEN) {
|
||||
std::list<double>::iterator firstItem = tsDeltaHist_.begin();
|
||||
tsDeltaHist_.erase(firstItem);
|
||||
}
|
||||
std::list<double>::iterator it = _tsDeltaHist.begin();
|
||||
for (; it != _tsDeltaHist.end(); it++) {
|
||||
std::list<double>::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
|
||||
|
||||
@ -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 <list>
|
||||
|
||||
#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<double> _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<double> 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_
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user