Expose a set of options to the OveruseDetector supporting experiments

Updated overuse_detector.* to use google style naming convention
Removed OveruseDetector::Reset
Review URL: https://webrtc-codereview.appspot.com/666005

git-svn-id: http://webrtc.googlecode.com/svn/trunk@2443 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
astor@webrtc.org 2012-06-26 10:47:04 +00:00
parent f494fd0954
commit bd7aeba8fb
15 changed files with 304 additions and 271 deletions

View File

@ -571,5 +571,32 @@ struct VideoCodec
unsigned char numberOfSimulcastStreams;
SimulcastStream simulcastStream[kMaxSimulcastStreams];
};
// Bandwidth over-use detector options. These are used to drive
// experimentation with bandwidth estimation parameters.
// See modules/remote_bitrate_estimator/overuse_detector.h
struct OverUseDetectorOptions {
OverUseDetectorOptions()
: initial_slope(8.0/512.0),
initial_offset(0),
initial_e(),
initial_process_noise(),
initial_avg_noise(0.0),
initial_var_noise(500),
initial_threshold(25.0) {
initial_e[0][0] = 100;
initial_e[1][1] = 1e-1;
initial_e[0][1] = initial_e[1][0] = 0;
initial_process_noise[0] = 1e-10;
initial_process_noise[1] = 1e-2;
}
double initial_slope;
double initial_offset;
double initial_e[2][2];
double initial_process_noise[2];
double initial_avg_noise;
double initial_var_noise;
double initial_threshold;
};
} // namespace webrtc
#endif // WEBRTC_COMMON_TYPES_H

View File

@ -39,7 +39,8 @@ class RemoteBitrateObserver {
class RemoteBitrateEstimator {
public:
explicit RemoteBitrateEstimator(RemoteBitrateObserver* observer);
RemoteBitrateEstimator(RemoteBitrateObserver* observer,
const OverUseDetectorOptions& options);
// Called for each incoming packet. If this is a new SSRC, a new
// BitrateControl will be created.
@ -65,6 +66,16 @@ class RemoteBitrateEstimator {
private:
struct BitrateControls {
explicit BitrateControls(const OverUseDetectorOptions& options)
: remote_rate(),
overuse_detector(options),
incoming_bitrate() {
}
BitrateControls(const BitrateControls& other)
: remote_rate(other.remote_rate),
overuse_detector(other.overuse_detector),
incoming_bitrate(other.incoming_bitrate) {
}
RemoteRateControl remote_rate;
OverUseDetector overuse_detector;
BitRateStats incoming_bitrate;
@ -72,6 +83,7 @@ class RemoteBitrateEstimator {
typedef std::map<unsigned int, BitrateControls> SsrcBitrateControlsMap;
const OverUseDetectorOptions& options_;
SsrcBitrateControlsMap bitrate_controls_;
RemoteBitrateObserver* observer_;
scoped_ptr<CriticalSectionWrapper> crit_sect_;

View File

@ -23,163 +23,128 @@
extern MatlabEngine eng; // global variable defined elsewhere
#endif
#define INIT_CAPACITY_SLOPE 8.0/512.0
#define DETECTOR_THRESHOLD 25.0
#define OVER_USING_TIME_THRESHOLD 100
#define MIN_FRAME_PERIOD_HISTORY_LEN 60
namespace webrtc {
OverUseDetector::OverUseDetector()
: firstPacket_(true),
currentFrame_(),
prevFrame_(),
numOfDeltas_(0),
slope_(INIT_CAPACITY_SLOPE),
offset_(0),
OverUseDetector::OverUseDetector(const OverUseDetectorOptions& options)
: options_(options),
first_packet_(true),
current_frame_(),
prev_frame_(),
num_of_deltas_(0),
slope_(options_.initial_slope),
offset_(options_.initial_offset),
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;
process_noise_(),
avg_noise_(options_.initial_avg_noise),
var_noise_(options_.initial_var_noise),
threshold_(options_.initial_threshold),
ts_delta_hist_(),
prev_offset_(0.0),
time_over_using_(-1),
over_use_counter_(0),
hypothesis_(kBwNormal),
plots_() {
memcpy(E_, options_.initial_e, sizeof(E_));
memcpy(process_noise_, options_.initial_process_noise,
sizeof(process_noise_));
}
OverUseDetector::~OverUseDetector() {
#ifdef WEBRTC_BWE_MATLAB
if (plot1_) {
eng.DeletePlot(plot1_);
plot1_ = NULL;
if (plots_.plot1_) {
eng.DeletePlot(plots_.plot1_);
plots_.plot1_ = NULL;
}
if (plot2_) {
eng.DeletePlot(plot2_);
plot2_ = NULL;
if (plots_.plot2_) {
eng.DeletePlot(plots_.plot2_);
plots_.plot2_ = NULL;
}
if (plot3_) {
eng.DeletePlot(plot3_);
plot3_ = NULL;
if (plots_.plot3_) {
eng.DeletePlot(plots_.plot3_);
plots_.plot3_ = NULL;
}
if (plot4_) {
eng.DeletePlot(plot4_);
plot4_ = NULL;
if (plots_.plot4_) {
eng.DeletePlot(plots_.plot4_);
plots_.plot4_ = NULL;
}
#endif
tsDeltaHist_.clear();
ts_delta_hist_.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::Update(WebRtc_UWord16 packetSize,
WebRtc_UWord32 timestamp,
const WebRtc_Word64 nowMS) {
void OverUseDetector::Update(uint16_t packet_size,
uint32_t timestamp,
const int64_t now_ms) {
#ifdef WEBRTC_BWE_MATLAB
// Create plots
const WebRtc_Word64 startTimeMs = nowMS;
if (plot1_ == NULL) {
plot1_ = eng.NewPlot(new MatlabPlot());
plot1_->AddLine(1000, "b.", "scatter");
const int64_t startTimeMs = nowMS;
if (plots_.plot1_ == NULL) {
plots_.plot1_ = eng.NewPlot(new MatlabPlot());
plots_.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 (plots_.plot2_ == NULL) {
plots_.plot2_ = eng.NewPlot(new MatlabPlot());
plots_.plot2_->AddTimeLine(30, "b", "offset", startTimeMs);
plots_.plot2_->AddTimeLine(30, "r--", "limitPos", startTimeMs);
plots_.plot2_->AddTimeLine(30, "k.", "trigger", startTimeMs);
plots_.plot2_->AddTimeLine(30, "ko", "detection", startTimeMs);
// plots_.plot2_->AddTimeLine(30, "g", "slowMean", startTimeMs);
}
if (plot3_ == NULL) {
plot3_ = eng.NewPlot(new MatlabPlot());
plot3_->AddTimeLine(30, "b", "noiseVar", startTimeMs);
if (plots_.plot3_ == NULL) {
plots_.plot3_ = eng.NewPlot(new MatlabPlot());
plots_.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);
if (plots_.plot4_ == NULL) {
plots_.plot4_ = eng.NewPlot(new MatlabPlot());
// plots_.plot4_->AddTimeLine(60, "b", "p11", startTimeMs);
// plots_.plot4_->AddTimeLine(60, "r", "p12", startTimeMs);
plots_.plot4_->AddTimeLine(60, "g", "p22", startTimeMs);
// plots_.plot4_->AddTimeLine(60, "g--", "p22_hat", startTimeMs);
// plots_.plot4_->AddTimeLine(30, "b.-", "deltaFs", startTimeMs);
}
#endif
bool wrapped = false;
bool completeFrame = false;
if (currentFrame_.timestamp_ == -1) {
currentFrame_.timestamp_ = timestamp;
if (current_frame_.timestamp_ == -1) {
current_frame_.timestamp_ = timestamp;
} else if (OldTimestamp(
timestamp,
static_cast<WebRtc_UWord32>(currentFrame_.timestamp_),
static_cast<uint32_t>(current_frame_.timestamp_),
&wrapped)) {
// Don't update with old data
return;
} else if (timestamp != currentFrame_.timestamp_) {
} else if (timestamp != current_frame_.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;
"Frame complete at %I64i", current_frame_.completeTimeMs_);
if (prev_frame_.completeTimeMs_ >= 0) { // This is our second frame
int64_t t_delta = 0;
double ts_delta = 0;
// Check for wrap
OldTimestamp(
static_cast<WebRtc_UWord32>(prevFrame_.timestamp_),
static_cast<WebRtc_UWord32>(currentFrame_.timestamp_),
static_cast<uint32_t>(prev_frame_.timestamp_),
static_cast<uint32_t>(current_frame_.timestamp_),
&wrapped);
CompensatedTimeDelta(currentFrame_, prevFrame_, tDelta, tsDelta,
CompensatedTimeDelta(current_frame_, prev_frame_, t_delta, ts_delta,
wrapped);
UpdateKalman(tDelta, tsDelta, currentFrame_.size_,
prevFrame_.size_);
UpdateKalman(t_delta, ts_delta, current_frame_.size_,
prev_frame_.size_);
}
// The new timestamp is now the current frame,
// and the old timestamp becomes the previous frame.
prevFrame_ = currentFrame_;
currentFrame_.timestamp_ = timestamp;
currentFrame_.size_ = 0;
currentFrame_.completeTimeMs_ = -1;
prev_frame_ = current_frame_;
current_frame_.timestamp_ = timestamp;
current_frame_.size_ = 0;
current_frame_.completeTimeMs_ = -1;
completeFrame = true;
}
// Accumulate the frame size
currentFrame_.size_ += packetSize;
currentFrame_.completeTimeMs_ = nowMS;
current_frame_.size_ += packet_size;
current_frame_.completeTimeMs_ = now_ms;
}
BandwidthUsage OverUseDetector::State() const {
@ -187,18 +152,18 @@ BandwidthUsage OverUseDetector::State() const {
}
double OverUseDetector::NoiseVar() const {
return varNoise_;
return var_noise_;
}
void OverUseDetector::SetRateControlRegion(RateControlRegion region) {
switch (region) {
case kRcMaxUnknown: {
threshold_ = DETECTOR_THRESHOLD;
threshold_ = options_.initial_threshold;
break;
}
case kRcAboveMax:
case kRcNearMax: {
threshold_ = DETECTOR_THRESHOLD / 2;
threshold_ = options_.initial_threshold / 2;
break;
}
}
@ -206,47 +171,47 @@ void OverUseDetector::SetRateControlRegion(RateControlRegion region) {
void OverUseDetector::CompensatedTimeDelta(const FrameSample& currentFrame,
const FrameSample& prevFrame,
WebRtc_Word64& tDelta,
double& tsDelta,
int64_t& t_delta,
double& ts_delta,
bool wrapped) {
numOfDeltas_++;
if (numOfDeltas_ > 1000) {
numOfDeltas_ = 1000;
num_of_deltas_++;
if (num_of_deltas_ > 1000) {
num_of_deltas_ = 1000;
}
// Add wrap-around compensation
WebRtc_Word64 wrapCompensation = 0;
int64_t wrapCompensation = 0;
if (wrapped) {
wrapCompensation = static_cast<WebRtc_Word64>(1)<<32;
wrapCompensation = static_cast<int64_t>(1)<<32;
}
tsDelta = (currentFrame.timestamp_
ts_delta = (currentFrame.timestamp_
+ wrapCompensation
- prevFrame.timestamp_) / 90.0;
tDelta = currentFrame.completeTimeMs_ - prevFrame.completeTimeMs_;
assert(tsDelta > 0);
t_delta = currentFrame.completeTimeMs_ - prevFrame.completeTimeMs_;
assert(ts_delta > 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);
void OverUseDetector::UpdateKalman(int64_t t_delta,
double ts_delta,
uint32_t frame_size,
uint32_t prev_frame_size) {
const double minFramePeriod = UpdateMinFramePeriod(ts_delta);
const double drift = CurrentDrift();
// Compensate for drift
const double tTsDelta = tDelta - tsDelta / drift;
double fsDelta = static_cast<double>(frameSize) - prevFrameSize;
const double tTsDelta = t_delta - ts_delta / drift;
double fsDelta = static_cast<double>(frame_size) - prev_frame_size;
// Update the Kalman filter
const double scaleFactor = minFramePeriod / (1000.0 / 30.0);
E_[0][0] += processNoise_[0] * scaleFactor;
E_[1][1] += processNoise_[1] * scaleFactor;
E_[0][0] += process_noise_[0] * scaleFactor;
E_[1][1] += process_noise_[1] * scaleFactor;
if ((hypothesis_ == kBwOverusing && offset_ < prevOffset_) ||
(hypothesis_ == kBwUnderUsing && offset_ > prevOffset_)) {
E_[1][1] += 10 * processNoise_[1] * scaleFactor;
if ((hypothesis_ == kBwOverusing && offset_ < prev_offset_) ||
(hypothesis_ == kBwUnderUsing && offset_ > prev_offset_)) {
E_[1][1] += 10 * process_noise_[1] * scaleFactor;
}
const double h[2] = {fsDelta, 1.0};
@ -255,17 +220,17 @@ void OverUseDetector::UpdateKalman(WebRtc_Word64 tDelta,
const double residual = tTsDelta - slope_*h[0] - offset_;
const bool stableState =
(BWE_MIN(numOfDeltas_, 60) * fabsf(offset_) < threshold_);
const bool stable_state =
(BWE_MIN(num_of_deltas_, 60) * fabsf(offset_) < threshold_);
// We try to filter out very late frames. For instance periodic key
// frames doesn't fit the Gaussian model well.
if (fabsf(residual) < 3 * sqrt(varNoise_)) {
UpdateNoiseEstimate(residual, minFramePeriod, stableState);
if (fabsf(residual) < 3 * sqrt(var_noise_)) {
UpdateNoiseEstimate(residual, minFramePeriod, stable_state);
} else {
UpdateNoiseEstimate(3 * sqrt(varNoise_), minFramePeriod, stableState);
UpdateNoiseEstimate(3 * sqrt(var_noise_), minFramePeriod, stable_state);
}
const double denom = varNoise_ + h[0]*Eh[0] + h[1]*Eh[1];
const double denom = var_noise_ + h[0]*Eh[0] + h[1]*Eh[1];
const double K[2] = {Eh[0] / denom,
Eh[1] / denom};
@ -287,114 +252,114 @@ void OverUseDetector::UpdateKalman(WebRtc_Word64 tDelta,
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();
// plots_.plot4_->Append("p11",E_[0][0]);
// plots_.plot4_->Append("p12",E_[0][1]);
plots_.plot4_->Append("p22", E_[1][1]);
// plots_.plot4_->Append("p22_hat", 0.5*(process_noise_[1] +
// sqrt(process_noise_[1]*(process_noise_[1] + 4*var_noise_))));
// plots_.plot4_->Append("deltaFs", fsDelta);
plots_.plot4_->Plot();
#endif
slope_ = slope_ + K[0] * residual;
prevOffset_ = offset_;
prev_offset_ = offset_;
offset_ = offset_ + K[1] * residual;
Detect(tsDelta);
Detect(ts_delta);
#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();
plots_.plot1_->Append("scatter",
static_cast<double>(current_frame_.size_) - prev_frame_.size_,
static_cast<double>(t_delta - ts_delta));
plots_.plot1_->MakeTrend("scatter", "slope", slope_, offset_, "k-");
plots_.plot1_->MakeTrend("scatter", "thresholdPos",
slope_, offset_ + 2 * sqrt(var_noise_), "r-");
plots_.plot1_->MakeTrend("scatter", "thresholdNeg",
slope_, offset_ - 2 * sqrt(var_noise_), "r-");
plots_.plot1_->Plot();
plot2_->Append("offset", offset_);
plot2_->Append("limitPos", threshold_/BWE_MIN(numOfDeltas_, 60));
plot2_->Plot();
plots_.plot2_->Append("offset", offset_);
plots_.plot2_->Append("limitPos", threshold_/BWE_MIN(num_of_deltas_, 60));
plots_.plot2_->Plot();
plot3_->Append("noiseVar", varNoise_);
plot3_->Plot();
plots_.plot3_->Append("noiseVar", var_noise_);
plots_.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);
double OverUseDetector::UpdateMinFramePeriod(double ts_delta) {
double minFramePeriod = ts_delta;
if (ts_delta_hist_.size() >= MIN_FRAME_PERIOD_HISTORY_LEN) {
std::list<double>::iterator firstItem = ts_delta_hist_.begin();
ts_delta_hist_.erase(firstItem);
}
std::list<double>::iterator it = tsDeltaHist_.begin();
for (; it != tsDeltaHist_.end(); it++) {
std::list<double>::iterator it = ts_delta_hist_.begin();
for (; it != ts_delta_hist_.end(); it++) {
minFramePeriod = BWE_MIN(*it, minFramePeriod);
}
tsDeltaHist_.push_back(tsDelta);
ts_delta_hist_.push_back(ts_delta);
return minFramePeriod;
}
void OverUseDetector::UpdateNoiseEstimate(double residual,
double tsDelta,
bool stableState) {
if (!stableState) {
double ts_delta,
bool stable_state) {
if (!stable_state) {
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) {
if (num_of_deltas_ > 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_
const double beta = pow(1 - alpha, ts_delta * 30.0 / 1000.0);
avg_noise_ = beta * avg_noise_
+ (1 - beta) * residual;
varNoise_ = beta * varNoise_
+ (1 - beta) * (avgNoise_ - residual) * (avgNoise_ - residual);
if (varNoise_ < 1e-7) {
varNoise_ = 1e-7;
var_noise_ = beta * var_noise_
+ (1 - beta) * (avg_noise_ - residual) * (avg_noise_ - residual);
if (var_noise_ < 1e-7) {
var_noise_ = 1e-7;
}
}
BandwidthUsage OverUseDetector::Detect(double tsDelta) {
if (numOfDeltas_ < 2) {
BandwidthUsage OverUseDetector::Detect(double ts_delta) {
if (num_of_deltas_ < 2) {
return kBwNormal;
}
const double T = BWE_MIN(numOfDeltas_, 60) * offset_;
const double T = BWE_MIN(num_of_deltas_, 60) * offset_;
if (fabsf(T) > threshold_) {
if (offset_ > 0) {
if (timeOverUsing_ == -1) {
if (time_over_using_ == -1) {
// Initialize the timer. Assume that we've been
// over-using half of the time since the previous
// sample.
timeOverUsing_ = tsDelta / 2;
time_over_using_ = ts_delta / 2;
} else {
// Increment timer
timeOverUsing_ += tsDelta;
time_over_using_ += ts_delta;
}
overUseCounter_++;
if (timeOverUsing_ > OVER_USING_TIME_THRESHOLD
&& overUseCounter_ > 1) {
if (offset_ >= prevOffset_) {
over_use_counter_++;
if (time_over_using_ > OVER_USING_TIME_THRESHOLD
&& over_use_counter_ > 1) {
if (offset_ >= prev_offset_) {
#ifdef _DEBUG
if (hypothesis_ != kBwOverusing) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwOverusing");
}
#endif
timeOverUsing_ = 0;
overUseCounter_ = 0;
time_over_using_ = 0;
over_use_counter_ = 0;
hypothesis_ = kBwOverusing;
#ifdef WEBRTC_BWE_MATLAB
plot2_->Append("detection", offset_); // plot it later
plots_.plot2_->Append("detection", offset_); // plot it later
#endif
}
}
#ifdef WEBRTC_BWE_MATLAB
plot2_->Append("trigger", offset_); // plot it later
plots_.plot2_->Append("trigger", offset_); // plot it later
#endif
} else {
#ifdef _DEBUG
@ -402,8 +367,8 @@ BandwidthUsage OverUseDetector::Detect(double tsDelta) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwUnderUsing");
}
#endif
timeOverUsing_ = -1;
overUseCounter_ = 0;
time_over_using_ = -1;
over_use_counter_ = 0;
hypothesis_ = kBwUnderUsing;
}
} else {
@ -412,25 +377,25 @@ BandwidthUsage OverUseDetector::Detect(double tsDelta) {
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwNormal");
}
#endif
timeOverUsing_ = -1;
overUseCounter_ = 0;
time_over_using_ = -1;
over_use_counter_ = 0;
hypothesis_ = kBwNormal;
}
return hypothesis_;
}
bool OverUseDetector::OldTimestamp(uint32_t newTimestamp,
uint32_t existingTimestamp,
bool OverUseDetector::OldTimestamp(uint32_t new_timestamp,
uint32_t existing_timestamp,
bool* wrapped) {
bool tmpWrapped =
(newTimestamp < 0x0000ffff && existingTimestamp > 0xffff0000) ||
(newTimestamp > 0xffff0000 && existingTimestamp < 0x0000ffff);
(new_timestamp < 0x0000ffff && existing_timestamp > 0xffff0000) ||
(new_timestamp > 0xffff0000 && existing_timestamp < 0x0000ffff);
*wrapped = tmpWrapped;
if (existingTimestamp > newTimestamp && !tmpWrapped) {
if (existing_timestamp > new_timestamp && !tmpWrapped) {
return true;
} else if (existingTimestamp <= newTimestamp && !tmpWrapped) {
} else if (existing_timestamp <= new_timestamp && !tmpWrapped) {
return false;
} else if (existingTimestamp < newTimestamp && tmpWrapped) {
} else if (existing_timestamp < new_timestamp && tmpWrapped) {
return true;
} else {
return false;

View File

@ -25,13 +25,12 @@ enum RateControlRegion;
class OverUseDetector {
public:
OverUseDetector();
explicit OverUseDetector(const OverUseDetectorOptions& options);
~OverUseDetector();
void Update(const WebRtc_UWord16 packetSize,
const WebRtc_UWord32 timestamp,
const WebRtc_Word64 nowMS);
void Update(const WebRtc_UWord16 packet_size,
const uint32_t timestamp,
const int64_t now_ms);
BandwidthUsage State() const;
void Reset();
double NoiseVar() const;
void SetRateControlRegion(RateControlRegion region);
@ -39,52 +38,59 @@ class OverUseDetector {
struct FrameSample {
FrameSample() : size_(0), completeTimeMs_(-1), timestamp_(-1) {}
WebRtc_UWord32 size_;
WebRtc_Word64 completeTimeMs_;
WebRtc_Word64 timestamp_;
uint32_t size_;
int64_t completeTimeMs_;
int64_t timestamp_;
};
static bool OldTimestamp(uint32_t newTimestamp,
uint32_t existingTimestamp,
struct DebugPlots {
#ifdef WEBRTC_BWE_MATLAB
DebugPlots() : plot1(NULL), plot2(NULL), plot3(NULL), plot4(NULL) {}
MatlabPlot* plot1;
MatlabPlot* plot2;
MatlabPlot* plot3;
MatlabPlot* plot4;
#endif
};
static bool OldTimestamp(uint32_t new_timestamp,
uint32_t existing_timestamp,
bool* wrapped);
void CompensatedTimeDelta(const FrameSample& currentFrame,
const FrameSample& prevFrame,
WebRtc_Word64& tDelta,
double& tsDelta,
void CompensatedTimeDelta(const FrameSample& current_frame,
const FrameSample& prev_frame,
int64_t& t_delta,
double& ts_delta,
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);
void UpdateKalman(int64_t t_delta,
double ts_elta,
uint32_t frame_size,
uint32_t prev_frame_size);
double UpdateMinFramePeriod(double ts_delta);
void UpdateNoiseEstimate(double residual, double ts_delta, bool stable_state);
BandwidthUsage Detect(double ts_delta);
double CurrentDrift();
bool firstPacket_;
FrameSample currentFrame_;
FrameSample prevFrame_;
WebRtc_UWord16 numOfDeltas_;
OverUseDetectorOptions options_; // Must be first member
// variable. Cannot be const
// because we need to be copyable.
bool first_packet_;
FrameSample current_frame_;
FrameSample prev_frame_;
uint16_t num_of_deltas_;
double slope_;
double offset_;
double E_[2][2];
double processNoise_[2];
double avgNoise_;
double varNoise_;
double process_noise_[2];
double avg_noise_;
double var_noise_;
double threshold_;
std::list<double> tsDeltaHist_;
double prevOffset_;
double timeOverUsing_;
WebRtc_UWord16 overUseCounter_;
std::list<double> ts_delta_hist_;
double prev_offset_;
double time_over_using_;
uint16_t over_use_counter_;
BandwidthUsage hypothesis_;
#ifdef WEBRTC_BWE_MATLAB
MatlabPlot* plot1_;
MatlabPlot* plot2_;
MatlabPlot* plot3_;
MatlabPlot* plot4_;
#endif
DebugPlots plots_;
};
} // namespace webrtc

View File

@ -15,8 +15,10 @@
namespace webrtc {
RemoteBitrateEstimator::RemoteBitrateEstimator(
RemoteBitrateObserver* observer)
: observer_(observer),
RemoteBitrateObserver* observer,
const OverUseDetectorOptions& options)
: options_(options),
observer_(observer),
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {
assert(observer_);
}
@ -35,12 +37,11 @@ void RemoteBitrateEstimator::IncomingPacket(unsigned int ssrc,
// callback will no longer be called for the old SSRC. This will be
// automatically cleaned up when we have one RemoteBitrateEstimator per REMB
// group.
bitrate_controls_[ssrc] = BitrateControls();
bitrate_controls_.insert(std::make_pair(ssrc, BitrateControls(options_)));
it = bitrate_controls_.find(ssrc);
}
OverUseDetector* overuse_detector =
&bitrate_controls_[ssrc].overuse_detector;
bitrate_controls_[ssrc].incoming_bitrate.Update(packet_size, arrival_time);
OverUseDetector* overuse_detector = &it->second.overuse_detector;
it->second.incoming_bitrate.Update(packet_size, arrival_time);
const BandwidthUsage prior_state = overuse_detector->State();
overuse_detector->Update(packet_size, rtp_timestamp, arrival_time);
if (prior_state != overuse_detector->State() &&

View File

@ -123,7 +123,7 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
virtual void SetUp() {
bitrate_observer_.reset(new TestBitrateObserver);
bitrate_estimator_.reset(new RemoteBitrateEstimator(
bitrate_observer_.get()));
bitrate_observer_.get(), over_use_detector_options_));
// Framerate: 30 fps; Start bitrate: 300 kbps; Link capacity: 1000 kbps,
// Start time: 0.
stream_generator_.reset(new StreamGenerator(30, 3e5, 1e6, 0));
@ -196,6 +196,7 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
return bitrate_bps;
}
OverUseDetectorOptions over_use_detector_options_;
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
scoped_ptr<TestBitrateObserver> bitrate_observer_;
scoped_ptr<StreamGenerator> stream_generator_;

View File

@ -59,11 +59,14 @@ class TestTransport : public Transport {
class RtcpFormatRembTest : public ::testing::Test {
protected:
RtcpFormatRembTest()
: remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_) {}
: over_use_detector_options_(),
remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_,
over_use_detector_options_) {}
virtual void SetUp();
virtual void TearDown();
OverUseDetectorOptions over_use_detector_options_;
RtpRtcpClock* system_clock_;
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
RTCPSender* rtcp_sender_;

View File

@ -183,8 +183,10 @@ class TestTransport : public Transport,
class RtcpReceiverTest : public ::testing::Test {
protected:
RtcpReceiverTest()
: remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_) {
: over_use_detector_options_(),
remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_,
over_use_detector_options_) {
// system_clock_ = ModuleRTPUtility::GetSystemClock();
system_clock_ = new FakeSystemClock();
test_transport_ = new TestTransport();
@ -221,6 +223,7 @@ class RtcpReceiverTest : public ::testing::Test {
return result;
}
OverUseDetectorOptions over_use_detector_options_;
FakeSystemClock* system_clock_;
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
RTCPReceiver* rtcp_receiver_;

View File

@ -98,8 +98,10 @@ class TestTransport : public Transport,
class RtcpSenderTest : public ::testing::Test {
protected:
RtcpSenderTest()
: remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_) {
: over_use_detector_options_(),
remote_bitrate_observer_(),
remote_bitrate_estimator_(&remote_bitrate_observer_,
over_use_detector_options_) {
system_clock_ = ModuleRTPUtility::GetSystemClock();
test_transport_ = new TestTransport();
@ -133,6 +135,7 @@ class RtcpSenderTest : public ::testing::Test {
packet_type) != 0U;
}
OverUseDetectorOptions over_use_detector_options_;
RtpRtcpClock* system_clock_;
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
RTCPSender* rtcp_sender_;

View File

@ -19,10 +19,12 @@
namespace webrtc {
ChannelGroup::ChannelGroup(ProcessThread* process_thread)
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
const OverUseDetectorOptions& options)
: remb_(new VieRemb(process_thread)),
bitrate_controller_(BitrateController::CreateBitrateController()),
remote_bitrate_estimator_(new RemoteBitrateEstimator(remb_.get())) {
remote_bitrate_estimator_(new RemoteBitrateEstimator(remb_.get(),
options)) {
}
ChannelGroup::~ChannelGroup() {

View File

@ -18,6 +18,7 @@
namespace webrtc {
class BitrateController;
struct OverUseDetectorOptions;
class ProcessThread;
class RemoteBitrateEstimator;
class RemoteBitrateObserver;
@ -29,7 +30,8 @@ class VieRemb;
// group are assumed to send/receive data to the same end-point.
class ChannelGroup {
public:
explicit ChannelGroup(ProcessThread* process_thread);
ChannelGroup(ProcessThread* process_thread,
const OverUseDetectorOptions& options);
~ChannelGroup();
void AddChannel(int channel_id);

View File

@ -27,7 +27,8 @@ namespace webrtc {
ViEChannelManager::ViEChannelManager(
int engine_id,
int number_of_cores,
ViEPerformanceMonitor& vie_performance_monitor)
ViEPerformanceMonitor& vie_performance_monitor,
const OverUseDetectorOptions& options)
: channel_id_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
engine_id_(engine_id),
number_of_cores_(number_of_cores),
@ -35,7 +36,8 @@ ViEChannelManager::ViEChannelManager(
free_channel_ids_size_(kViEMaxNumberOfChannels),
voice_sync_interface_(NULL),
voice_engine_(NULL),
module_process_thread_(NULL) {
module_process_thread_(NULL),
over_use_detector_options_(options) {
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id),
"ViEChannelManager::ViEChannelManager(engine_id: %d)",
engine_id);
@ -87,7 +89,8 @@ int ViEChannelManager::CreateChannel(int& channel_id) {
}
// Create a new channel group and add this channel.
ChannelGroup* group = new ChannelGroup(module_process_thread_);
ChannelGroup* group = new ChannelGroup(module_process_thread_,
over_use_detector_options_);
BitrateController* bitrate_controller = group->GetBitrateController();
ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id,
number_of_cores_,

View File

@ -43,7 +43,8 @@ class ViEChannelManager: private ViEManagerBase {
public:
ViEChannelManager(int engine_id,
int number_of_cores,
ViEPerformanceMonitor& vie_performance_monitor);
ViEPerformanceMonitor& vie_performance_monitor,
const OverUseDetectorOptions& options);
~ViEChannelManager();
void SetModuleProcessThread(ProcessThread& module_process_thread);
@ -125,6 +126,7 @@ class ViEChannelManager: private ViEManagerBase {
VoiceEngine* voice_engine_;
ProcessThread* module_process_thread_;
const OverUseDetectorOptions& over_use_detector_options_;
};
class ViEChannelManagerScoped: private ViEManagerScopedBase {

View File

@ -26,9 +26,11 @@ ViESharedData::ViESharedData()
: instance_id_(++instance_counter_),
initialized_(false),
number_cores_(CpuInfo::DetectNumberOfCores()),
over_use_detector_options_(),
vie_performance_monitor_(ViEPerformanceMonitor(instance_id_)),
channel_manager_(*new ViEChannelManager(instance_id_, number_cores_,
vie_performance_monitor_)),
vie_performance_monitor_,
over_use_detector_options_)),
input_manager_(*new ViEInputManager(instance_id_)),
render_manager_(*new ViERenderManager(instance_id_)),
module_process_thread_(ProcessThread::CreateProcessThread()),

View File

@ -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
@ -50,6 +50,7 @@ class ViESharedData {
bool initialized_;
const int number_cores_;
OverUseDetectorOptions over_use_detector_options_;
ViEPerformanceMonitor vie_performance_monitor_;
ViEChannelManager& channel_manager_;
ViEInputManager& input_manager_;