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:
@ -571,5 +571,32 @@ struct VideoCodec
|
|||||||
unsigned char numberOfSimulcastStreams;
|
unsigned char numberOfSimulcastStreams;
|
||||||
SimulcastStream simulcastStream[kMaxSimulcastStreams];
|
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
|
} // namespace webrtc
|
||||||
#endif // WEBRTC_COMMON_TYPES_H
|
#endif // WEBRTC_COMMON_TYPES_H
|
||||||
|
@ -39,7 +39,8 @@ class RemoteBitrateObserver {
|
|||||||
|
|
||||||
class RemoteBitrateEstimator {
|
class RemoteBitrateEstimator {
|
||||||
public:
|
public:
|
||||||
explicit RemoteBitrateEstimator(RemoteBitrateObserver* observer);
|
RemoteBitrateEstimator(RemoteBitrateObserver* observer,
|
||||||
|
const OverUseDetectorOptions& options);
|
||||||
|
|
||||||
// Called for each incoming packet. If this is a new SSRC, a new
|
// Called for each incoming packet. If this is a new SSRC, a new
|
||||||
// BitrateControl will be created.
|
// BitrateControl will be created.
|
||||||
@ -65,6 +66,16 @@ class RemoteBitrateEstimator {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
struct BitrateControls {
|
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;
|
RemoteRateControl remote_rate;
|
||||||
OverUseDetector overuse_detector;
|
OverUseDetector overuse_detector;
|
||||||
BitRateStats incoming_bitrate;
|
BitRateStats incoming_bitrate;
|
||||||
@ -72,6 +83,7 @@ class RemoteBitrateEstimator {
|
|||||||
|
|
||||||
typedef std::map<unsigned int, BitrateControls> SsrcBitrateControlsMap;
|
typedef std::map<unsigned int, BitrateControls> SsrcBitrateControlsMap;
|
||||||
|
|
||||||
|
const OverUseDetectorOptions& options_;
|
||||||
SsrcBitrateControlsMap bitrate_controls_;
|
SsrcBitrateControlsMap bitrate_controls_;
|
||||||
RemoteBitrateObserver* observer_;
|
RemoteBitrateObserver* observer_;
|
||||||
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
||||||
|
@ -23,163 +23,128 @@
|
|||||||
extern MatlabEngine eng; // global variable defined elsewhere
|
extern MatlabEngine eng; // global variable defined elsewhere
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define INIT_CAPACITY_SLOPE 8.0/512.0
|
|
||||||
#define DETECTOR_THRESHOLD 25.0
|
|
||||||
#define OVER_USING_TIME_THRESHOLD 100
|
#define OVER_USING_TIME_THRESHOLD 100
|
||||||
#define MIN_FRAME_PERIOD_HISTORY_LEN 60
|
#define MIN_FRAME_PERIOD_HISTORY_LEN 60
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
OverUseDetector::OverUseDetector()
|
OverUseDetector::OverUseDetector(const OverUseDetectorOptions& options)
|
||||||
: firstPacket_(true),
|
: options_(options),
|
||||||
currentFrame_(),
|
first_packet_(true),
|
||||||
prevFrame_(),
|
current_frame_(),
|
||||||
numOfDeltas_(0),
|
prev_frame_(),
|
||||||
slope_(INIT_CAPACITY_SLOPE),
|
num_of_deltas_(0),
|
||||||
offset_(0),
|
slope_(options_.initial_slope),
|
||||||
|
offset_(options_.initial_offset),
|
||||||
E_(),
|
E_(),
|
||||||
processNoise_(),
|
process_noise_(),
|
||||||
avgNoise_(0.0),
|
avg_noise_(options_.initial_avg_noise),
|
||||||
varNoise_(500),
|
var_noise_(options_.initial_var_noise),
|
||||||
threshold_(DETECTOR_THRESHOLD),
|
threshold_(options_.initial_threshold),
|
||||||
tsDeltaHist_(),
|
ts_delta_hist_(),
|
||||||
prevOffset_(0.0),
|
prev_offset_(0.0),
|
||||||
timeOverUsing_(-1),
|
time_over_using_(-1),
|
||||||
overUseCounter_(0),
|
over_use_counter_(0),
|
||||||
#ifndef WEBRTC_BWE_MATLAB
|
hypothesis_(kBwNormal),
|
||||||
hypothesis_(kBwNormal) {
|
plots_() {
|
||||||
#else
|
memcpy(E_, options_.initial_e, sizeof(E_));
|
||||||
plot1_(NULL),
|
memcpy(process_noise_, options_.initial_process_noise,
|
||||||
plot2_(NULL),
|
sizeof(process_noise_));
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OverUseDetector::~OverUseDetector() {
|
OverUseDetector::~OverUseDetector() {
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
if (plot1_) {
|
if (plots_.plot1_) {
|
||||||
eng.DeletePlot(plot1_);
|
eng.DeletePlot(plots_.plot1_);
|
||||||
plot1_ = NULL;
|
plots_.plot1_ = NULL;
|
||||||
}
|
}
|
||||||
if (plot2_) {
|
if (plots_.plot2_) {
|
||||||
eng.DeletePlot(plot2_);
|
eng.DeletePlot(plots_.plot2_);
|
||||||
plot2_ = NULL;
|
plots_.plot2_ = NULL;
|
||||||
}
|
}
|
||||||
if (plot3_) {
|
if (plots_.plot3_) {
|
||||||
eng.DeletePlot(plot3_);
|
eng.DeletePlot(plots_.plot3_);
|
||||||
plot3_ = NULL;
|
plots_.plot3_ = NULL;
|
||||||
}
|
}
|
||||||
if (plot4_) {
|
if (plots_.plot4_) {
|
||||||
eng.DeletePlot(plot4_);
|
eng.DeletePlot(plots_.plot4_);
|
||||||
plot4_ = NULL;
|
plots_.plot4_ = NULL;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
tsDeltaHist_.clear();
|
ts_delta_hist_.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverUseDetector::Reset() {
|
void OverUseDetector::Update(uint16_t packet_size,
|
||||||
firstPacket_ = true;
|
uint32_t timestamp,
|
||||||
currentFrame_.size_ = 0;
|
const int64_t now_ms) {
|
||||||
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) {
|
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
// Create plots
|
// Create plots
|
||||||
const WebRtc_Word64 startTimeMs = nowMS;
|
const int64_t startTimeMs = nowMS;
|
||||||
if (plot1_ == NULL) {
|
if (plots_.plot1_ == NULL) {
|
||||||
plot1_ = eng.NewPlot(new MatlabPlot());
|
plots_.plot1_ = eng.NewPlot(new MatlabPlot());
|
||||||
plot1_->AddLine(1000, "b.", "scatter");
|
plots_.plot1_->AddLine(1000, "b.", "scatter");
|
||||||
}
|
}
|
||||||
if (plot2_ == NULL) {
|
if (plots_.plot2_ == NULL) {
|
||||||
plot2_ = eng.NewPlot(new MatlabPlot());
|
plots_.plot2_ = eng.NewPlot(new MatlabPlot());
|
||||||
plot2_->AddTimeLine(30, "b", "offset", startTimeMs);
|
plots_.plot2_->AddTimeLine(30, "b", "offset", startTimeMs);
|
||||||
plot2_->AddTimeLine(30, "r--", "limitPos", startTimeMs);
|
plots_.plot2_->AddTimeLine(30, "r--", "limitPos", startTimeMs);
|
||||||
plot2_->AddTimeLine(30, "k.", "trigger", startTimeMs);
|
plots_.plot2_->AddTimeLine(30, "k.", "trigger", startTimeMs);
|
||||||
plot2_->AddTimeLine(30, "ko", "detection", startTimeMs);
|
plots_.plot2_->AddTimeLine(30, "ko", "detection", startTimeMs);
|
||||||
// plot2_->AddTimeLine(30, "g", "slowMean", startTimeMs);
|
// plots_.plot2_->AddTimeLine(30, "g", "slowMean", startTimeMs);
|
||||||
}
|
}
|
||||||
if (plot3_ == NULL) {
|
if (plots_.plot3_ == NULL) {
|
||||||
plot3_ = eng.NewPlot(new MatlabPlot());
|
plots_.plot3_ = eng.NewPlot(new MatlabPlot());
|
||||||
plot3_->AddTimeLine(30, "b", "noiseVar", startTimeMs);
|
plots_.plot3_->AddTimeLine(30, "b", "noiseVar", startTimeMs);
|
||||||
}
|
}
|
||||||
if (plot4_ == NULL) {
|
if (plots_.plot4_ == NULL) {
|
||||||
plot4_ = eng.NewPlot(new MatlabPlot());
|
plots_.plot4_ = eng.NewPlot(new MatlabPlot());
|
||||||
// plot4_->AddTimeLine(60, "b", "p11", startTimeMs);
|
// plots_.plot4_->AddTimeLine(60, "b", "p11", startTimeMs);
|
||||||
// plot4_->AddTimeLine(60, "r", "p12", startTimeMs);
|
// plots_.plot4_->AddTimeLine(60, "r", "p12", startTimeMs);
|
||||||
plot4_->AddTimeLine(60, "g", "p22", startTimeMs);
|
plots_.plot4_->AddTimeLine(60, "g", "p22", startTimeMs);
|
||||||
// plot4_->AddTimeLine(60, "g--", "p22_hat", startTimeMs);
|
// plots_.plot4_->AddTimeLine(60, "g--", "p22_hat", startTimeMs);
|
||||||
// plot4_->AddTimeLine(30, "b.-", "deltaFs", startTimeMs);
|
// plots_.plot4_->AddTimeLine(30, "b.-", "deltaFs", startTimeMs);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool wrapped = false;
|
bool wrapped = false;
|
||||||
bool completeFrame = false;
|
bool completeFrame = false;
|
||||||
if (currentFrame_.timestamp_ == -1) {
|
if (current_frame_.timestamp_ == -1) {
|
||||||
currentFrame_.timestamp_ = timestamp;
|
current_frame_.timestamp_ = timestamp;
|
||||||
} else if (OldTimestamp(
|
} else if (OldTimestamp(
|
||||||
timestamp,
|
timestamp,
|
||||||
static_cast<WebRtc_UWord32>(currentFrame_.timestamp_),
|
static_cast<uint32_t>(current_frame_.timestamp_),
|
||||||
&wrapped)) {
|
&wrapped)) {
|
||||||
// Don't update with old data
|
// Don't update with old data
|
||||||
return;
|
return;
|
||||||
} else if (timestamp != currentFrame_.timestamp_) {
|
} else if (timestamp != current_frame_.timestamp_) {
|
||||||
// First packet of a later frame, the previous frame sample is ready
|
// First packet of a later frame, the previous frame sample is ready
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1,
|
||||||
"Frame complete at %I64i", currentFrame_.completeTimeMs_);
|
"Frame complete at %I64i", current_frame_.completeTimeMs_);
|
||||||
if (prevFrame_.completeTimeMs_ >= 0) { // This is our second frame
|
if (prev_frame_.completeTimeMs_ >= 0) { // This is our second frame
|
||||||
WebRtc_Word64 tDelta = 0;
|
int64_t t_delta = 0;
|
||||||
double tsDelta = 0;
|
double ts_delta = 0;
|
||||||
// Check for wrap
|
// Check for wrap
|
||||||
OldTimestamp(
|
OldTimestamp(
|
||||||
static_cast<WebRtc_UWord32>(prevFrame_.timestamp_),
|
static_cast<uint32_t>(prev_frame_.timestamp_),
|
||||||
static_cast<WebRtc_UWord32>(currentFrame_.timestamp_),
|
static_cast<uint32_t>(current_frame_.timestamp_),
|
||||||
&wrapped);
|
&wrapped);
|
||||||
CompensatedTimeDelta(currentFrame_, prevFrame_, tDelta, tsDelta,
|
CompensatedTimeDelta(current_frame_, prev_frame_, t_delta, ts_delta,
|
||||||
wrapped);
|
wrapped);
|
||||||
UpdateKalman(tDelta, tsDelta, currentFrame_.size_,
|
UpdateKalman(t_delta, ts_delta, current_frame_.size_,
|
||||||
prevFrame_.size_);
|
prev_frame_.size_);
|
||||||
}
|
}
|
||||||
// The new timestamp is now the current frame,
|
// The new timestamp is now the current frame,
|
||||||
// and the old timestamp becomes the previous frame.
|
// and the old timestamp becomes the previous frame.
|
||||||
prevFrame_ = currentFrame_;
|
prev_frame_ = current_frame_;
|
||||||
currentFrame_.timestamp_ = timestamp;
|
current_frame_.timestamp_ = timestamp;
|
||||||
currentFrame_.size_ = 0;
|
current_frame_.size_ = 0;
|
||||||
currentFrame_.completeTimeMs_ = -1;
|
current_frame_.completeTimeMs_ = -1;
|
||||||
completeFrame = true;
|
completeFrame = true;
|
||||||
}
|
}
|
||||||
// Accumulate the frame size
|
// Accumulate the frame size
|
||||||
currentFrame_.size_ += packetSize;
|
current_frame_.size_ += packet_size;
|
||||||
currentFrame_.completeTimeMs_ = nowMS;
|
current_frame_.completeTimeMs_ = now_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
BandwidthUsage OverUseDetector::State() const {
|
BandwidthUsage OverUseDetector::State() const {
|
||||||
@ -187,18 +152,18 @@ BandwidthUsage OverUseDetector::State() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double OverUseDetector::NoiseVar() const {
|
double OverUseDetector::NoiseVar() const {
|
||||||
return varNoise_;
|
return var_noise_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverUseDetector::SetRateControlRegion(RateControlRegion region) {
|
void OverUseDetector::SetRateControlRegion(RateControlRegion region) {
|
||||||
switch (region) {
|
switch (region) {
|
||||||
case kRcMaxUnknown: {
|
case kRcMaxUnknown: {
|
||||||
threshold_ = DETECTOR_THRESHOLD;
|
threshold_ = options_.initial_threshold;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case kRcAboveMax:
|
case kRcAboveMax:
|
||||||
case kRcNearMax: {
|
case kRcNearMax: {
|
||||||
threshold_ = DETECTOR_THRESHOLD / 2;
|
threshold_ = options_.initial_threshold / 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,47 +171,47 @@ void OverUseDetector::SetRateControlRegion(RateControlRegion region) {
|
|||||||
|
|
||||||
void OverUseDetector::CompensatedTimeDelta(const FrameSample& currentFrame,
|
void OverUseDetector::CompensatedTimeDelta(const FrameSample& currentFrame,
|
||||||
const FrameSample& prevFrame,
|
const FrameSample& prevFrame,
|
||||||
WebRtc_Word64& tDelta,
|
int64_t& t_delta,
|
||||||
double& tsDelta,
|
double& ts_delta,
|
||||||
bool wrapped) {
|
bool wrapped) {
|
||||||
numOfDeltas_++;
|
num_of_deltas_++;
|
||||||
if (numOfDeltas_ > 1000) {
|
if (num_of_deltas_ > 1000) {
|
||||||
numOfDeltas_ = 1000;
|
num_of_deltas_ = 1000;
|
||||||
}
|
}
|
||||||
// Add wrap-around compensation
|
// Add wrap-around compensation
|
||||||
WebRtc_Word64 wrapCompensation = 0;
|
int64_t wrapCompensation = 0;
|
||||||
if (wrapped) {
|
if (wrapped) {
|
||||||
wrapCompensation = static_cast<WebRtc_Word64>(1)<<32;
|
wrapCompensation = static_cast<int64_t>(1)<<32;
|
||||||
}
|
}
|
||||||
tsDelta = (currentFrame.timestamp_
|
ts_delta = (currentFrame.timestamp_
|
||||||
+ wrapCompensation
|
+ wrapCompensation
|
||||||
- prevFrame.timestamp_) / 90.0;
|
- prevFrame.timestamp_) / 90.0;
|
||||||
tDelta = currentFrame.completeTimeMs_ - prevFrame.completeTimeMs_;
|
t_delta = currentFrame.completeTimeMs_ - prevFrame.completeTimeMs_;
|
||||||
assert(tsDelta > 0);
|
assert(ts_delta > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
double OverUseDetector::CurrentDrift() {
|
double OverUseDetector::CurrentDrift() {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverUseDetector::UpdateKalman(WebRtc_Word64 tDelta,
|
void OverUseDetector::UpdateKalman(int64_t t_delta,
|
||||||
double tsDelta,
|
double ts_delta,
|
||||||
WebRtc_UWord32 frameSize,
|
uint32_t frame_size,
|
||||||
WebRtc_UWord32 prevFrameSize) {
|
uint32_t prev_frame_size) {
|
||||||
const double minFramePeriod = UpdateMinFramePeriod(tsDelta);
|
const double minFramePeriod = UpdateMinFramePeriod(ts_delta);
|
||||||
const double drift = CurrentDrift();
|
const double drift = CurrentDrift();
|
||||||
// Compensate for drift
|
// Compensate for drift
|
||||||
const double tTsDelta = tDelta - tsDelta / drift;
|
const double tTsDelta = t_delta - ts_delta / drift;
|
||||||
double fsDelta = static_cast<double>(frameSize) - prevFrameSize;
|
double fsDelta = static_cast<double>(frame_size) - prev_frame_size;
|
||||||
|
|
||||||
// Update the Kalman filter
|
// Update the Kalman filter
|
||||||
const double scaleFactor = minFramePeriod / (1000.0 / 30.0);
|
const double scaleFactor = minFramePeriod / (1000.0 / 30.0);
|
||||||
E_[0][0] += processNoise_[0] * scaleFactor;
|
E_[0][0] += process_noise_[0] * scaleFactor;
|
||||||
E_[1][1] += processNoise_[1] * scaleFactor;
|
E_[1][1] += process_noise_[1] * scaleFactor;
|
||||||
|
|
||||||
if ((hypothesis_ == kBwOverusing && offset_ < prevOffset_) ||
|
if ((hypothesis_ == kBwOverusing && offset_ < prev_offset_) ||
|
||||||
(hypothesis_ == kBwUnderUsing && offset_ > prevOffset_)) {
|
(hypothesis_ == kBwUnderUsing && offset_ > prev_offset_)) {
|
||||||
E_[1][1] += 10 * processNoise_[1] * scaleFactor;
|
E_[1][1] += 10 * process_noise_[1] * scaleFactor;
|
||||||
}
|
}
|
||||||
|
|
||||||
const double h[2] = {fsDelta, 1.0};
|
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 double residual = tTsDelta - slope_*h[0] - offset_;
|
||||||
|
|
||||||
const bool stableState =
|
const bool stable_state =
|
||||||
(BWE_MIN(numOfDeltas_, 60) * fabsf(offset_) < threshold_);
|
(BWE_MIN(num_of_deltas_, 60) * fabsf(offset_) < threshold_);
|
||||||
// We try to filter out very late frames. For instance periodic key
|
// We try to filter out very late frames. For instance periodic key
|
||||||
// frames doesn't fit the Gaussian model well.
|
// frames doesn't fit the Gaussian model well.
|
||||||
if (fabsf(residual) < 3 * sqrt(varNoise_)) {
|
if (fabsf(residual) < 3 * sqrt(var_noise_)) {
|
||||||
UpdateNoiseEstimate(residual, minFramePeriod, stableState);
|
UpdateNoiseEstimate(residual, minFramePeriod, stable_state);
|
||||||
} else {
|
} 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,
|
const double K[2] = {Eh[0] / denom,
|
||||||
Eh[1] / denom};
|
Eh[1] / denom};
|
||||||
@ -287,114 +252,114 @@ void OverUseDetector::UpdateKalman(WebRtc_Word64 tDelta,
|
|||||||
E_[0][0] >= 0);
|
E_[0][0] >= 0);
|
||||||
|
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
// plot4_->Append("p11",E_[0][0]);
|
// plots_.plot4_->Append("p11",E_[0][0]);
|
||||||
// plot4_->Append("p12",E_[0][1]);
|
// plots_.plot4_->Append("p12",E_[0][1]);
|
||||||
plot4_->Append("p22", E_[1][1]);
|
plots_.plot4_->Append("p22", E_[1][1]);
|
||||||
// plot4_->Append("p22_hat", 0.5*(processNoise_[1] +
|
// plots_.plot4_->Append("p22_hat", 0.5*(process_noise_[1] +
|
||||||
// sqrt(processNoise_[1]*(processNoise_[1] + 4*varNoise_))));
|
// sqrt(process_noise_[1]*(process_noise_[1] + 4*var_noise_))));
|
||||||
// plot4_->Append("deltaFs", fsDelta);
|
// plots_.plot4_->Append("deltaFs", fsDelta);
|
||||||
plot4_->Plot();
|
plots_.plot4_->Plot();
|
||||||
#endif
|
#endif
|
||||||
slope_ = slope_ + K[0] * residual;
|
slope_ = slope_ + K[0] * residual;
|
||||||
prevOffset_ = offset_;
|
prev_offset_ = offset_;
|
||||||
offset_ = offset_ + K[1] * residual;
|
offset_ = offset_ + K[1] * residual;
|
||||||
|
|
||||||
Detect(tsDelta);
|
Detect(ts_delta);
|
||||||
|
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
plot1_->Append("scatter",
|
plots_.plot1_->Append("scatter",
|
||||||
static_cast<double>(currentFrame_.size_) - prevFrame_.size_,
|
static_cast<double>(current_frame_.size_) - prev_frame_.size_,
|
||||||
static_cast<double>(tDelta-tsDelta));
|
static_cast<double>(t_delta - ts_delta));
|
||||||
plot1_->MakeTrend("scatter", "slope", slope_, offset_, "k-");
|
plots_.plot1_->MakeTrend("scatter", "slope", slope_, offset_, "k-");
|
||||||
plot1_->MakeTrend("scatter", "thresholdPos",
|
plots_.plot1_->MakeTrend("scatter", "thresholdPos",
|
||||||
slope_, offset_ + 2 * sqrt(varNoise_), "r-");
|
slope_, offset_ + 2 * sqrt(var_noise_), "r-");
|
||||||
plot1_->MakeTrend("scatter", "thresholdNeg",
|
plots_.plot1_->MakeTrend("scatter", "thresholdNeg",
|
||||||
slope_, offset_ - 2 * sqrt(varNoise_), "r-");
|
slope_, offset_ - 2 * sqrt(var_noise_), "r-");
|
||||||
plot1_->Plot();
|
plots_.plot1_->Plot();
|
||||||
|
|
||||||
plot2_->Append("offset", offset_);
|
plots_.plot2_->Append("offset", offset_);
|
||||||
plot2_->Append("limitPos", threshold_/BWE_MIN(numOfDeltas_, 60));
|
plots_.plot2_->Append("limitPos", threshold_/BWE_MIN(num_of_deltas_, 60));
|
||||||
plot2_->Plot();
|
plots_.plot2_->Plot();
|
||||||
|
|
||||||
plot3_->Append("noiseVar", varNoise_);
|
plots_.plot3_->Append("noiseVar", var_noise_);
|
||||||
plot3_->Plot();
|
plots_.plot3_->Plot();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
double OverUseDetector::UpdateMinFramePeriod(double tsDelta) {
|
double OverUseDetector::UpdateMinFramePeriod(double ts_delta) {
|
||||||
double minFramePeriod = tsDelta;
|
double minFramePeriod = ts_delta;
|
||||||
if (tsDeltaHist_.size() >= MIN_FRAME_PERIOD_HISTORY_LEN) {
|
if (ts_delta_hist_.size() >= MIN_FRAME_PERIOD_HISTORY_LEN) {
|
||||||
std::list<double>::iterator firstItem = tsDeltaHist_.begin();
|
std::list<double>::iterator firstItem = ts_delta_hist_.begin();
|
||||||
tsDeltaHist_.erase(firstItem);
|
ts_delta_hist_.erase(firstItem);
|
||||||
}
|
}
|
||||||
std::list<double>::iterator it = tsDeltaHist_.begin();
|
std::list<double>::iterator it = ts_delta_hist_.begin();
|
||||||
for (; it != tsDeltaHist_.end(); it++) {
|
for (; it != ts_delta_hist_.end(); it++) {
|
||||||
minFramePeriod = BWE_MIN(*it, minFramePeriod);
|
minFramePeriod = BWE_MIN(*it, minFramePeriod);
|
||||||
}
|
}
|
||||||
tsDeltaHist_.push_back(tsDelta);
|
ts_delta_hist_.push_back(ts_delta);
|
||||||
return minFramePeriod;
|
return minFramePeriod;
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverUseDetector::UpdateNoiseEstimate(double residual,
|
void OverUseDetector::UpdateNoiseEstimate(double residual,
|
||||||
double tsDelta,
|
double ts_delta,
|
||||||
bool stableState) {
|
bool stable_state) {
|
||||||
if (!stableState) {
|
if (!stable_state) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Faster filter during startup to faster adapt to the jitter level
|
// Faster filter during startup to faster adapt to the jitter level
|
||||||
// of the network alpha is tuned for 30 frames per second, but
|
// of the network alpha is tuned for 30 frames per second, but
|
||||||
double alpha = 0.01;
|
double alpha = 0.01;
|
||||||
if (numOfDeltas_ > 10*30) {
|
if (num_of_deltas_ > 10*30) {
|
||||||
alpha = 0.002;
|
alpha = 0.002;
|
||||||
}
|
}
|
||||||
// Only update the noise estimate if we're not over-using
|
// Only update the noise estimate if we're not over-using
|
||||||
// beta is a function of alpha and the time delta since
|
// beta is a function of alpha and the time delta since
|
||||||
// the previous update.
|
// the previous update.
|
||||||
const double beta = pow(1 - alpha, tsDelta * 30.0 / 1000.0);
|
const double beta = pow(1 - alpha, ts_delta * 30.0 / 1000.0);
|
||||||
avgNoise_ = beta * avgNoise_
|
avg_noise_ = beta * avg_noise_
|
||||||
+ (1 - beta) * residual;
|
+ (1 - beta) * residual;
|
||||||
varNoise_ = beta * varNoise_
|
var_noise_ = beta * var_noise_
|
||||||
+ (1 - beta) * (avgNoise_ - residual) * (avgNoise_ - residual);
|
+ (1 - beta) * (avg_noise_ - residual) * (avg_noise_ - residual);
|
||||||
if (varNoise_ < 1e-7) {
|
if (var_noise_ < 1e-7) {
|
||||||
varNoise_ = 1e-7;
|
var_noise_ = 1e-7;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BandwidthUsage OverUseDetector::Detect(double tsDelta) {
|
BandwidthUsage OverUseDetector::Detect(double ts_delta) {
|
||||||
if (numOfDeltas_ < 2) {
|
if (num_of_deltas_ < 2) {
|
||||||
return kBwNormal;
|
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 (fabsf(T) > threshold_) {
|
||||||
if (offset_ > 0) {
|
if (offset_ > 0) {
|
||||||
if (timeOverUsing_ == -1) {
|
if (time_over_using_ == -1) {
|
||||||
// Initialize the timer. Assume that we've been
|
// Initialize the timer. Assume that we've been
|
||||||
// over-using half of the time since the previous
|
// over-using half of the time since the previous
|
||||||
// sample.
|
// sample.
|
||||||
timeOverUsing_ = tsDelta / 2;
|
time_over_using_ = ts_delta / 2;
|
||||||
} else {
|
} else {
|
||||||
// Increment timer
|
// Increment timer
|
||||||
timeOverUsing_ += tsDelta;
|
time_over_using_ += ts_delta;
|
||||||
}
|
}
|
||||||
overUseCounter_++;
|
over_use_counter_++;
|
||||||
if (timeOverUsing_ > OVER_USING_TIME_THRESHOLD
|
if (time_over_using_ > OVER_USING_TIME_THRESHOLD
|
||||||
&& overUseCounter_ > 1) {
|
&& over_use_counter_ > 1) {
|
||||||
if (offset_ >= prevOffset_) {
|
if (offset_ >= prev_offset_) {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
if (hypothesis_ != kBwOverusing) {
|
if (hypothesis_ != kBwOverusing) {
|
||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwOverusing");
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwOverusing");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
timeOverUsing_ = 0;
|
time_over_using_ = 0;
|
||||||
overUseCounter_ = 0;
|
over_use_counter_ = 0;
|
||||||
hypothesis_ = kBwOverusing;
|
hypothesis_ = kBwOverusing;
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
plot2_->Append("detection", offset_); // plot it later
|
plots_.plot2_->Append("detection", offset_); // plot it later
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
plot2_->Append("trigger", offset_); // plot it later
|
plots_.plot2_->Append("trigger", offset_); // plot it later
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#ifdef _DEBUG
|
#ifdef _DEBUG
|
||||||
@ -402,8 +367,8 @@ BandwidthUsage OverUseDetector::Detect(double tsDelta) {
|
|||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwUnderUsing");
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwUnderUsing");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
timeOverUsing_ = -1;
|
time_over_using_ = -1;
|
||||||
overUseCounter_ = 0;
|
over_use_counter_ = 0;
|
||||||
hypothesis_ = kBwUnderUsing;
|
hypothesis_ = kBwUnderUsing;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -412,25 +377,25 @@ BandwidthUsage OverUseDetector::Detect(double tsDelta) {
|
|||||||
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwNormal");
|
WEBRTC_TRACE(kTraceStream, kTraceRtpRtcp, -1, "BWE: kBwNormal");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
timeOverUsing_ = -1;
|
time_over_using_ = -1;
|
||||||
overUseCounter_ = 0;
|
over_use_counter_ = 0;
|
||||||
hypothesis_ = kBwNormal;
|
hypothesis_ = kBwNormal;
|
||||||
}
|
}
|
||||||
return hypothesis_;
|
return hypothesis_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OverUseDetector::OldTimestamp(uint32_t newTimestamp,
|
bool OverUseDetector::OldTimestamp(uint32_t new_timestamp,
|
||||||
uint32_t existingTimestamp,
|
uint32_t existing_timestamp,
|
||||||
bool* wrapped) {
|
bool* wrapped) {
|
||||||
bool tmpWrapped =
|
bool tmpWrapped =
|
||||||
(newTimestamp < 0x0000ffff && existingTimestamp > 0xffff0000) ||
|
(new_timestamp < 0x0000ffff && existing_timestamp > 0xffff0000) ||
|
||||||
(newTimestamp > 0xffff0000 && existingTimestamp < 0x0000ffff);
|
(new_timestamp > 0xffff0000 && existing_timestamp < 0x0000ffff);
|
||||||
*wrapped = tmpWrapped;
|
*wrapped = tmpWrapped;
|
||||||
if (existingTimestamp > newTimestamp && !tmpWrapped) {
|
if (existing_timestamp > new_timestamp && !tmpWrapped) {
|
||||||
return true;
|
return true;
|
||||||
} else if (existingTimestamp <= newTimestamp && !tmpWrapped) {
|
} else if (existing_timestamp <= new_timestamp && !tmpWrapped) {
|
||||||
return false;
|
return false;
|
||||||
} else if (existingTimestamp < newTimestamp && tmpWrapped) {
|
} else if (existing_timestamp < new_timestamp && tmpWrapped) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
@ -25,13 +25,12 @@ enum RateControlRegion;
|
|||||||
|
|
||||||
class OverUseDetector {
|
class OverUseDetector {
|
||||||
public:
|
public:
|
||||||
OverUseDetector();
|
explicit OverUseDetector(const OverUseDetectorOptions& options);
|
||||||
~OverUseDetector();
|
~OverUseDetector();
|
||||||
void Update(const WebRtc_UWord16 packetSize,
|
void Update(const WebRtc_UWord16 packet_size,
|
||||||
const WebRtc_UWord32 timestamp,
|
const uint32_t timestamp,
|
||||||
const WebRtc_Word64 nowMS);
|
const int64_t now_ms);
|
||||||
BandwidthUsage State() const;
|
BandwidthUsage State() const;
|
||||||
void Reset();
|
|
||||||
double NoiseVar() const;
|
double NoiseVar() const;
|
||||||
void SetRateControlRegion(RateControlRegion region);
|
void SetRateControlRegion(RateControlRegion region);
|
||||||
|
|
||||||
@ -39,52 +38,59 @@ class OverUseDetector {
|
|||||||
struct FrameSample {
|
struct FrameSample {
|
||||||
FrameSample() : size_(0), completeTimeMs_(-1), timestamp_(-1) {}
|
FrameSample() : size_(0), completeTimeMs_(-1), timestamp_(-1) {}
|
||||||
|
|
||||||
WebRtc_UWord32 size_;
|
uint32_t size_;
|
||||||
WebRtc_Word64 completeTimeMs_;
|
int64_t completeTimeMs_;
|
||||||
WebRtc_Word64 timestamp_;
|
int64_t timestamp_;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool OldTimestamp(uint32_t newTimestamp,
|
struct DebugPlots {
|
||||||
uint32_t existingTimestamp,
|
#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);
|
bool* wrapped);
|
||||||
|
|
||||||
void CompensatedTimeDelta(const FrameSample& currentFrame,
|
void CompensatedTimeDelta(const FrameSample& current_frame,
|
||||||
const FrameSample& prevFrame,
|
const FrameSample& prev_frame,
|
||||||
WebRtc_Word64& tDelta,
|
int64_t& t_delta,
|
||||||
double& tsDelta,
|
double& ts_delta,
|
||||||
bool wrapped);
|
bool wrapped);
|
||||||
void UpdateKalman(WebRtc_Word64 tDelta,
|
void UpdateKalman(int64_t t_delta,
|
||||||
double tsDelta,
|
double ts_elta,
|
||||||
WebRtc_UWord32 frameSize,
|
uint32_t frame_size,
|
||||||
WebRtc_UWord32 prevFrameSize);
|
uint32_t prev_frame_size);
|
||||||
double UpdateMinFramePeriod(double tsDelta);
|
double UpdateMinFramePeriod(double ts_delta);
|
||||||
void UpdateNoiseEstimate(double residual, double tsDelta, bool stableState);
|
void UpdateNoiseEstimate(double residual, double ts_delta, bool stable_state);
|
||||||
BandwidthUsage Detect(double tsDelta);
|
BandwidthUsage Detect(double ts_delta);
|
||||||
double CurrentDrift();
|
double CurrentDrift();
|
||||||
|
|
||||||
bool firstPacket_;
|
OverUseDetectorOptions options_; // Must be first member
|
||||||
FrameSample currentFrame_;
|
// variable. Cannot be const
|
||||||
FrameSample prevFrame_;
|
// because we need to be copyable.
|
||||||
WebRtc_UWord16 numOfDeltas_;
|
bool first_packet_;
|
||||||
|
FrameSample current_frame_;
|
||||||
|
FrameSample prev_frame_;
|
||||||
|
uint16_t num_of_deltas_;
|
||||||
double slope_;
|
double slope_;
|
||||||
double offset_;
|
double offset_;
|
||||||
double E_[2][2];
|
double E_[2][2];
|
||||||
double processNoise_[2];
|
double process_noise_[2];
|
||||||
double avgNoise_;
|
double avg_noise_;
|
||||||
double varNoise_;
|
double var_noise_;
|
||||||
double threshold_;
|
double threshold_;
|
||||||
std::list<double> tsDeltaHist_;
|
std::list<double> ts_delta_hist_;
|
||||||
double prevOffset_;
|
double prev_offset_;
|
||||||
double timeOverUsing_;
|
double time_over_using_;
|
||||||
WebRtc_UWord16 overUseCounter_;
|
uint16_t over_use_counter_;
|
||||||
BandwidthUsage hypothesis_;
|
BandwidthUsage hypothesis_;
|
||||||
|
DebugPlots plots_;
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
|
||||||
MatlabPlot* plot1_;
|
|
||||||
MatlabPlot* plot2_;
|
|
||||||
MatlabPlot* plot3_;
|
|
||||||
MatlabPlot* plot4_;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|
||||||
|
@ -15,8 +15,10 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
RemoteBitrateEstimator::RemoteBitrateEstimator(
|
RemoteBitrateEstimator::RemoteBitrateEstimator(
|
||||||
RemoteBitrateObserver* observer)
|
RemoteBitrateObserver* observer,
|
||||||
: observer_(observer),
|
const OverUseDetectorOptions& options)
|
||||||
|
: options_(options),
|
||||||
|
observer_(observer),
|
||||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {
|
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {
|
||||||
assert(observer_);
|
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
|
// callback will no longer be called for the old SSRC. This will be
|
||||||
// automatically cleaned up when we have one RemoteBitrateEstimator per REMB
|
// automatically cleaned up when we have one RemoteBitrateEstimator per REMB
|
||||||
// group.
|
// group.
|
||||||
bitrate_controls_[ssrc] = BitrateControls();
|
bitrate_controls_.insert(std::make_pair(ssrc, BitrateControls(options_)));
|
||||||
it = bitrate_controls_.find(ssrc);
|
it = bitrate_controls_.find(ssrc);
|
||||||
}
|
}
|
||||||
OverUseDetector* overuse_detector =
|
OverUseDetector* overuse_detector = &it->second.overuse_detector;
|
||||||
&bitrate_controls_[ssrc].overuse_detector;
|
it->second.incoming_bitrate.Update(packet_size, arrival_time);
|
||||||
bitrate_controls_[ssrc].incoming_bitrate.Update(packet_size, arrival_time);
|
|
||||||
const BandwidthUsage prior_state = overuse_detector->State();
|
const BandwidthUsage prior_state = overuse_detector->State();
|
||||||
overuse_detector->Update(packet_size, rtp_timestamp, arrival_time);
|
overuse_detector->Update(packet_size, rtp_timestamp, arrival_time);
|
||||||
if (prior_state != overuse_detector->State() &&
|
if (prior_state != overuse_detector->State() &&
|
||||||
|
@ -123,7 +123,7 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
|
|||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
bitrate_observer_.reset(new TestBitrateObserver);
|
bitrate_observer_.reset(new TestBitrateObserver);
|
||||||
bitrate_estimator_.reset(new RemoteBitrateEstimator(
|
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,
|
// Framerate: 30 fps; Start bitrate: 300 kbps; Link capacity: 1000 kbps,
|
||||||
// Start time: 0.
|
// Start time: 0.
|
||||||
stream_generator_.reset(new StreamGenerator(30, 3e5, 1e6, 0));
|
stream_generator_.reset(new StreamGenerator(30, 3e5, 1e6, 0));
|
||||||
@ -196,6 +196,7 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
|
|||||||
return bitrate_bps;
|
return bitrate_bps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OverUseDetectorOptions over_use_detector_options_;
|
||||||
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
||||||
scoped_ptr<TestBitrateObserver> bitrate_observer_;
|
scoped_ptr<TestBitrateObserver> bitrate_observer_;
|
||||||
scoped_ptr<StreamGenerator> stream_generator_;
|
scoped_ptr<StreamGenerator> stream_generator_;
|
||||||
|
@ -59,11 +59,14 @@ class TestTransport : public Transport {
|
|||||||
class RtcpFormatRembTest : public ::testing::Test {
|
class RtcpFormatRembTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
RtcpFormatRembTest()
|
RtcpFormatRembTest()
|
||||||
: remote_bitrate_observer_(),
|
: over_use_detector_options_(),
|
||||||
remote_bitrate_estimator_(&remote_bitrate_observer_) {}
|
remote_bitrate_observer_(),
|
||||||
|
remote_bitrate_estimator_(&remote_bitrate_observer_,
|
||||||
|
over_use_detector_options_) {}
|
||||||
virtual void SetUp();
|
virtual void SetUp();
|
||||||
virtual void TearDown();
|
virtual void TearDown();
|
||||||
|
|
||||||
|
OverUseDetectorOptions over_use_detector_options_;
|
||||||
RtpRtcpClock* system_clock_;
|
RtpRtcpClock* system_clock_;
|
||||||
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
|
ModuleRtpRtcpImpl* dummy_rtp_rtcp_impl_;
|
||||||
RTCPSender* rtcp_sender_;
|
RTCPSender* rtcp_sender_;
|
||||||
|
@ -183,8 +183,10 @@ class TestTransport : public Transport,
|
|||||||
class RtcpReceiverTest : public ::testing::Test {
|
class RtcpReceiverTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
RtcpReceiverTest()
|
RtcpReceiverTest()
|
||||||
: remote_bitrate_observer_(),
|
: over_use_detector_options_(),
|
||||||
remote_bitrate_estimator_(&remote_bitrate_observer_) {
|
remote_bitrate_observer_(),
|
||||||
|
remote_bitrate_estimator_(&remote_bitrate_observer_,
|
||||||
|
over_use_detector_options_) {
|
||||||
// system_clock_ = ModuleRTPUtility::GetSystemClock();
|
// system_clock_ = ModuleRTPUtility::GetSystemClock();
|
||||||
system_clock_ = new FakeSystemClock();
|
system_clock_ = new FakeSystemClock();
|
||||||
test_transport_ = new TestTransport();
|
test_transport_ = new TestTransport();
|
||||||
@ -221,6 +223,7 @@ class RtcpReceiverTest : public ::testing::Test {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OverUseDetectorOptions over_use_detector_options_;
|
||||||
FakeSystemClock* system_clock_;
|
FakeSystemClock* system_clock_;
|
||||||
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
|
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
|
||||||
RTCPReceiver* rtcp_receiver_;
|
RTCPReceiver* rtcp_receiver_;
|
||||||
|
@ -98,8 +98,10 @@ class TestTransport : public Transport,
|
|||||||
class RtcpSenderTest : public ::testing::Test {
|
class RtcpSenderTest : public ::testing::Test {
|
||||||
protected:
|
protected:
|
||||||
RtcpSenderTest()
|
RtcpSenderTest()
|
||||||
: remote_bitrate_observer_(),
|
: over_use_detector_options_(),
|
||||||
remote_bitrate_estimator_(&remote_bitrate_observer_) {
|
remote_bitrate_observer_(),
|
||||||
|
remote_bitrate_estimator_(&remote_bitrate_observer_,
|
||||||
|
over_use_detector_options_) {
|
||||||
system_clock_ = ModuleRTPUtility::GetSystemClock();
|
system_clock_ = ModuleRTPUtility::GetSystemClock();
|
||||||
test_transport_ = new TestTransport();
|
test_transport_ = new TestTransport();
|
||||||
|
|
||||||
@ -133,6 +135,7 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
packet_type) != 0U;
|
packet_type) != 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OverUseDetectorOptions over_use_detector_options_;
|
||||||
RtpRtcpClock* system_clock_;
|
RtpRtcpClock* system_clock_;
|
||||||
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
|
ModuleRtpRtcpImpl* rtp_rtcp_impl_;
|
||||||
RTCPSender* rtcp_sender_;
|
RTCPSender* rtcp_sender_;
|
||||||
|
@ -19,10 +19,12 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
ChannelGroup::ChannelGroup(ProcessThread* process_thread)
|
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
|
||||||
|
const OverUseDetectorOptions& options)
|
||||||
: remb_(new VieRemb(process_thread)),
|
: remb_(new VieRemb(process_thread)),
|
||||||
bitrate_controller_(BitrateController::CreateBitrateController()),
|
bitrate_controller_(BitrateController::CreateBitrateController()),
|
||||||
remote_bitrate_estimator_(new RemoteBitrateEstimator(remb_.get())) {
|
remote_bitrate_estimator_(new RemoteBitrateEstimator(remb_.get(),
|
||||||
|
options)) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelGroup::~ChannelGroup() {
|
ChannelGroup::~ChannelGroup() {
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class BitrateController;
|
class BitrateController;
|
||||||
|
struct OverUseDetectorOptions;
|
||||||
class ProcessThread;
|
class ProcessThread;
|
||||||
class RemoteBitrateEstimator;
|
class RemoteBitrateEstimator;
|
||||||
class RemoteBitrateObserver;
|
class RemoteBitrateObserver;
|
||||||
@ -29,7 +30,8 @@ class VieRemb;
|
|||||||
// group are assumed to send/receive data to the same end-point.
|
// group are assumed to send/receive data to the same end-point.
|
||||||
class ChannelGroup {
|
class ChannelGroup {
|
||||||
public:
|
public:
|
||||||
explicit ChannelGroup(ProcessThread* process_thread);
|
ChannelGroup(ProcessThread* process_thread,
|
||||||
|
const OverUseDetectorOptions& options);
|
||||||
~ChannelGroup();
|
~ChannelGroup();
|
||||||
|
|
||||||
void AddChannel(int channel_id);
|
void AddChannel(int channel_id);
|
||||||
|
@ -27,7 +27,8 @@ namespace webrtc {
|
|||||||
ViEChannelManager::ViEChannelManager(
|
ViEChannelManager::ViEChannelManager(
|
||||||
int engine_id,
|
int engine_id,
|
||||||
int number_of_cores,
|
int number_of_cores,
|
||||||
ViEPerformanceMonitor& vie_performance_monitor)
|
ViEPerformanceMonitor& vie_performance_monitor,
|
||||||
|
const OverUseDetectorOptions& options)
|
||||||
: channel_id_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
: channel_id_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
engine_id_(engine_id),
|
engine_id_(engine_id),
|
||||||
number_of_cores_(number_of_cores),
|
number_of_cores_(number_of_cores),
|
||||||
@ -35,7 +36,8 @@ ViEChannelManager::ViEChannelManager(
|
|||||||
free_channel_ids_size_(kViEMaxNumberOfChannels),
|
free_channel_ids_size_(kViEMaxNumberOfChannels),
|
||||||
voice_sync_interface_(NULL),
|
voice_sync_interface_(NULL),
|
||||||
voice_engine_(NULL),
|
voice_engine_(NULL),
|
||||||
module_process_thread_(NULL) {
|
module_process_thread_(NULL),
|
||||||
|
over_use_detector_options_(options) {
|
||||||
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id),
|
WEBRTC_TRACE(kTraceMemory, kTraceVideo, ViEId(engine_id),
|
||||||
"ViEChannelManager::ViEChannelManager(engine_id: %d)",
|
"ViEChannelManager::ViEChannelManager(engine_id: %d)",
|
||||||
engine_id);
|
engine_id);
|
||||||
@ -87,7 +89,8 @@ int ViEChannelManager::CreateChannel(int& channel_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create a new channel group and add this channel.
|
// 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();
|
BitrateController* bitrate_controller = group->GetBitrateController();
|
||||||
ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id,
|
ViEEncoder* vie_encoder = new ViEEncoder(engine_id_, new_channel_id,
|
||||||
number_of_cores_,
|
number_of_cores_,
|
||||||
|
@ -43,7 +43,8 @@ class ViEChannelManager: private ViEManagerBase {
|
|||||||
public:
|
public:
|
||||||
ViEChannelManager(int engine_id,
|
ViEChannelManager(int engine_id,
|
||||||
int number_of_cores,
|
int number_of_cores,
|
||||||
ViEPerformanceMonitor& vie_performance_monitor);
|
ViEPerformanceMonitor& vie_performance_monitor,
|
||||||
|
const OverUseDetectorOptions& options);
|
||||||
~ViEChannelManager();
|
~ViEChannelManager();
|
||||||
|
|
||||||
void SetModuleProcessThread(ProcessThread& module_process_thread);
|
void SetModuleProcessThread(ProcessThread& module_process_thread);
|
||||||
@ -125,6 +126,7 @@ class ViEChannelManager: private ViEManagerBase {
|
|||||||
|
|
||||||
VoiceEngine* voice_engine_;
|
VoiceEngine* voice_engine_;
|
||||||
ProcessThread* module_process_thread_;
|
ProcessThread* module_process_thread_;
|
||||||
|
const OverUseDetectorOptions& over_use_detector_options_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ViEChannelManagerScoped: private ViEManagerScopedBase {
|
class ViEChannelManagerScoped: private ViEManagerScopedBase {
|
||||||
|
@ -26,9 +26,11 @@ ViESharedData::ViESharedData()
|
|||||||
: instance_id_(++instance_counter_),
|
: instance_id_(++instance_counter_),
|
||||||
initialized_(false),
|
initialized_(false),
|
||||||
number_cores_(CpuInfo::DetectNumberOfCores()),
|
number_cores_(CpuInfo::DetectNumberOfCores()),
|
||||||
|
over_use_detector_options_(),
|
||||||
vie_performance_monitor_(ViEPerformanceMonitor(instance_id_)),
|
vie_performance_monitor_(ViEPerformanceMonitor(instance_id_)),
|
||||||
channel_manager_(*new ViEChannelManager(instance_id_, number_cores_,
|
channel_manager_(*new ViEChannelManager(instance_id_, number_cores_,
|
||||||
vie_performance_monitor_)),
|
vie_performance_monitor_,
|
||||||
|
over_use_detector_options_)),
|
||||||
input_manager_(*new ViEInputManager(instance_id_)),
|
input_manager_(*new ViEInputManager(instance_id_)),
|
||||||
render_manager_(*new ViERenderManager(instance_id_)),
|
render_manager_(*new ViERenderManager(instance_id_)),
|
||||||
module_process_thread_(ProcessThread::CreateProcessThread()),
|
module_process_thread_(ProcessThread::CreateProcessThread()),
|
||||||
|
@ -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
|
* 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
|
* that can be found in the LICENSE file in the root of the source
|
||||||
@ -50,6 +50,7 @@ class ViESharedData {
|
|||||||
bool initialized_;
|
bool initialized_;
|
||||||
const int number_cores_;
|
const int number_cores_;
|
||||||
|
|
||||||
|
OverUseDetectorOptions over_use_detector_options_;
|
||||||
ViEPerformanceMonitor vie_performance_monitor_;
|
ViEPerformanceMonitor vie_performance_monitor_;
|
||||||
ViEChannelManager& channel_manager_;
|
ViEChannelManager& channel_manager_;
|
||||||
ViEInputManager& input_manager_;
|
ViEInputManager& input_manager_;
|
||||||
|
Reference in New Issue
Block a user