Apply Chromium C++ style to RemoteRateControl.
BUG= Review URL: https://webrtc-codereview.appspot.com/1329004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3919 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
@@ -10,89 +10,52 @@
|
|||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
|
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <algorithm>
|
||||||
#include <math.h>
|
#include <cassert>
|
||||||
#include <string.h>
|
#include <cmath>
|
||||||
#if _WIN32
|
#include <cstring>
|
||||||
#include <windows.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "system_wrappers/interface/trace.h"
|
#include "system_wrappers/interface/trace.h"
|
||||||
|
|
||||||
#ifdef MATLAB
|
|
||||||
extern MatlabEngine eng; // global variable defined elsewhere
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
const unsigned int kDefaultRttMs = 200;
|
const unsigned int kDefaultRttMs = 200;
|
||||||
|
|
||||||
RemoteRateControl::RemoteRateControl()
|
RemoteRateControl::RemoteRateControl()
|
||||||
:
|
: min_configured_bit_rate_(30000),
|
||||||
_minConfiguredBitRate(30000),
|
max_configured_bit_rate_(30000000),
|
||||||
_maxConfiguredBitRate(30000000),
|
current_bit_rate_(max_configured_bit_rate_),
|
||||||
_currentBitRate(_maxConfiguredBitRate),
|
max_hold_rate_(0),
|
||||||
_maxHoldRate(0),
|
avg_max_bit_rate_(-1.0f),
|
||||||
_avgMaxBitRate(-1.0f),
|
var_max_bit_rate_(0.4f),
|
||||||
_varMaxBitRate(0.4f),
|
rate_control_state_(kRcHold),
|
||||||
_rcState(kRcHold),
|
came_from_state_(kRcDecrease),
|
||||||
_cameFromState(kRcDecrease),
|
rate_control_region_(kRcMaxUnknown),
|
||||||
_rcRegion(kRcMaxUnknown),
|
last_bit_rate_change_(-1),
|
||||||
_lastBitRateChange(-1),
|
current_input_(kBwNormal, 0, 1.0),
|
||||||
_currentInput(kBwNormal, 0, 1.0),
|
updated_(false),
|
||||||
_updated(false),
|
time_first_incoming_estimate_(-1),
|
||||||
_timeFirstIncomingEstimate(-1),
|
initialized_bit_rate_(false),
|
||||||
_initializedBitRate(false),
|
avg_change_period_(1000.0f),
|
||||||
_avgChangePeriod(1000.0f),
|
last_change_ms_(-1),
|
||||||
_lastChangeMs(-1),
|
beta_(0.9f),
|
||||||
_beta(0.9f),
|
rtt_(kDefaultRttMs)
|
||||||
_rtt(kDefaultRttMs)
|
|
||||||
#ifdef MATLAB
|
|
||||||
,_plot1(NULL),
|
|
||||||
_plot2(NULL)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteRateControl::~RemoteRateControl()
|
void RemoteRateControl::Reset() {
|
||||||
{
|
*this = RemoteRateControl();
|
||||||
#ifdef MATLAB
|
came_from_state_ = kRcHold;
|
||||||
eng.DeletePlot(_plot1);
|
|
||||||
eng.DeletePlot(_plot2);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void RemoteRateControl::Reset()
|
|
||||||
{
|
|
||||||
_minConfiguredBitRate = 30000;
|
|
||||||
_maxConfiguredBitRate = 30000000;
|
|
||||||
_currentBitRate = _maxConfiguredBitRate;
|
|
||||||
_maxHoldRate = 0;
|
|
||||||
_avgMaxBitRate = -1.0f;
|
|
||||||
_varMaxBitRate = 0.4f;
|
|
||||||
_rcState = kRcHold;
|
|
||||||
_cameFromState = kRcHold;
|
|
||||||
_rcRegion = kRcMaxUnknown;
|
|
||||||
_lastBitRateChange = -1;
|
|
||||||
_avgChangePeriod = 1000.0f;
|
|
||||||
_lastChangeMs = -1;
|
|
||||||
_beta = 0.9f;
|
|
||||||
_currentInput._bwState = kBwNormal;
|
|
||||||
_currentInput._incomingBitRate = 0;
|
|
||||||
_currentInput._noiseVar = 1.0;
|
|
||||||
_updated = false;
|
|
||||||
_timeFirstIncomingEstimate = -1;
|
|
||||||
_initializedBitRate = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoteRateControl::ValidEstimate() const {
|
bool RemoteRateControl::ValidEstimate() const {
|
||||||
return _initializedBitRate;
|
return initialized_bit_rate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RemoteRateControl::TimeToReduceFurther(
|
bool RemoteRateControl::TimeToReduceFurther(int64_t time_now,
|
||||||
int64_t time_now, unsigned int incoming_bitrate) const {
|
unsigned int incoming_bitrate) const {
|
||||||
const int bitrate_reduction_interval = BWE_MAX(BWE_MIN(_rtt, 200), 10);
|
const int bitrate_reduction_interval = std::max(std::min(rtt_, 200u), 10u);
|
||||||
if (time_now - _lastBitRateChange >= bitrate_reduction_interval) {
|
if (time_now - last_bit_rate_change_ >= bitrate_reduction_interval) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (ValidEstimate()) {
|
if (ValidEstimate()) {
|
||||||
@@ -103,405 +66,319 @@ bool RemoteRateControl::TimeToReduceFurther(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t RemoteRateControl::SetConfiguredBitRates(
|
int32_t RemoteRateControl::SetConfiguredBitRates(uint32_t min_bit_rate_bps,
|
||||||
uint32_t minBitRateBps, uint32_t maxBitRateBps)
|
uint32_t max_bit_rate_bps) {
|
||||||
{
|
if (min_bit_rate_bps > max_bit_rate_bps) {
|
||||||
if (minBitRateBps > maxBitRateBps)
|
return -1;
|
||||||
{
|
}
|
||||||
return -1;
|
min_configured_bit_rate_ = min_bit_rate_bps;
|
||||||
}
|
max_configured_bit_rate_ = max_bit_rate_bps;
|
||||||
_minConfiguredBitRate = minBitRateBps;
|
current_bit_rate_ = std::min(std::max(min_bit_rate_bps, current_bit_rate_),
|
||||||
_maxConfiguredBitRate = maxBitRateBps;
|
max_bit_rate_bps);
|
||||||
_currentBitRate = BWE_MIN(BWE_MAX(minBitRateBps, _currentBitRate),
|
return 0;
|
||||||
maxBitRateBps);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RemoteRateControl::LatestEstimate() const {
|
uint32_t RemoteRateControl::LatestEstimate() const {
|
||||||
return _currentBitRate;
|
return current_bit_rate_;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RemoteRateControl::UpdateBandwidthEstimate(int64_t nowMS)
|
uint32_t RemoteRateControl::UpdateBandwidthEstimate(int64_t now_ms) {
|
||||||
{
|
current_bit_rate_ = ChangeBitRate(current_bit_rate_,
|
||||||
_currentBitRate = ChangeBitRate(_currentBitRate,
|
current_input_._incomingBitRate,
|
||||||
_currentInput._incomingBitRate,
|
current_input_._noiseVar,
|
||||||
_currentInput._noiseVar,
|
now_ms);
|
||||||
nowMS);
|
return current_bit_rate_;
|
||||||
return _currentBitRate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::SetRtt(unsigned int rtt) {
|
void RemoteRateControl::SetRtt(unsigned int rtt) {
|
||||||
_rtt = rtt;
|
rtt_ = rtt;
|
||||||
}
|
}
|
||||||
|
|
||||||
RateControlRegion RemoteRateControl::Update(const RateControlInput* input,
|
RateControlRegion RemoteRateControl::Update(const RateControlInput* input,
|
||||||
int64_t nowMS)
|
int64_t now_ms) {
|
||||||
{
|
assert(input);
|
||||||
assert(input);
|
|
||||||
#ifdef MATLAB
|
|
||||||
// Create plots
|
|
||||||
if (_plot1 == NULL)
|
|
||||||
{
|
|
||||||
_plot1 = eng.NewPlot(new MatlabPlot());
|
|
||||||
|
|
||||||
_plot1->AddTimeLine(30, "b", "current");
|
// Set the initial bit rate value to what we're receiving the first half
|
||||||
_plot1->AddTimeLine(30, "r-", "avgMax");
|
// second.
|
||||||
_plot1->AddTimeLine(30, "r--", "pStdMax");
|
if (!initialized_bit_rate_) {
|
||||||
_plot1->AddTimeLine(30, "r--", "nStdMax");
|
if (time_first_incoming_estimate_ < 0) {
|
||||||
_plot1->AddTimeLine(30, "r+", "max");
|
if (input->_incomingBitRate > 0) {
|
||||||
_plot1->AddTimeLine(30, "g", "incoming");
|
time_first_incoming_estimate_ = now_ms;
|
||||||
_plot1->AddTimeLine(30, "b+", "recovery");
|
}
|
||||||
|
} else if (now_ms - time_first_incoming_estimate_ > 500 &&
|
||||||
|
input->_incomingBitRate > 0) {
|
||||||
|
current_bit_rate_ = input->_incomingBitRate;
|
||||||
|
initialized_bit_rate_ = true;
|
||||||
}
|
}
|
||||||
if (_plot2 == NULL)
|
}
|
||||||
{
|
|
||||||
_plot2 = eng.NewPlot(new MatlabPlot());
|
|
||||||
|
|
||||||
_plot2->AddTimeLine(30, "b", "alpha");
|
if (updated_ && current_input_._bwState == kBwOverusing) {
|
||||||
}
|
// Only update delay factor and incoming bit rate. We always want to react
|
||||||
#endif
|
// on an over-use.
|
||||||
|
current_input_._noiseVar = input->_noiseVar;
|
||||||
// Set the initial bit rate value to what we're receiving the first half
|
current_input_._incomingBitRate = input->_incomingBitRate;
|
||||||
// second.
|
return rate_control_region_;
|
||||||
if (!_initializedBitRate)
|
}
|
||||||
{
|
updated_ = true;
|
||||||
if (_timeFirstIncomingEstimate < 0)
|
current_input_ = *input;
|
||||||
{
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: Incoming rate = %u kbps",
|
||||||
if (input->_incomingBitRate > 0)
|
input->_incomingBitRate/1000);
|
||||||
{
|
return rate_control_region_;
|
||||||
_timeFirstIncomingEstimate = nowMS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (nowMS - _timeFirstIncomingEstimate > 500 &&
|
|
||||||
input->_incomingBitRate > 0)
|
|
||||||
{
|
|
||||||
_currentBitRate = input->_incomingBitRate;
|
|
||||||
_initializedBitRate = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_updated && _currentInput._bwState == kBwOverusing)
|
|
||||||
{
|
|
||||||
// Only update delay factor and incoming bit rate. We always want to react on an over-use.
|
|
||||||
_currentInput._noiseVar = input->_noiseVar;
|
|
||||||
_currentInput._incomingBitRate = input->_incomingBitRate;
|
|
||||||
return _rcRegion;
|
|
||||||
}
|
|
||||||
_updated = true;
|
|
||||||
_currentInput = *input;
|
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: Incoming rate = %u kbps", input->_incomingBitRate/1000);
|
|
||||||
return _rcRegion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t RemoteRateControl::ChangeBitRate(uint32_t currentBitRate,
|
uint32_t RemoteRateControl::ChangeBitRate(uint32_t current_bit_rate,
|
||||||
uint32_t incomingBitRate,
|
uint32_t incoming_bit_rate,
|
||||||
double noiseVar,
|
double noise_var,
|
||||||
int64_t nowMS)
|
int64_t now_ms) {
|
||||||
{
|
if (!updated_) {
|
||||||
if (!_updated)
|
return current_bit_rate_;
|
||||||
{
|
}
|
||||||
return _currentBitRate;
|
updated_ = false;
|
||||||
|
UpdateChangePeriod(now_ms);
|
||||||
|
ChangeState(current_input_, now_ms);
|
||||||
|
// calculated here because it's used in multiple places
|
||||||
|
const float incoming_bit_rate_kbps = incoming_bit_rate / 1000.0f;
|
||||||
|
// Calculate the max bit rate std dev given the normalized
|
||||||
|
// variance and the current incoming bit rate.
|
||||||
|
const float std_max_bit_rate = sqrt(var_max_bit_rate_ * avg_max_bit_rate_);
|
||||||
|
bool recovery = false;
|
||||||
|
switch (rate_control_state_) {
|
||||||
|
case kRcHold: {
|
||||||
|
max_hold_rate_ = std::max(max_hold_rate_, incoming_bit_rate);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
_updated = false;
|
case kRcIncrease: {
|
||||||
UpdateChangePeriod(nowMS);
|
if (avg_max_bit_rate_ >= 0) {
|
||||||
ChangeState(_currentInput, nowMS);
|
if (incoming_bit_rate_kbps > avg_max_bit_rate_ + 3 * std_max_bit_rate) {
|
||||||
// calculated here because it's used in multiple places
|
ChangeRegion(kRcMaxUnknown);
|
||||||
const float incomingBitRateKbps = incomingBitRate / 1000.0f;
|
avg_max_bit_rate_ = -1.0;
|
||||||
// Calculate the max bit rate std dev given the normalized
|
} else if (incoming_bit_rate_kbps > avg_max_bit_rate_ + 2.5 *
|
||||||
// variance and the current incoming bit rate.
|
std_max_bit_rate) {
|
||||||
const float stdMaxBitRate = sqrt(_varMaxBitRate * _avgMaxBitRate);
|
ChangeRegion(kRcAboveMax);
|
||||||
bool recovery = false;
|
|
||||||
switch (_rcState)
|
|
||||||
{
|
|
||||||
case kRcHold:
|
|
||||||
{
|
|
||||||
_maxHoldRate = BWE_MAX(_maxHoldRate, incomingBitRate);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case kRcIncrease:
|
}
|
||||||
{
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
if (_avgMaxBitRate >= 0)
|
"BWE: Response time: %f + %i + 10*33\n",
|
||||||
{
|
avg_change_period_, rtt_);
|
||||||
if (incomingBitRateKbps > _avgMaxBitRate + 3 * stdMaxBitRate)
|
const uint32_t response_time = static_cast<uint32_t>(avg_change_period_ +
|
||||||
{
|
0.5f) + rtt_ + 300;
|
||||||
ChangeRegion(kRcMaxUnknown);
|
double alpha = RateIncreaseFactor(now_ms, last_bit_rate_change_,
|
||||||
_avgMaxBitRate = -1.0;
|
response_time, noise_var);
|
||||||
}
|
|
||||||
else if (incomingBitRateKbps > _avgMaxBitRate + 2.5 * stdMaxBitRate)
|
|
||||||
{
|
|
||||||
ChangeRegion(kRcAboveMax);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
|
||||||
"BWE: Response time: %f + %i + 10*33\n",
|
|
||||||
_avgChangePeriod, _rtt);
|
|
||||||
const uint32_t responseTime = static_cast<uint32_t>(_avgChangePeriod + 0.5f) + _rtt + 300;
|
|
||||||
double alpha = RateIncreaseFactor(nowMS, _lastBitRateChange,
|
|
||||||
responseTime, noiseVar);
|
|
||||||
|
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
"BWE: _avgChangePeriod = %f ms; RTT = %u ms", _avgChangePeriod, _rtt);
|
"BWE: avg_change_period_ = %f ms; RTT = %u ms", avg_change_period_,
|
||||||
|
rtt_);
|
||||||
|
|
||||||
currentBitRate = static_cast<uint32_t>(currentBitRate * alpha) + 1000;
|
current_bit_rate = static_cast<uint32_t>(current_bit_rate * alpha) + 1000;
|
||||||
if (_maxHoldRate > 0 && _beta * _maxHoldRate > currentBitRate)
|
if (max_hold_rate_ > 0 && beta_ * max_hold_rate_ > current_bit_rate) {
|
||||||
{
|
current_bit_rate = static_cast<uint32_t>(beta_ * max_hold_rate_);
|
||||||
currentBitRate = static_cast<uint32_t>(_beta * _maxHoldRate);
|
avg_max_bit_rate_ = beta_ * max_hold_rate_ / 1000.0f;
|
||||||
_avgMaxBitRate = _beta * _maxHoldRate / 1000.0f;
|
ChangeRegion(kRcNearMax);
|
||||||
ChangeRegion(kRcNearMax);
|
recovery = true;
|
||||||
recovery = true;
|
}
|
||||||
#ifdef MATLAB
|
max_hold_rate_ = 0;
|
||||||
_plot1->Append("recovery", _maxHoldRate/1000);
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
#endif
|
"BWE: Increase rate to current_bit_rate = %u kbps",
|
||||||
}
|
current_bit_rate / 1000);
|
||||||
_maxHoldRate = 0;
|
last_bit_rate_change_ = now_ms;
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
break;
|
||||||
"BWE: Increase rate to currentBitRate = %u kbps", currentBitRate/1000);
|
}
|
||||||
_lastBitRateChange = nowMS;
|
case kRcDecrease: {
|
||||||
break;
|
if (incoming_bit_rate < min_configured_bit_rate_) {
|
||||||
|
current_bit_rate = min_configured_bit_rate_;
|
||||||
|
} else {
|
||||||
|
// Set bit rate to something slightly lower than max
|
||||||
|
// to get rid of any self-induced delay.
|
||||||
|
current_bit_rate = static_cast<uint32_t>(beta_ * incoming_bit_rate +
|
||||||
|
0.5);
|
||||||
|
if (current_bit_rate > current_bit_rate_) {
|
||||||
|
// Avoid increasing the rate when over-using.
|
||||||
|
if (rate_control_region_ != kRcMaxUnknown) {
|
||||||
|
current_bit_rate = static_cast<uint32_t>(beta_ * avg_max_bit_rate_ *
|
||||||
|
1000 + 0.5f);
|
||||||
|
}
|
||||||
|
current_bit_rate = std::min(current_bit_rate, current_bit_rate_);
|
||||||
}
|
}
|
||||||
case kRcDecrease:
|
ChangeRegion(kRcNearMax);
|
||||||
{
|
|
||||||
if (incomingBitRate < _minConfiguredBitRate)
|
|
||||||
{
|
|
||||||
currentBitRate = _minConfiguredBitRate;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set bit rate to something slightly lower than max
|
|
||||||
// to get rid of any self-induced delay.
|
|
||||||
currentBitRate = static_cast<uint32_t>(_beta * incomingBitRate + 0.5);
|
|
||||||
if (currentBitRate > _currentBitRate)
|
|
||||||
{
|
|
||||||
// Avoid increasing the rate when over-using.
|
|
||||||
if (_rcRegion != kRcMaxUnknown)
|
|
||||||
{
|
|
||||||
currentBitRate = static_cast<uint32_t>(_beta * _avgMaxBitRate * 1000 + 0.5f);
|
|
||||||
}
|
|
||||||
currentBitRate = BWE_MIN(currentBitRate, _currentBitRate);
|
|
||||||
}
|
|
||||||
ChangeRegion(kRcNearMax);
|
|
||||||
|
|
||||||
if (incomingBitRateKbps < _avgMaxBitRate - 3 * stdMaxBitRate)
|
if (incoming_bit_rate_kbps < avg_max_bit_rate_ - 3 * std_max_bit_rate) {
|
||||||
{
|
avg_max_bit_rate_ = -1.0f;
|
||||||
_avgMaxBitRate = -1.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateMaxBitRateEstimate(incomingBitRateKbps);
|
|
||||||
|
|
||||||
#ifdef MATLAB
|
|
||||||
_plot1->Append("max", incomingBitRateKbps);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: Decrease rate to currentBitRate = %u kbps", currentBitRate/1000);
|
|
||||||
}
|
|
||||||
// Stay on hold until the pipes are cleared.
|
|
||||||
ChangeState(kRcHold);
|
|
||||||
_lastBitRateChange = nowMS;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UpdateMaxBitRateEstimate(incoming_bit_rate_kbps);
|
||||||
|
|
||||||
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
|
"BWE: Decrease rate to current_bit_rate = %u kbps",
|
||||||
|
current_bit_rate / 1000);
|
||||||
|
}
|
||||||
|
// Stay on hold until the pipes are cleared.
|
||||||
|
ChangeState(kRcHold);
|
||||||
|
last_bit_rate_change_ = now_ms;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (!recovery && (incomingBitRate > 100000 || currentBitRate > 150000) &&
|
default:
|
||||||
currentBitRate > 1.5 * incomingBitRate)
|
assert(false);
|
||||||
{
|
}
|
||||||
// Allow changing the bit rate if we are operating at very low rates
|
if (!recovery && (incoming_bit_rate > 100000 || current_bit_rate > 150000) &&
|
||||||
// Don't change the bit rate if the send side is too far off
|
current_bit_rate > 1.5 * incoming_bit_rate) {
|
||||||
currentBitRate = _currentBitRate;
|
// Allow changing the bit rate if we are operating at very low rates
|
||||||
_lastBitRateChange = nowMS;
|
// Don't change the bit rate if the send side is too far off
|
||||||
}
|
current_bit_rate = current_bit_rate_;
|
||||||
#ifdef MATLAB
|
last_bit_rate_change_ = now_ms;
|
||||||
if (_avgMaxBitRate >= 0.0f)
|
}
|
||||||
{
|
return current_bit_rate;
|
||||||
_plot1->Append("avgMax", _avgMaxBitRate);
|
|
||||||
_plot1->Append("pStdMax", _avgMaxBitRate + 3*stdMaxBitRate);
|
|
||||||
_plot1->Append("nStdMax", _avgMaxBitRate - 3*stdMaxBitRate);
|
|
||||||
}
|
|
||||||
_plot1->Append("incoming", incomingBitRate/1000);
|
|
||||||
_plot1->Append("current", currentBitRate/1000);
|
|
||||||
_plot1->Plot();
|
|
||||||
#endif
|
|
||||||
return currentBitRate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double RemoteRateControl::RateIncreaseFactor(int64_t nowMs, int64_t lastMs, uint32_t reactionTimeMs, double noiseVar) const
|
double RemoteRateControl::RateIncreaseFactor(int64_t now_ms,
|
||||||
{
|
int64_t last_ms,
|
||||||
// alpha = 1.02 + B ./ (1 + exp(b*(tr - (c1*s2 + c2))))
|
uint32_t reaction_time_ms,
|
||||||
// Parameters
|
double noise_var) const {
|
||||||
const double B = 0.0407;
|
// alpha = 1.02 + B ./ (1 + exp(b*(tr - (c1*s2 + c2))))
|
||||||
const double b = 0.0025;
|
// Parameters
|
||||||
const double c1 = -6700.0 / (33 * 33);
|
const double B = 0.0407;
|
||||||
const double c2 = 800.0;
|
const double b = 0.0025;
|
||||||
const double d = 0.85;
|
const double c1 = -6700.0 / (33 * 33);
|
||||||
|
const double c2 = 800.0;
|
||||||
|
const double d = 0.85;
|
||||||
|
|
||||||
double alpha = 1.005 + B / (1 + exp( b * (d * reactionTimeMs - (c1 * noiseVar + c2))));
|
double alpha = 1.005 + B / (1 + exp( b * (d * reaction_time_ms -
|
||||||
|
(c1 * noise_var + c2))));
|
||||||
|
|
||||||
if (alpha < 1.005)
|
if (alpha < 1.005) {
|
||||||
{
|
alpha = 1.005;
|
||||||
alpha = 1.005;
|
} else if (alpha > 1.3) {
|
||||||
}
|
alpha = 1.3;
|
||||||
else if (alpha > 1.3)
|
}
|
||||||
{
|
|
||||||
alpha = 1.3;
|
|
||||||
}
|
|
||||||
|
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: alpha = %f", alpha);
|
||||||
"BWE: alpha = %f", alpha);
|
|
||||||
#ifdef MATLAB
|
|
||||||
_plot2->Append("alpha", alpha);
|
|
||||||
_plot2->Plot();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (lastMs > -1)
|
if (last_ms > -1) {
|
||||||
{
|
alpha = pow(alpha, (now_ms - last_ms) / 1000.0);
|
||||||
alpha = pow(alpha, (nowMs - lastMs) / 1000.0);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (_rcRegion == kRcNearMax)
|
if (rate_control_region_ == kRcNearMax) {
|
||||||
{
|
// We're close to our previous maximum. Try to stabilize the
|
||||||
// We're close to our previous maximum. Try to stabilize the
|
// bit rate in this region, by increasing in smaller steps.
|
||||||
// bit rate in this region, by increasing in smaller steps.
|
alpha = alpha - (alpha - 1.0) / 2.0;
|
||||||
alpha = alpha - (alpha - 1.0) / 2.0;
|
} else if (rate_control_region_ == kRcMaxUnknown) {
|
||||||
}
|
alpha = alpha + (alpha - 1.0) * 2.0;
|
||||||
else if (_rcRegion == kRcMaxUnknown)
|
}
|
||||||
{
|
|
||||||
alpha = alpha + (alpha - 1.0) * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return alpha;
|
return alpha;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::UpdateChangePeriod(int64_t nowMs)
|
void RemoteRateControl::UpdateChangePeriod(int64_t now_ms) {
|
||||||
{
|
int64_t changePeriod = 0;
|
||||||
int64_t changePeriod = 0;
|
if (last_change_ms_ > -1) {
|
||||||
if (_lastChangeMs > -1)
|
changePeriod = now_ms - last_change_ms_;
|
||||||
{
|
}
|
||||||
changePeriod = nowMs - _lastChangeMs;
|
last_change_ms_ = now_ms;
|
||||||
}
|
avg_change_period_ = 0.9f * avg_change_period_ + 0.1f * changePeriod;
|
||||||
_lastChangeMs = nowMs;
|
|
||||||
_avgChangePeriod = 0.9f * _avgChangePeriod + 0.1f * changePeriod;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::UpdateMaxBitRateEstimate(float incomingBitRateKbps)
|
void RemoteRateControl::UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps) {
|
||||||
{
|
const float alpha = 0.05f;
|
||||||
const float alpha = 0.05f;
|
if (avg_max_bit_rate_ == -1.0f) {
|
||||||
if (_avgMaxBitRate == -1.0f)
|
avg_max_bit_rate_ = incoming_bit_rate_kbps;
|
||||||
{
|
} else {
|
||||||
_avgMaxBitRate = incomingBitRateKbps;
|
avg_max_bit_rate_ = (1 - alpha) * avg_max_bit_rate_ +
|
||||||
}
|
alpha * incoming_bit_rate_kbps;
|
||||||
else
|
}
|
||||||
{
|
// Estimate the max bit rate variance and normalize the variance
|
||||||
_avgMaxBitRate = (1 - alpha) * _avgMaxBitRate +
|
// with the average max bit rate.
|
||||||
alpha * incomingBitRateKbps;
|
const float norm = std::max(avg_max_bit_rate_, 1.0f);
|
||||||
}
|
var_max_bit_rate_ = (1 - alpha) * var_max_bit_rate_ +
|
||||||
// Estimate the max bit rate variance and normalize the variance
|
alpha * (avg_max_bit_rate_ - incoming_bit_rate_kbps) *
|
||||||
// with the average max bit rate.
|
(avg_max_bit_rate_ - incoming_bit_rate_kbps) / norm;
|
||||||
const float norm = BWE_MAX(_avgMaxBitRate, 1.0f);
|
// 0.4 ~= 14 kbit/s at 500 kbit/s
|
||||||
_varMaxBitRate = (1 - alpha) * _varMaxBitRate +
|
if (var_max_bit_rate_ < 0.4f) {
|
||||||
alpha * (_avgMaxBitRate - incomingBitRateKbps) *
|
var_max_bit_rate_ = 0.4f;
|
||||||
(_avgMaxBitRate - incomingBitRateKbps) /
|
}
|
||||||
norm;
|
// 2.5f ~= 35 kbit/s at 500 kbit/s
|
||||||
// 0.4 ~= 14 kbit/s at 500 kbit/s
|
if (var_max_bit_rate_ > 2.5f) {
|
||||||
if (_varMaxBitRate < 0.4f)
|
var_max_bit_rate_ = 2.5f;
|
||||||
{
|
}
|
||||||
_varMaxBitRate = 0.4f;
|
|
||||||
}
|
|
||||||
// 2.5f ~= 35 kbit/s at 500 kbit/s
|
|
||||||
if (_varMaxBitRate > 2.5f)
|
|
||||||
{
|
|
||||||
_varMaxBitRate = 2.5f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::ChangeState(const RateControlInput& input, int64_t nowMs)
|
void RemoteRateControl::ChangeState(const RateControlInput& input,
|
||||||
{
|
int64_t now_ms) {
|
||||||
switch (_currentInput._bwState)
|
switch (current_input_._bwState) {
|
||||||
{
|
|
||||||
case kBwNormal:
|
case kBwNormal:
|
||||||
{
|
if (rate_control_state_ == kRcHold) {
|
||||||
if (_rcState == kRcHold)
|
last_bit_rate_change_ = now_ms;
|
||||||
{
|
ChangeState(kRcIncrease);
|
||||||
_lastBitRateChange = nowMs;
|
}
|
||||||
ChangeState(kRcIncrease);
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kBwOverusing:
|
case kBwOverusing:
|
||||||
{
|
if (rate_control_state_ != kRcDecrease) {
|
||||||
if (_rcState != kRcDecrease)
|
ChangeState(kRcDecrease);
|
||||||
{
|
}
|
||||||
ChangeState(kRcDecrease);
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kBwUnderusing:
|
case kBwUnderusing:
|
||||||
{
|
ChangeState(kRcHold);
|
||||||
ChangeState(kRcHold);
|
break;
|
||||||
break;
|
default:
|
||||||
}
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::ChangeRegion(RateControlRegion region)
|
void RemoteRateControl::ChangeRegion(RateControlRegion region) {
|
||||||
{
|
rate_control_region_ = region;
|
||||||
_rcRegion = region;
|
switch (rate_control_region_) {
|
||||||
switch (_rcRegion)
|
|
||||||
{
|
|
||||||
case kRcAboveMax:
|
case kRcAboveMax:
|
||||||
case kRcMaxUnknown:
|
case kRcMaxUnknown:
|
||||||
{
|
beta_ = 0.9f;
|
||||||
_beta = 0.9f;
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
case kRcNearMax:
|
case kRcNearMax:
|
||||||
{
|
beta_ = 0.95f;
|
||||||
_beta = 0.95f;
|
break;
|
||||||
break;
|
default:
|
||||||
}
|
assert(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::ChangeState(RateControlState newState)
|
void RemoteRateControl::ChangeState(RateControlState new_state) {
|
||||||
{
|
came_from_state_ = rate_control_state_;
|
||||||
_cameFromState = _rcState;
|
rate_control_state_ = new_state;
|
||||||
_rcState = newState;
|
char state1[15];
|
||||||
char state1[15];
|
char state2[15];
|
||||||
char state2[15];
|
char state3[15];
|
||||||
char state3[15];
|
StateStr(came_from_state_, state1);
|
||||||
StateStr(_cameFromState, state1);
|
StateStr(rate_control_state_, state2);
|
||||||
StateStr(_rcState, state2);
|
StateStr(current_input_._bwState, state3);
|
||||||
StateStr(_currentInput._bwState, state3);
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
"\t%s => %s due to %s\n", state1, state2, state3);
|
||||||
"\t%s => %s due to %s\n", state1, state2, state3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::StateStr(RateControlState state, char* str)
|
void RemoteRateControl::StateStr(RateControlState state, char* str) {
|
||||||
{
|
switch (state) {
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case kRcDecrease:
|
case kRcDecrease:
|
||||||
strncpy(str, "DECREASE", 9);
|
strncpy(str, "DECREASE", 9);
|
||||||
break;
|
break;
|
||||||
case kRcHold:
|
case kRcHold:
|
||||||
strncpy(str, "HOLD", 5);
|
strncpy(str, "HOLD", 5);
|
||||||
break;
|
break;
|
||||||
case kRcIncrease:
|
case kRcIncrease:
|
||||||
strncpy(str, "INCREASE", 9);
|
strncpy(str, "INCREASE", 9);
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteRateControl::StateStr(BandwidthUsage state, char* str)
|
void RemoteRateControl::StateStr(BandwidthUsage state, char* str) {
|
||||||
{
|
switch (state) {
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case kBwNormal:
|
case kBwNormal:
|
||||||
strncpy(str, "NORMAL", 7);
|
strncpy(str, "NORMAL", 7);
|
||||||
break;
|
break;
|
||||||
case kBwOverusing:
|
case kBwOverusing:
|
||||||
strncpy(str, "OVER USING", 11);
|
strncpy(str, "OVER USING", 11);
|
||||||
break;
|
break;
|
||||||
case kBwUnderusing:
|
case kBwUnderusing:
|
||||||
strncpy(str, "UNDER USING", 12);
|
strncpy(str, "UNDER USING", 12);
|
||||||
break;
|
break;
|
||||||
}
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@@ -12,77 +12,68 @@
|
|||||||
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_REMOTE_RATE_CONTROL_H_
|
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_REMOTE_RATE_CONTROL_H_
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
|
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
|
||||||
#include "typedefs.h"
|
|
||||||
|
|
||||||
#ifdef MATLAB
|
|
||||||
#include "../test/BWEStandAlone/MatlabPlot.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
class RemoteRateControl
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
RemoteRateControl();
|
|
||||||
~RemoteRateControl();
|
|
||||||
int32_t SetConfiguredBitRates(uint32_t minBitRate,
|
|
||||||
uint32_t maxBitRate);
|
|
||||||
uint32_t LatestEstimate() const;
|
|
||||||
uint32_t UpdateBandwidthEstimate(int64_t nowMS);
|
|
||||||
void SetRtt(unsigned int rtt);
|
|
||||||
RateControlRegion Update(const RateControlInput* input,
|
|
||||||
int64_t nowMS);
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
// Returns true if there is a valid estimate of the incoming bitrate, false
|
class RemoteRateControl {
|
||||||
// otherwise.
|
public:
|
||||||
bool ValidEstimate() const;
|
RemoteRateControl();
|
||||||
// Returns true if the bitrate estimate hasn't been changed for more than
|
~RemoteRateControl() {}
|
||||||
// an RTT, or if the incoming_bitrate is more than 5% above the current
|
|
||||||
// estimate. Should be used to decide if we should reduce the rate further
|
|
||||||
// when over-using.
|
|
||||||
bool TimeToReduceFurther(int64_t time_now,
|
|
||||||
unsigned int incoming_bitrate) const;
|
|
||||||
|
|
||||||
private:
|
void Reset();
|
||||||
uint32_t ChangeBitRate(uint32_t currentBitRate,
|
|
||||||
uint32_t incomingBitRate,
|
|
||||||
double delayFactor,
|
|
||||||
int64_t nowMS);
|
|
||||||
double RateIncreaseFactor(int64_t nowMs,
|
|
||||||
int64_t lastMs,
|
|
||||||
uint32_t reactionTimeMs,
|
|
||||||
double noiseVar) const;
|
|
||||||
void UpdateChangePeriod(int64_t nowMs);
|
|
||||||
void UpdateMaxBitRateEstimate(float incomingBitRateKbps);
|
|
||||||
void ChangeState(const RateControlInput& input, int64_t nowMs);
|
|
||||||
void ChangeState(RateControlState newState);
|
|
||||||
void ChangeRegion(RateControlRegion region);
|
|
||||||
static void StateStr(RateControlState state, char* str);
|
|
||||||
static void StateStr(BandwidthUsage state, char* str);
|
|
||||||
|
|
||||||
uint32_t _minConfiguredBitRate;
|
// Returns true if there is a valid estimate of the incoming bitrate, false
|
||||||
uint32_t _maxConfiguredBitRate;
|
// otherwise.
|
||||||
uint32_t _currentBitRate;
|
bool ValidEstimate() const;
|
||||||
uint32_t _maxHoldRate;
|
|
||||||
float _avgMaxBitRate;
|
|
||||||
float _varMaxBitRate;
|
|
||||||
RateControlState _rcState;
|
|
||||||
RateControlState _cameFromState;
|
|
||||||
RateControlRegion _rcRegion;
|
|
||||||
int64_t _lastBitRateChange;
|
|
||||||
RateControlInput _currentInput;
|
|
||||||
bool _updated;
|
|
||||||
int64_t _timeFirstIncomingEstimate;
|
|
||||||
bool _initializedBitRate;
|
|
||||||
|
|
||||||
float _avgChangePeriod;
|
// Returns true if the bitrate estimate hasn't been changed for more than
|
||||||
int64_t _lastChangeMs;
|
// an RTT, or if the incoming_bitrate is more than 5% above the current
|
||||||
float _beta;
|
// estimate. Should be used to decide if we should reduce the rate further
|
||||||
unsigned int _rtt;
|
// when over-using.
|
||||||
#ifdef MATLAB
|
bool TimeToReduceFurther(int64_t time_now,
|
||||||
MatlabPlot *_plot1;
|
unsigned int incoming_bitrate) const;
|
||||||
MatlabPlot *_plot2;
|
|
||||||
#endif
|
int32_t SetConfiguredBitRates(uint32_t min_bit_rate, uint32_t max_bit_rate);
|
||||||
|
uint32_t LatestEstimate() const;
|
||||||
|
uint32_t UpdateBandwidthEstimate(int64_t now_ms);
|
||||||
|
void SetRtt(unsigned int rtt);
|
||||||
|
RateControlRegion Update(const RateControlInput* input, int64_t now_ms);
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t ChangeBitRate(uint32_t current_bit_rate,
|
||||||
|
uint32_t incoming_bit_rate,
|
||||||
|
double delay_factor,
|
||||||
|
int64_t now_ms);
|
||||||
|
double RateIncreaseFactor(int64_t now_ms,
|
||||||
|
int64_t last_ms,
|
||||||
|
uint32_t reaction_time_ms,
|
||||||
|
double noise_var) const;
|
||||||
|
void UpdateChangePeriod(int64_t now_ms);
|
||||||
|
void UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps);
|
||||||
|
void ChangeState(const RateControlInput& input, int64_t now_ms);
|
||||||
|
void ChangeState(RateControlState new_state);
|
||||||
|
void ChangeRegion(RateControlRegion region);
|
||||||
|
static void StateStr(RateControlState state, char* str);
|
||||||
|
static void StateStr(BandwidthUsage state, char* str);
|
||||||
|
|
||||||
|
uint32_t min_configured_bit_rate_;
|
||||||
|
uint32_t max_configured_bit_rate_;
|
||||||
|
uint32_t current_bit_rate_;
|
||||||
|
uint32_t max_hold_rate_;
|
||||||
|
float avg_max_bit_rate_;
|
||||||
|
float var_max_bit_rate_;
|
||||||
|
RateControlState rate_control_state_;
|
||||||
|
RateControlState came_from_state_;
|
||||||
|
RateControlRegion rate_control_region_;
|
||||||
|
int64_t last_bit_rate_change_;
|
||||||
|
RateControlInput current_input_;
|
||||||
|
bool updated_;
|
||||||
|
int64_t time_first_incoming_estimate_;
|
||||||
|
bool initialized_bit_rate_;
|
||||||
|
float avg_change_period_;
|
||||||
|
int64_t last_change_ms_;
|
||||||
|
float beta_;
|
||||||
|
unsigned int rtt_;
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user