JitterEstimator: rename some member variables to include unit
This makes it easier to read the code, and to visually verify that the computations make sense from a dimensional perspective. No functional changes are intended. Bug: webrtc:14151 Change-Id: Ic059f3c53618903d63a270b901ac5cec6139d2c4 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/274120 Commit-Queue: Rasmus Brandt <brandtr@webrtc.org> Reviewed-by: Philip Eliasson <philipel@webrtc.org> Cr-Commit-Position: refs/heads/main@{#38006}
This commit is contained in:
parent
e1e2c466f9
commit
8cd8d2292c
@ -60,21 +60,20 @@ JitterEstimator::~JitterEstimator() = default;
|
|||||||
|
|
||||||
// Resets the JitterEstimate.
|
// Resets the JitterEstimate.
|
||||||
void JitterEstimator::Reset() {
|
void JitterEstimator::Reset() {
|
||||||
var_noise_ = 4.0;
|
|
||||||
|
|
||||||
avg_frame_size_bytes_ = kDefaultAvgAndMaxFrameSize;
|
avg_frame_size_bytes_ = kDefaultAvgAndMaxFrameSize;
|
||||||
max_frame_size_bytes_ = kDefaultAvgAndMaxFrameSize;
|
max_frame_size_bytes_ = kDefaultAvgAndMaxFrameSize;
|
||||||
var_frame_size_ = 100;
|
var_frame_size_bytes2_ = 100;
|
||||||
last_update_time_ = absl::nullopt;
|
last_update_time_ = absl::nullopt;
|
||||||
prev_estimate_ = absl::nullopt;
|
prev_estimate_ = absl::nullopt;
|
||||||
prev_frame_size_ = absl::nullopt;
|
prev_frame_size_ = absl::nullopt;
|
||||||
avg_noise_ = 0.0;
|
avg_noise_ms_ = 0.0;
|
||||||
|
var_noise_ms2_ = 4.0;
|
||||||
alpha_count_ = 1;
|
alpha_count_ = 1;
|
||||||
filter_jitter_estimate_ = TimeDelta::Zero();
|
filter_jitter_estimate_ = TimeDelta::Zero();
|
||||||
latest_nack_ = Timestamp::Zero();
|
latest_nack_ = Timestamp::Zero();
|
||||||
nack_count_ = 0;
|
nack_count_ = 0;
|
||||||
frame_size_sum_bytes_ = 0;
|
startup_frame_size_sum_bytes_ = 0;
|
||||||
frame_size_count_ = 0;
|
startup_frame_size_count_ = 0;
|
||||||
startup_count_ = 0;
|
startup_count_ = 0;
|
||||||
rtt_filter_.Reset();
|
rtt_filter_.Reset();
|
||||||
fps_counter_.Reset();
|
fps_counter_.Reset();
|
||||||
@ -91,27 +90,28 @@ void JitterEstimator::UpdateEstimate(TimeDelta frame_delay,
|
|||||||
// Can't use DataSize since this can be negative.
|
// Can't use DataSize since this can be negative.
|
||||||
double delta_frame_bytes =
|
double delta_frame_bytes =
|
||||||
frame_size.bytes() - prev_frame_size_.value_or(DataSize::Zero()).bytes();
|
frame_size.bytes() - prev_frame_size_.value_or(DataSize::Zero()).bytes();
|
||||||
if (frame_size_count_ < kFsAccuStartupSamples) {
|
if (startup_frame_size_count_ < kFsAccuStartupSamples) {
|
||||||
frame_size_sum_bytes_ += frame_size.bytes();
|
startup_frame_size_sum_bytes_ += frame_size.bytes();
|
||||||
frame_size_count_++;
|
startup_frame_size_count_++;
|
||||||
} else if (frame_size_count_ == kFsAccuStartupSamples) {
|
} else if (startup_frame_size_count_ == kFsAccuStartupSamples) {
|
||||||
// Give the frame size filter.
|
// Give the frame size filter.
|
||||||
avg_frame_size_bytes_ =
|
avg_frame_size_bytes_ = startup_frame_size_sum_bytes_ /
|
||||||
frame_size_sum_bytes_ / static_cast<double>(frame_size_count_);
|
static_cast<double>(startup_frame_size_count_);
|
||||||
frame_size_count_++;
|
startup_frame_size_count_++;
|
||||||
}
|
}
|
||||||
|
|
||||||
double avg_frame_size_bytes =
|
double avg_frame_size_bytes =
|
||||||
kPhi * avg_frame_size_bytes_ + (1 - kPhi) * frame_size.bytes();
|
kPhi * avg_frame_size_bytes_ + (1 - kPhi) * frame_size.bytes();
|
||||||
double deviation_size_bytes = 2 * sqrt(var_frame_size_);
|
double deviation_size_bytes = 2 * sqrt(var_frame_size_bytes2_);
|
||||||
if (frame_size.bytes() < avg_frame_size_bytes_ + deviation_size_bytes) {
|
if (frame_size.bytes() < avg_frame_size_bytes_ + deviation_size_bytes) {
|
||||||
// Only update the average frame size if this sample wasn't a key frame.
|
// Only update the average frame size if this sample wasn't a key frame.
|
||||||
avg_frame_size_bytes_ = avg_frame_size_bytes;
|
avg_frame_size_bytes_ = avg_frame_size_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
double delta_bytes = frame_size.bytes() - avg_frame_size_bytes;
|
double delta_bytes = frame_size.bytes() - avg_frame_size_bytes;
|
||||||
var_frame_size_ = std::max(
|
var_frame_size_bytes2_ = std::max(
|
||||||
kPhi * var_frame_size_ + (1 - kPhi) * (delta_bytes * delta_bytes), 1.0);
|
kPhi * var_frame_size_bytes2_ + (1 - kPhi) * (delta_bytes * delta_bytes),
|
||||||
|
1.0);
|
||||||
|
|
||||||
// Update max_frame_size_bytes_ estimate.
|
// Update max_frame_size_bytes_ estimate.
|
||||||
max_frame_size_bytes_ =
|
max_frame_size_bytes_ =
|
||||||
@ -125,23 +125,24 @@ void JitterEstimator::UpdateEstimate(TimeDelta frame_delay,
|
|||||||
|
|
||||||
// Cap frame_delay based on the current time deviation noise.
|
// Cap frame_delay based on the current time deviation noise.
|
||||||
TimeDelta max_time_deviation = TimeDelta::Millis(
|
TimeDelta max_time_deviation = TimeDelta::Millis(
|
||||||
kDefaultMaxTimestampDeviationInSigmas * sqrt(var_noise_) + 0.5);
|
kDefaultMaxTimestampDeviationInSigmas * sqrt(var_noise_ms2_) + 0.5);
|
||||||
frame_delay.Clamp(-max_time_deviation, max_time_deviation);
|
frame_delay.Clamp(-max_time_deviation, max_time_deviation);
|
||||||
|
|
||||||
// Only update the Kalman filter if the sample is not considered an extreme
|
// Only update the Kalman filter if the sample is not considered an extreme
|
||||||
// outlier. Even if it is an extreme outlier from a delay point of view, if
|
// outlier. Even if it is an extreme outlier from a delay point of view, if
|
||||||
// the frame size also is large the deviation is probably due to an incorrect
|
// the frame size also is large the deviation is probably due to an incorrect
|
||||||
// line slope.
|
// line slope.
|
||||||
double deviation =
|
double deviation_ms =
|
||||||
frame_delay.ms() -
|
frame_delay.ms() -
|
||||||
kalman_filter_.GetFrameDelayVariationEstimateTotal(delta_frame_bytes);
|
kalman_filter_.GetFrameDelayVariationEstimateTotal(delta_frame_bytes);
|
||||||
|
|
||||||
if (fabs(deviation) < kNumStdDevDelayOutlier * sqrt(var_noise_) ||
|
if (fabs(deviation_ms) < kNumStdDevDelayOutlier * sqrt(var_noise_ms2_) ||
|
||||||
frame_size.bytes() > avg_frame_size_bytes_ + kNumStdDevFrameSizeOutlier *
|
frame_size.bytes() >
|
||||||
sqrt(var_frame_size_)) {
|
avg_frame_size_bytes_ +
|
||||||
|
kNumStdDevFrameSizeOutlier * sqrt(var_frame_size_bytes2_)) {
|
||||||
// Update the variance of the deviation from the line given by the Kalman
|
// Update the variance of the deviation from the line given by the Kalman
|
||||||
// filter.
|
// filter.
|
||||||
EstimateRandomJitter(deviation);
|
EstimateRandomJitter(deviation_ms);
|
||||||
// Prevent updating with frames which have been congested by a large frame,
|
// Prevent updating with frames which have been congested by a large frame,
|
||||||
// and therefore arrives almost at the same time as that frame.
|
// and therefore arrives almost at the same time as that frame.
|
||||||
// This can occur when we receive a large frame (key frame) which has been
|
// This can occur when we receive a large frame (key frame) which has been
|
||||||
@ -151,12 +152,12 @@ void JitterEstimator::UpdateEstimate(TimeDelta frame_delay,
|
|||||||
if (delta_frame_bytes > -0.25 * max_frame_size_bytes_) {
|
if (delta_frame_bytes > -0.25 * max_frame_size_bytes_) {
|
||||||
// Update the Kalman filter with the new data
|
// Update the Kalman filter with the new data
|
||||||
kalman_filter_.PredictAndUpdate(frame_delay.ms(), delta_frame_bytes,
|
kalman_filter_.PredictAndUpdate(frame_delay.ms(), delta_frame_bytes,
|
||||||
max_frame_size_bytes_, var_noise_);
|
max_frame_size_bytes_, var_noise_ms2_);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int nStdDev =
|
int nStdDev =
|
||||||
(deviation >= 0) ? kNumStdDevDelayOutlier : -kNumStdDevDelayOutlier;
|
(deviation_ms >= 0) ? kNumStdDevDelayOutlier : -kNumStdDevDelayOutlier;
|
||||||
EstimateRandomJitter(nStdDev * sqrt(var_noise_));
|
EstimateRandomJitter(nStdDev * sqrt(var_noise_ms2_));
|
||||||
}
|
}
|
||||||
// Post process the total estimated jitter
|
// Post process the total estimated jitter
|
||||||
if (startup_count_ >= kStartupDelaySamples) {
|
if (startup_count_ >= kStartupDelaySamples) {
|
||||||
@ -210,24 +211,26 @@ void JitterEstimator::EstimateRandomJitter(double d_dT) {
|
|||||||
alpha = pow(alpha, rate_scale);
|
alpha = pow(alpha, rate_scale);
|
||||||
}
|
}
|
||||||
|
|
||||||
double avgNoise = alpha * avg_noise_ + (1 - alpha) * d_dT;
|
double avg_noise_ms = alpha * avg_noise_ms_ + (1 - alpha) * d_dT;
|
||||||
double varNoise = alpha * var_noise_ +
|
double var_noise_ms2 = alpha * var_noise_ms2_ + (1 - alpha) *
|
||||||
(1 - alpha) * (d_dT - avg_noise_) * (d_dT - avg_noise_);
|
(d_dT - avg_noise_ms_) *
|
||||||
avg_noise_ = avgNoise;
|
(d_dT - avg_noise_ms_);
|
||||||
var_noise_ = varNoise;
|
avg_noise_ms_ = avg_noise_ms;
|
||||||
if (var_noise_ < 1.0) {
|
var_noise_ms2_ = var_noise_ms2;
|
||||||
|
if (var_noise_ms2_ < 1.0) {
|
||||||
// The variance should never be zero, since we might get stuck and consider
|
// The variance should never be zero, since we might get stuck and consider
|
||||||
// all samples as outliers.
|
// all samples as outliers.
|
||||||
var_noise_ = 1.0;
|
var_noise_ms2_ = 1.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double JitterEstimator::NoiseThreshold() const {
|
double JitterEstimator::NoiseThreshold() const {
|
||||||
double noiseThreshold = kNoiseStdDevs * sqrt(var_noise_) - kNoiseStdDevOffset;
|
double noise_threshold_ms =
|
||||||
if (noiseThreshold < 1.0) {
|
kNoiseStdDevs * sqrt(var_noise_ms2_) - kNoiseStdDevOffset;
|
||||||
noiseThreshold = 1.0;
|
if (noise_threshold_ms < 1.0) {
|
||||||
|
noise_threshold_ms = 1.0;
|
||||||
}
|
}
|
||||||
return noiseThreshold;
|
return noise_threshold_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the current jitter estimate from the filtered estimates.
|
// Calculates the current jitter estimate from the filtered estimates.
|
||||||
|
|||||||
@ -67,8 +67,6 @@ class JitterEstimator {
|
|||||||
static constexpr TimeDelta OPERATING_SYSTEM_JITTER = TimeDelta::Millis(10);
|
static constexpr TimeDelta OPERATING_SYSTEM_JITTER = TimeDelta::Millis(10);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
double var_noise_; // Variance of the time-deviation from the line
|
|
||||||
|
|
||||||
// Updates the random jitter estimate, i.e. the variance of the time
|
// Updates the random jitter estimate, i.e. the variance of the time
|
||||||
// deviations from the line given by the Kalman filter.
|
// deviations from the line given by the Kalman filter.
|
||||||
//
|
//
|
||||||
@ -86,6 +84,7 @@ class JitterEstimator {
|
|||||||
// Post process the calculated estimate.
|
// Post process the calculated estimate.
|
||||||
void PostProcessEstimate();
|
void PostProcessEstimate();
|
||||||
|
|
||||||
|
// Returns the estimated incoming frame rate.
|
||||||
Frequency GetFrameRate() const;
|
Frequency GetFrameRate() const;
|
||||||
|
|
||||||
// Filters the {frame_delay_delta, frame_size_delta} measurements through
|
// Filters the {frame_delay_delta, frame_size_delta} measurements through
|
||||||
@ -95,33 +94,35 @@ class JitterEstimator {
|
|||||||
// TODO(bugs.webrtc.org/14381): Update `avg_frame_size_bytes_` to DataSize
|
// TODO(bugs.webrtc.org/14381): Update `avg_frame_size_bytes_` to DataSize
|
||||||
// when api/units have sufficient precision.
|
// when api/units have sufficient precision.
|
||||||
double avg_frame_size_bytes_; // Average frame size
|
double avg_frame_size_bytes_; // Average frame size
|
||||||
double var_frame_size_; // Frame size variance. Unit is bytes^2.
|
double var_frame_size_bytes2_; // Frame size variance. Unit is bytes^2.
|
||||||
// Largest frame size received (descending with a factor kPsi)
|
// Largest frame size received (descending with a factor kPsi)
|
||||||
// TODO(bugs.webrtc.org/14381): Update `max_frame_size_bytes_` to DataSize
|
// TODO(bugs.webrtc.org/14381): Update `max_frame_size_bytes_` to DataSize
|
||||||
// when api/units have sufficient precision.
|
// when api/units have sufficient precision.
|
||||||
double max_frame_size_bytes_;
|
double max_frame_size_bytes_;
|
||||||
// TODO(bugs.webrtc.org/14381): Update `frame_size_sum_bytes_` to DataSize
|
// TODO(bugs.webrtc.org/14381): Update `startup_frame_size_sum_bytes_` to
|
||||||
// when api/units have sufficient precision.
|
// DataSize when api/units have sufficient precision.
|
||||||
double frame_size_sum_bytes_;
|
double startup_frame_size_sum_bytes_;
|
||||||
uint32_t frame_size_count_;
|
size_t startup_frame_size_count_;
|
||||||
|
|
||||||
absl::optional<Timestamp> last_update_time_;
|
absl::optional<Timestamp> last_update_time_;
|
||||||
// The previously returned jitter estimate
|
// The previously returned jitter estimate
|
||||||
absl::optional<TimeDelta> prev_estimate_;
|
absl::optional<TimeDelta> prev_estimate_;
|
||||||
// Frame size of the previous frame
|
// Frame size of the previous frame
|
||||||
absl::optional<DataSize> prev_frame_size_;
|
absl::optional<DataSize> prev_frame_size_;
|
||||||
// Average of the random jitter
|
// Average of the random jitter. Unit is milliseconds.
|
||||||
double avg_noise_;
|
double avg_noise_ms_;
|
||||||
uint32_t alpha_count_;
|
// Variance of the time-deviation from the line. Unit is milliseconds^2.
|
||||||
|
double var_noise_ms2_;
|
||||||
|
size_t alpha_count_;
|
||||||
// The filtered sum of jitter estimates
|
// The filtered sum of jitter estimates
|
||||||
TimeDelta filter_jitter_estimate_ = TimeDelta::Zero();
|
TimeDelta filter_jitter_estimate_ = TimeDelta::Zero();
|
||||||
|
|
||||||
uint32_t startup_count_;
|
size_t startup_count_;
|
||||||
// Time when the latest nack was seen
|
// Time when the latest nack was seen
|
||||||
Timestamp latest_nack_ = Timestamp::Zero();
|
Timestamp latest_nack_ = Timestamp::Zero();
|
||||||
// Keeps track of the number of nacks received, but never goes above
|
// Keeps track of the number of nacks received, but never goes above
|
||||||
// kNackLimit.
|
// kNackLimit.
|
||||||
uint32_t nack_count_;
|
size_t nack_count_;
|
||||||
RttFilter rtt_filter_;
|
RttFilter rtt_filter_;
|
||||||
|
|
||||||
// Tracks frame rates in microseconds.
|
// Tracks frame rates in microseconds.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user