Use TimeDelta and Timestamp in VCMJitterEstimator
* Uses DataSize to represent incoming and outgoing bytes.
* Puts units into doubles as they enter the Kalman filter
* Moved to its own GN target.
Change-Id: I1e7d5486a00a7158d418f553a6c77f9dd56bf3c2
Bug: webrtc:13756
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/253121
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Commit-Queue: Evan Shrubsole <eshr@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36143}
diff --git a/modules/video_coding/BUILD.gn b/modules/video_coding/BUILD.gn
index 8307011..a1b2d07 100644
--- a/modules/video_coding/BUILD.gn
+++ b/modules/video_coding/BUILD.gn
@@ -214,6 +214,26 @@
]
}
+rtc_library("jitter_estimator") {
+ sources = [
+ "jitter_estimator.cc",
+ "jitter_estimator.h",
+ ]
+ deps = [
+ ":rtt_filter",
+ "../../api/units:data_size",
+ "../../api/units:frequency",
+ "../../api/units:time_delta",
+ "../../api/units:timestamp",
+ "../../rtc_base",
+ "../../rtc_base:safe_conversions",
+ "../../rtc_base/experiments:jitter_upper_bound_experiment",
+ "../../system_wrappers",
+ "../../system_wrappers:field_trial",
+ ]
+ absl_deps = [ "//third_party/abseil-cpp/absl/types:optional" ]
+}
+
rtc_library("video_coding") {
visibility = [ "*" ]
sources = [
@@ -236,8 +256,6 @@
"inter_frame_delay.cc",
"inter_frame_delay.h",
"internal_defines.h",
- "jitter_estimator.cc",
- "jitter_estimator.h",
"loss_notification_controller.cc",
"loss_notification_controller.h",
"media_opt_util.cc",
@@ -268,6 +286,7 @@
":encoded_frame",
":frame_buffer",
":frame_helpers",
+ ":jitter_estimator",
":packet_buffer",
":rtt_filter",
":timing",
@@ -285,6 +304,8 @@
"../../api:sequence_checker",
"../../api/task_queue",
"../../api/units:data_rate",
+ "../../api/units:data_size",
+ "../../api/units:frequency",
"../../api/units:time_delta",
"../../api/units:timestamp",
"../../api/video:builtin_video_bitrate_allocator_factory",
@@ -381,6 +402,7 @@
deps = [
":codec_globals_headers",
":encoded_frame",
+ ":jitter_estimator",
":timing",
":video_codec_interface",
":video_coding",
@@ -1129,6 +1151,7 @@
":frame_buffer",
":frame_dependencies_calculator",
":h264_packet_buffer",
+ ":jitter_estimator",
":nack_requester",
":packet_buffer",
":rtt_filter",
@@ -1158,6 +1181,7 @@
"../../api:videocodec_test_fixture_api",
"../../api/task_queue:default_task_queue_factory",
"../../api/test/video:function_video_factory",
+ "../../api/units:data_size",
"../../api/units:frequency",
"../../api/units:time_delta",
"../../api/units:timestamp",
diff --git a/modules/video_coding/frame_buffer2.cc b/modules/video_coding/frame_buffer2.cc
index b17cc94..d7944db 100644
--- a/modules/video_coding/frame_buffer2.cc
+++ b/modules/video_coding/frame_buffer2.cc
@@ -19,6 +19,8 @@
#include <vector>
#include "absl/container/inlined_vector.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
#include "api/video/encoded_image.h"
#include "api/video/video_timing.h"
#include "modules/video_coding/frame_helpers.h"
@@ -250,7 +252,7 @@
RTC_DCHECK(!frames_to_decode_.empty());
bool superframe_delayed_by_retransmission = false;
- size_t superframe_size = 0;
+ DataSize superframe_size = DataSize::Zero();
const EncodedFrame& first_frame = *frames_to_decode_[0]->second.frame;
absl::optional<Timestamp> render_time = first_frame.RenderTimestamp();
int64_t receive_time_ms = first_frame.ReceivedTime();
@@ -270,7 +272,7 @@
superframe_delayed_by_retransmission |= frame->delayed_by_retransmission();
receive_time_ms = std::max(receive_time_ms, frame->ReceivedTime());
- superframe_size += frame->size();
+ superframe_size += DataSize::Bytes(frame->size());
PropagateDecodability(frame_it->second);
decoded_frames_history_.InsertDecoded(frame_it->first, frame->Timestamp());
@@ -297,17 +299,19 @@
if (inter_frame_delay_.CalculateDelay(first_frame.Timestamp(), &frame_delay,
receive_time_ms)) {
- jitter_estimator_.UpdateEstimate(frame_delay, superframe_size);
+ jitter_estimator_.UpdateEstimate(TimeDelta::Millis(frame_delay),
+ superframe_size);
}
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
- absl::optional<float> rtt_mult_add_cap_ms = absl::nullopt;
+ absl::optional<TimeDelta> rtt_mult_add_cap_ms = absl::nullopt;
if (rtt_mult_settings_.has_value()) {
rtt_mult = rtt_mult_settings_->rtt_mult_setting;
- rtt_mult_add_cap_ms = rtt_mult_settings_->rtt_mult_add_cap_ms;
+ rtt_mult_add_cap_ms =
+ TimeDelta::Millis(rtt_mult_settings_->rtt_mult_add_cap_ms);
}
- timing_->SetJitterDelay(TimeDelta::Millis(
- jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms)));
+ timing_->SetJitterDelay(
+ jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms));
timing_->UpdateCurrentDelay(*render_time, now);
} else {
if (RttMultExperiment::RttMultEnabled())
@@ -352,7 +356,7 @@
void FrameBuffer::UpdateRtt(int64_t rtt_ms) {
MutexLock lock(&mutex_);
- jitter_estimator_.UpdateRtt(rtt_ms);
+ jitter_estimator_.UpdateRtt(TimeDelta::Millis(rtt_ms));
}
bool FrameBuffer::ValidReferences(const EncodedFrame& frame) const {
diff --git a/modules/video_coding/jitter_buffer.cc b/modules/video_coding/jitter_buffer.cc
index 4c6015e..a49ee69 100644
--- a/modules/video_coding/jitter_buffer.cc
+++ b/modules/video_coding/jitter_buffer.cc
@@ -572,7 +572,7 @@
uint32_t VCMJitterBuffer::EstimatedJitterMs() {
MutexLock lock(&mutex_);
const double rtt_mult = 1.0f;
- return jitter_estimate_.GetJitterEstimate(rtt_mult, absl::nullopt);
+ return jitter_estimate_.GetJitterEstimate(rtt_mult, absl::nullopt).ms();
}
void VCMJitterBuffer::SetNackSettings(size_t max_nack_list_size,
@@ -879,7 +879,9 @@
// Filter out frames which have been reordered in time by the network
if (not_reordered) {
// Update the jitter estimate with the new samples
- jitter_estimate_.UpdateEstimate(frame_delay, frame_size, incomplete_frame);
+ jitter_estimate_.UpdateEstimate(TimeDelta::Millis(frame_delay),
+ DataSize::Bytes(frame_size),
+ incomplete_frame);
}
}
diff --git a/modules/video_coding/jitter_estimator.cc b/modules/video_coding/jitter_estimator.cc
index cf57232..5ecd545 100644
--- a/modules/video_coding/jitter_estimator.cc
+++ b/modules/video_coding/jitter_estimator.cc
@@ -17,7 +17,10 @@
#include <cstdint>
#include "absl/types/optional.h"
-#include "modules/video_coding/internal_defines.h"
+#include "api/units/data_size.h"
+#include "api/units/frequency.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "modules/video_coding/rtt_filter.h"
#include "rtc_base/experiments/jitter_upper_bound_experiment.h"
#include "rtc_base/numerics/safe_conversions.h"
@@ -28,24 +31,26 @@
namespace {
static constexpr uint32_t kStartupDelaySamples = 30;
static constexpr int64_t kFsAccuStartupSamples = 5;
-static constexpr double kMaxFramerateEstimate = 200.0;
-static constexpr int64_t kNackCountTimeoutMs = 60000;
+static constexpr Frequency kMaxFramerateEstimate = Frequency::Hertz(200);
+static constexpr TimeDelta kNackCountTimeout = TimeDelta::Seconds(60);
static constexpr double kDefaultMaxTimestampDeviationInSigmas = 3.5;
+
+constexpr double kPhi = 0.97;
+constexpr double kPsi = 0.9999;
+constexpr uint32_t kAlphaCountMax = 400;
+constexpr double kThetaLow = 0.000001;
+constexpr uint32_t kNackLimit = 3;
+constexpr int32_t kNumStdDevDelayOutlier = 15;
+constexpr int32_t kNumStdDevFrameSizeOutlier = 3;
+// ~Less than 1% chance (look up in normal distribution table)...
+constexpr double kNoiseStdDevs = 2.33;
+// ...of getting 30 ms freezes
+constexpr double kNoiseStdDevOffset = 30.0;
+
} // namespace
VCMJitterEstimator::VCMJitterEstimator(Clock* clock)
- : _phi(0.97),
- _psi(0.9999),
- _alphaCountMax(400),
- _thetaLow(0.000001),
- _nackLimit(3),
- _numStdDevDelayOutlier(15),
- _numStdDevFrameSizeOutlier(3),
- _noiseStdDevs(2.33), // ~Less than 1% chance
- // (look up in normal distribution table)...
- _noiseStdDevOffset(30.0), // ...of getting 30 ms freezes
- _rttFilter(),
- fps_counter_(30), // TODO(sprang): Use an estimator with limit based on
+ : fps_counter_(30), // TODO(sprang): Use an estimator with limit based on
// time, rather than number of samples.
time_deviation_upper_bound_(
JitterUpperBoundExperiment::GetUpperBoundSigmas().value_or(
@@ -56,133 +61,133 @@
Reset();
}
-VCMJitterEstimator::~VCMJitterEstimator() {}
+VCMJitterEstimator::~VCMJitterEstimator() = default;
// Resets the JitterEstimate.
void VCMJitterEstimator::Reset() {
- _theta[0] = 1 / (512e3 / 8);
- _theta[1] = 0;
- _varNoise = 4.0;
+ theta_[0] = 1 / (512e3 / 8);
+ theta_[1] = 0;
+ var_noise_ = 4.0;
- _thetaCov[0][0] = 1e-4;
- _thetaCov[1][1] = 1e2;
- _thetaCov[0][1] = _thetaCov[1][0] = 0;
- _Qcov[0][0] = 2.5e-10;
- _Qcov[1][1] = 1e-10;
- _Qcov[0][1] = _Qcov[1][0] = 0;
- _avgFrameSize = 500;
- _maxFrameSize = 500;
- _varFrameSize = 100;
- _lastUpdateT = -1;
- _prevEstimate = -1.0;
- _prevFrameSize = 0;
- _avgNoise = 0.0;
- _alphaCount = 1;
- _filterJitterEstimate = 0.0;
- _latestNackTimestamp = 0;
- _nackCount = 0;
- _latestNackTimestamp = 0;
- _fsSum = 0;
- _fsCount = 0;
- _startupCount = 0;
- _rttFilter.Reset();
+ theta_cov_[0][0] = 1e-4;
+ theta_cov_[1][1] = 1e2;
+ theta_cov_[0][1] = theta_cov_[1][0] = 0;
+ q_cov_[0][0] = 2.5e-10;
+ q_cov_[1][1] = 1e-10;
+ q_cov_[0][1] = q_cov_[1][0] = 0;
+ avg_frame_size_ = kDefaultAvgAndMaxFrameSize;
+ max_frame_size_ = kDefaultAvgAndMaxFrameSize;
+ var_frame_size_ = 100;
+ last_update_time_ = absl::nullopt;
+ prev_estimate_ = absl::nullopt;
+ prev_frame_size_ = absl::nullopt;
+ avg_noise_ = 0.0;
+ alpha_count_ = 1;
+ filter_jitter_estimate_ = TimeDelta::Zero();
+ latest_nack_ = Timestamp::Zero();
+ nack_count_ = 0;
+ frame_size_sum_ = DataSize::Zero();
+ frame_size_count_ = 0;
+ startup_count_ = 0;
+ rtt_filter_.Reset();
fps_counter_.Reset();
}
// Updates the estimates with the new measurements.
-void VCMJitterEstimator::UpdateEstimate(int64_t frameDelayMS,
- uint32_t frameSizeBytes,
- bool incompleteFrame /* = false */) {
- if (frameSizeBytes == 0) {
+void VCMJitterEstimator::UpdateEstimate(TimeDelta frame_delay,
+ DataSize frame_size,
+ bool incomplete_frame /* = false */) {
+ if (frame_size.IsZero()) {
return;
}
- int deltaFS = frameSizeBytes - _prevFrameSize;
- if (_fsCount < kFsAccuStartupSamples) {
- _fsSum += frameSizeBytes;
- _fsCount++;
- } else if (_fsCount == kFsAccuStartupSamples) {
+ // Can't use DataSize since this can be negative.
+ double delta_frame_bytes =
+ frame_size.bytes() - prev_frame_size_.value_or(DataSize::Zero()).bytes();
+ if (frame_size_count_ < kFsAccuStartupSamples) {
+ frame_size_sum_ += frame_size;
+ frame_size_count_++;
+ } else if (frame_size_count_ == kFsAccuStartupSamples) {
// Give the frame size filter.
- _avgFrameSize = static_cast<double>(_fsSum) / static_cast<double>(_fsCount);
- _fsCount++;
+ avg_frame_size_ = frame_size_sum_ / static_cast<double>(frame_size_count_);
+ frame_size_count_++;
}
- if (!incompleteFrame || frameSizeBytes > _avgFrameSize) {
- double avgFrameSize = _phi * _avgFrameSize + (1 - _phi) * frameSizeBytes;
- if (frameSizeBytes < _avgFrameSize + 2 * sqrt(_varFrameSize)) {
+ if (!incomplete_frame || frame_size > avg_frame_size_) {
+ DataSize avg_frame_size = kPhi * avg_frame_size_ + (1 - kPhi) * frame_size;
+ DataSize deviation_size = DataSize::Bytes(2 * sqrt(var_frame_size_));
+ if (frame_size < avg_frame_size_ + deviation_size) {
// Only update the average frame size if this sample wasn't a key frame.
- _avgFrameSize = avgFrameSize;
+ avg_frame_size_ = avg_frame_size;
}
// Update the variance anyway since we want to capture cases where we only
// get key frames.
- _varFrameSize = VCM_MAX(
- _phi * _varFrameSize + (1 - _phi) * (frameSizeBytes - avgFrameSize) *
- (frameSizeBytes - avgFrameSize),
- 1.0);
+ double delta_bytes = frame_size.bytes() - avg_frame_size.bytes();
+ var_frame_size_ = std::max(
+ kPhi * var_frame_size_ + (1 - kPhi) * (delta_bytes * delta_bytes), 1.0);
}
- // Update max frameSize estimate.
- _maxFrameSize =
- VCM_MAX(_psi * _maxFrameSize, static_cast<double>(frameSizeBytes));
+ // Update max_frame_size_ estimate.
+ max_frame_size_ = std::max(kPsi * max_frame_size_, frame_size);
- if (_prevFrameSize == 0) {
- _prevFrameSize = frameSizeBytes;
+ if (!prev_frame_size_) {
+ prev_frame_size_ = frame_size;
return;
}
- _prevFrameSize = frameSizeBytes;
+ prev_frame_size_ = frame_size;
- // Cap frameDelayMS based on the current time deviation noise.
- int64_t max_time_deviation_ms =
- static_cast<int64_t>(time_deviation_upper_bound_ * sqrt(_varNoise) + 0.5);
- frameDelayMS = std::max(std::min(frameDelayMS, max_time_deviation_ms),
- -max_time_deviation_ms);
+ // Cap frame_delay based on the current time deviation noise.
+ TimeDelta max_time_deviation =
+ TimeDelta::Millis(time_deviation_upper_bound_ * sqrt(var_noise_) + 0.5);
+ frame_delay.Clamp(-max_time_deviation, max_time_deviation);
// 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
// the frame size also is large the deviation is probably due to an incorrect
// line slope.
- double deviation = DeviationFromExpectedDelay(frameDelayMS, deltaFS);
+ double deviation = DeviationFromExpectedDelay(frame_delay, delta_frame_bytes);
- if (fabs(deviation) < _numStdDevDelayOutlier * sqrt(_varNoise) ||
- frameSizeBytes >
- _avgFrameSize + _numStdDevFrameSizeOutlier * sqrt(_varFrameSize)) {
+ if (fabs(deviation) < kNumStdDevDelayOutlier * sqrt(var_noise_) ||
+ frame_size.bytes() >
+ avg_frame_size_.bytes() +
+ kNumStdDevFrameSizeOutlier * sqrt(var_frame_size_)) {
// Update the variance of the deviation from the line given by the Kalman
// filter.
- EstimateRandomJitter(deviation, incompleteFrame);
+ EstimateRandomJitter(deviation, incomplete_frame);
// Prevent updating with frames which have been congested by a large 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
// delayed. The next frame is of normal size (delta frame), and thus deltaFS
// will be << 0. This removes all frame samples which arrives after a key
// frame.
- if ((!incompleteFrame || deviation >= 0.0) &&
- static_cast<double>(deltaFS) > -0.25 * _maxFrameSize) {
+ if ((!incomplete_frame || deviation >= 0) &&
+ delta_frame_bytes > -0.25 * max_frame_size_.bytes()) {
// Update the Kalman filter with the new data
- KalmanEstimateChannel(frameDelayMS, deltaFS);
+ KalmanEstimateChannel(frame_delay, delta_frame_bytes);
}
} else {
int nStdDev =
- (deviation >= 0) ? _numStdDevDelayOutlier : -_numStdDevDelayOutlier;
- EstimateRandomJitter(nStdDev * sqrt(_varNoise), incompleteFrame);
+ (deviation >= 0) ? kNumStdDevDelayOutlier : -kNumStdDevDelayOutlier;
+ EstimateRandomJitter(nStdDev * sqrt(var_noise_), incomplete_frame);
}
// Post process the total estimated jitter
- if (_startupCount >= kStartupDelaySamples) {
+ if (startup_count_ >= kStartupDelaySamples) {
PostProcessEstimate();
} else {
- _startupCount++;
+ startup_count_++;
}
}
// Updates the nack/packet ratio.
void VCMJitterEstimator::FrameNacked() {
- if (_nackCount < _nackLimit) {
- _nackCount++;
+ if (nack_count_ < kNackLimit) {
+ nack_count_++;
}
- _latestNackTimestamp = clock_->TimeInMicroseconds();
+ latest_nack_ = clock_->CurrentTime();
}
// Updates Kalman estimate of the channel.
// The caller is expected to sanity check the inputs.
-void VCMJitterEstimator::KalmanEstimateChannel(int64_t frameDelayMS,
- int32_t deltaFSBytes) {
+void VCMJitterEstimator::KalmanEstimateChannel(TimeDelta frame_delay,
+ double delta_frame_size_bytes) {
double Mh[2];
double hMh_sigma;
double kalmanGain[2];
@@ -193,31 +198,31 @@
// Prediction
// M = M + Q
- _thetaCov[0][0] += _Qcov[0][0];
- _thetaCov[0][1] += _Qcov[0][1];
- _thetaCov[1][0] += _Qcov[1][0];
- _thetaCov[1][1] += _Qcov[1][1];
+ theta_cov_[0][0] += q_cov_[0][0];
+ theta_cov_[0][1] += q_cov_[0][1];
+ theta_cov_[1][0] += q_cov_[1][0];
+ theta_cov_[1][1] += q_cov_[1][1];
// Kalman gain
// K = M*h'/(sigma2n + h*M*h') = M*h'/(1 + h*M*h')
// h = [dFS 1]
// Mh = M*h'
// hMh_sigma = h*M*h' + R
- Mh[0] = _thetaCov[0][0] * deltaFSBytes + _thetaCov[0][1];
- Mh[1] = _thetaCov[1][0] * deltaFSBytes + _thetaCov[1][1];
+ Mh[0] = theta_cov_[0][0] * delta_frame_size_bytes + theta_cov_[0][1];
+ Mh[1] = theta_cov_[1][0] * delta_frame_size_bytes + theta_cov_[1][1];
// sigma weights measurements with a small deltaFS as noisy and
// measurements with large deltaFS as good
- if (_maxFrameSize < 1.0) {
+ if (max_frame_size_ < DataSize::Bytes(1)) {
return;
}
- double sigma = (300.0 * exp(-fabs(static_cast<double>(deltaFSBytes)) /
- (1e0 * _maxFrameSize)) +
+ double sigma = (300.0 * exp(-fabs(delta_frame_size_bytes) /
+ (1e0 * max_frame_size_.bytes())) +
1) *
- sqrt(_varNoise);
+ sqrt(var_noise_);
if (sigma < 1.0) {
sigma = 1.0;
}
- hMh_sigma = deltaFSBytes * Mh[0] + Mh[1] + sigma;
+ hMh_sigma = delta_frame_size_bytes * Mh[0] + Mh[1] + sigma;
if ((hMh_sigma < 1e-9 && hMh_sigma >= 0) ||
(hMh_sigma > -1e-9 && hMh_sigma <= 0)) {
RTC_DCHECK_NOTREACHED();
@@ -228,94 +233,96 @@
// Correction
// theta = theta + K*(dT - h*theta)
- measureRes = frameDelayMS - (deltaFSBytes * _theta[0] + _theta[1]);
- _theta[0] += kalmanGain[0] * measureRes;
- _theta[1] += kalmanGain[1] * measureRes;
+ measureRes =
+ frame_delay.ms() - (delta_frame_size_bytes * theta_[0] + theta_[1]);
+ theta_[0] += kalmanGain[0] * measureRes;
+ theta_[1] += kalmanGain[1] * measureRes;
- if (_theta[0] < _thetaLow) {
- _theta[0] = _thetaLow;
+ if (theta_[0] < kThetaLow) {
+ theta_[0] = kThetaLow;
}
// M = (I - K*h)*M
- t00 = _thetaCov[0][0];
- t01 = _thetaCov[0][1];
- _thetaCov[0][0] = (1 - kalmanGain[0] * deltaFSBytes) * t00 -
- kalmanGain[0] * _thetaCov[1][0];
- _thetaCov[0][1] = (1 - kalmanGain[0] * deltaFSBytes) * t01 -
- kalmanGain[0] * _thetaCov[1][1];
- _thetaCov[1][0] = _thetaCov[1][0] * (1 - kalmanGain[1]) -
- kalmanGain[1] * deltaFSBytes * t00;
- _thetaCov[1][1] = _thetaCov[1][1] * (1 - kalmanGain[1]) -
- kalmanGain[1] * deltaFSBytes * t01;
+ t00 = theta_cov_[0][0];
+ t01 = theta_cov_[0][1];
+ theta_cov_[0][0] = (1 - kalmanGain[0] * delta_frame_size_bytes) * t00 -
+ kalmanGain[0] * theta_cov_[1][0];
+ theta_cov_[0][1] = (1 - kalmanGain[0] * delta_frame_size_bytes) * t01 -
+ kalmanGain[0] * theta_cov_[1][1];
+ theta_cov_[1][0] = theta_cov_[1][0] * (1 - kalmanGain[1]) -
+ kalmanGain[1] * delta_frame_size_bytes * t00;
+ theta_cov_[1][1] = theta_cov_[1][1] * (1 - kalmanGain[1]) -
+ kalmanGain[1] * delta_frame_size_bytes * t01;
// Covariance matrix, must be positive semi-definite.
- RTC_DCHECK(_thetaCov[0][0] + _thetaCov[1][1] >= 0 &&
- _thetaCov[0][0] * _thetaCov[1][1] -
- _thetaCov[0][1] * _thetaCov[1][0] >=
+ RTC_DCHECK(theta_cov_[0][0] + theta_cov_[1][1] >= 0 &&
+ theta_cov_[0][0] * theta_cov_[1][1] -
+ theta_cov_[0][1] * theta_cov_[1][0] >=
0 &&
- _thetaCov[0][0] >= 0);
+ theta_cov_[0][0] >= 0);
}
// Calculate difference in delay between a sample and the expected delay
// estimated by the Kalman filter
double VCMJitterEstimator::DeviationFromExpectedDelay(
- int64_t frameDelayMS,
- int32_t deltaFSBytes) const {
- return frameDelayMS - (_theta[0] * deltaFSBytes + _theta[1]);
+ TimeDelta frame_delay,
+ double delta_frame_size_bytes) const {
+ return frame_delay.ms() - (theta_[0] * delta_frame_size_bytes + theta_[1]);
}
// Estimates the random jitter by calculating the variance of the sample
// distance from the line given by theta.
void VCMJitterEstimator::EstimateRandomJitter(double d_dT,
- bool incompleteFrame) {
- uint64_t now = clock_->TimeInMicroseconds();
- if (_lastUpdateT != -1) {
- fps_counter_.AddSample(now - _lastUpdateT);
+ bool incomplete_frame) {
+ Timestamp now = clock_->CurrentTime();
+ if (last_update_time_.has_value()) {
+ fps_counter_.AddSample((now - *last_update_time_).us());
}
- _lastUpdateT = now;
+ last_update_time_ = now;
- if (_alphaCount == 0) {
+ if (alpha_count_ == 0) {
RTC_DCHECK_NOTREACHED();
return;
}
double alpha =
- static_cast<double>(_alphaCount - 1) / static_cast<double>(_alphaCount);
- _alphaCount++;
- if (_alphaCount > _alphaCountMax)
- _alphaCount = _alphaCountMax;
+ static_cast<double>(alpha_count_ - 1) / static_cast<double>(alpha_count_);
+ alpha_count_++;
+ if (alpha_count_ > kAlphaCountMax)
+ alpha_count_ = kAlphaCountMax;
// In order to avoid a low frame rate stream to react slower to changes,
// scale the alpha weight relative a 30 fps stream.
- double fps = GetFrameRate();
- if (fps > 0.0) {
- double rate_scale = 30.0 / fps;
+ Frequency fps = GetFrameRate();
+ if (fps > Frequency::Zero()) {
+ constexpr Frequency k30Fps = Frequency::Hertz(30);
+ double rate_scale = k30Fps / fps;
// At startup, there can be a lot of noise in the fps estimate.
// Interpolate rate_scale linearly, from 1.0 at sample #1, to 30.0 / fps
// at sample #kStartupDelaySamples.
- if (_alphaCount < kStartupDelaySamples) {
+ if (alpha_count_ < kStartupDelaySamples) {
rate_scale =
- (_alphaCount * rate_scale + (kStartupDelaySamples - _alphaCount)) /
+ (alpha_count_ * rate_scale + (kStartupDelaySamples - alpha_count_)) /
kStartupDelaySamples;
}
alpha = pow(alpha, rate_scale);
}
- double avgNoise = alpha * _avgNoise + (1 - alpha) * d_dT;
- double varNoise =
- alpha * _varNoise + (1 - alpha) * (d_dT - _avgNoise) * (d_dT - _avgNoise);
- if (!incompleteFrame || varNoise > _varNoise) {
- _avgNoise = avgNoise;
- _varNoise = varNoise;
+ double avgNoise = alpha * avg_noise_ + (1 - alpha) * d_dT;
+ double varNoise = alpha * var_noise_ +
+ (1 - alpha) * (d_dT - avg_noise_) * (d_dT - avg_noise_);
+ if (!incomplete_frame || varNoise > var_noise_) {
+ avg_noise_ = avgNoise;
+ var_noise_ = varNoise;
}
- if (_varNoise < 1.0) {
+ if (var_noise_ < 1.0) {
// The variance should never be zero, since we might get stuck and consider
// all samples as outliers.
- _varNoise = 1.0;
+ var_noise_ = 1.0;
}
}
double VCMJitterEstimator::NoiseThreshold() const {
- double noiseThreshold = _noiseStdDevs * sqrt(_varNoise) - _noiseStdDevOffset;
+ double noiseThreshold = kNoiseStdDevs * sqrt(var_noise_) - kNoiseStdDevOffset;
if (noiseThreshold < 1.0) {
noiseThreshold = 1.0;
}
@@ -323,88 +330,91 @@
}
// Calculates the current jitter estimate from the filtered estimates.
-double VCMJitterEstimator::CalculateEstimate() {
- double ret = _theta[0] * (_maxFrameSize - _avgFrameSize) + NoiseThreshold();
+TimeDelta VCMJitterEstimator::CalculateEstimate() {
+ double retMs =
+ theta_[0] * (max_frame_size_.bytes() - avg_frame_size_.bytes()) +
+ NoiseThreshold();
+ TimeDelta ret = TimeDelta::Millis(retMs);
+
+ constexpr TimeDelta kMinPrevEstimate = TimeDelta::Micros(10);
+ constexpr TimeDelta kMaxEstimate = TimeDelta::Seconds(10);
// A very low estimate (or negative) is neglected.
- if (ret < 1.0) {
- if (_prevEstimate <= 0.01) {
- ret = 1.0;
+ if (ret < TimeDelta::Millis(1)) {
+ if (!prev_estimate_ || prev_estimate_ <= kMinPrevEstimate) {
+ ret = TimeDelta::Millis(1);
} else {
- ret = _prevEstimate;
+ ret = *prev_estimate_;
}
}
- if (ret > 10000.0) { // Sanity
- ret = 10000.0;
+ if (ret > kMaxEstimate) { // Sanity
+ ret = kMaxEstimate;
}
- _prevEstimate = ret;
+ prev_estimate_ = ret;
return ret;
}
void VCMJitterEstimator::PostProcessEstimate() {
- _filterJitterEstimate = CalculateEstimate();
+ filter_jitter_estimate_ = CalculateEstimate();
}
-void VCMJitterEstimator::UpdateRtt(int64_t rttMs) {
- _rttFilter.Update(TimeDelta::Millis(rttMs));
+void VCMJitterEstimator::UpdateRtt(TimeDelta rtt) {
+ rtt_filter_.Update(rtt);
}
// Returns the current filtered estimate if available,
// otherwise tries to calculate an estimate.
-int VCMJitterEstimator::GetJitterEstimate(
- double rttMultiplier,
- absl::optional<double> rttMultAddCapMs) {
- double jitterMS = CalculateEstimate() + OPERATING_SYSTEM_JITTER;
- uint64_t now = clock_->TimeInMicroseconds();
+TimeDelta VCMJitterEstimator::GetJitterEstimate(
+ double rtt_multiplier,
+ absl::optional<TimeDelta> rtt_mult_add_cap) {
+ TimeDelta jitter = CalculateEstimate() + OPERATING_SYSTEM_JITTER;
+ Timestamp now = clock_->CurrentTime();
- if (now - _latestNackTimestamp > kNackCountTimeoutMs * 1000)
- _nackCount = 0;
+ if (now - latest_nack_ > kNackCountTimeout)
+ nack_count_ = 0;
- if (_filterJitterEstimate > jitterMS)
- jitterMS = _filterJitterEstimate;
- if (_nackCount >= _nackLimit) {
- if (rttMultAddCapMs.has_value()) {
- jitterMS += std::min(_rttFilter.Rtt().ms() * rttMultiplier,
- rttMultAddCapMs.value());
+ if (filter_jitter_estimate_ > jitter)
+ jitter = filter_jitter_estimate_;
+ if (nack_count_ >= kNackLimit) {
+ if (rtt_mult_add_cap.has_value()) {
+ jitter += std::min(rtt_filter_.Rtt() * rtt_multiplier,
+ rtt_mult_add_cap.value());
} else {
- jitterMS += _rttFilter.Rtt().ms() * rttMultiplier;
+ jitter += rtt_filter_.Rtt() * rtt_multiplier;
}
}
if (enable_reduced_delay_) {
- static const double kJitterScaleLowThreshold = 5.0;
- static const double kJitterScaleHighThreshold = 10.0;
- double fps = GetFrameRate();
+ static const Frequency kJitterScaleLowThreshold = Frequency::Hertz(5);
+ static const Frequency kJitterScaleHighThreshold = Frequency::Hertz(10);
+ Frequency fps = GetFrameRate();
// Ignore jitter for very low fps streams.
if (fps < kJitterScaleLowThreshold) {
- if (fps == 0.0) {
- return rtc::checked_cast<int>(std::max(0.0, jitterMS) + 0.5);
+ if (fps.IsZero()) {
+ return std::max(TimeDelta::Zero(), jitter);
}
- return 0;
+ return TimeDelta::Zero();
}
// Semi-low frame rate; scale by factor linearly interpolated from 0.0 at
// kJitterScaleLowThreshold to 1.0 at kJitterScaleHighThreshold.
if (fps < kJitterScaleHighThreshold) {
- jitterMS =
- (1.0 / (kJitterScaleHighThreshold - kJitterScaleLowThreshold)) *
- (fps - kJitterScaleLowThreshold) * jitterMS;
+ jitter = (1.0 / (kJitterScaleHighThreshold - kJitterScaleLowThreshold)) *
+ (fps - kJitterScaleLowThreshold) * jitter;
}
}
- return rtc::checked_cast<int>(std::max(0.0, jitterMS) + 0.5);
+ return std::max(TimeDelta::Zero(), jitter);
}
-double VCMJitterEstimator::GetFrameRate() const {
- if (fps_counter_.ComputeMean() <= 0.0)
- return 0;
+Frequency VCMJitterEstimator::GetFrameRate() const {
+ TimeDelta mean_frame_period = TimeDelta::Micros(fps_counter_.ComputeMean());
+ if (mean_frame_period <= TimeDelta::Zero())
+ return Frequency::Zero();
- double fps = 1000000.0 / fps_counter_.ComputeMean();
+ Frequency fps = 1 / mean_frame_period;
// Sanity check.
- RTC_DCHECK_GE(fps, 0.0);
- if (fps > kMaxFramerateEstimate) {
- fps = kMaxFramerateEstimate;
- }
- return fps;
+ RTC_DCHECK_GE(fps, Frequency::Zero());
+ return std::min(fps, kMaxFramerateEstimate);
}
} // namespace webrtc
diff --git a/modules/video_coding/jitter_estimator.h b/modules/video_coding/jitter_estimator.h
index ee8f264..026fb7e 100644
--- a/modules/video_coding/jitter_estimator.h
+++ b/modules/video_coding/jitter_estimator.h
@@ -11,6 +11,11 @@
#ifndef MODULES_VIDEO_CODING_JITTER_ESTIMATOR_H_
#define MODULES_VIDEO_CODING_JITTER_ESTIMATOR_H_
+#include "absl/types/optional.h"
+#include "api/units/data_size.h"
+#include "api/units/frequency.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
#include "modules/video_coding/rtt_filter.h"
#include "rtc_base/rolling_accumulator.h"
@@ -31,24 +36,25 @@
// Updates the jitter estimate with the new data.
//
// Input:
- // - frameDelay : Delay-delta calculated by UTILDelayEstimate in
- // milliseconds.
- // - frameSize : Frame size of the current frame.
- // - incompleteFrame : Flags if the frame is used to update the
+ // - frame_delay : Delay-delta calculated by UTILDelayEstimate.
+ // - frame_size : Frame size of the current frame.
+ // - incomplete_frame : Flags if the frame is used to update the
// estimate before it was complete.
// Default is false.
- void UpdateEstimate(int64_t frameDelayMS,
- uint32_t frameSizeBytes,
- bool incompleteFrame = false);
+ void UpdateEstimate(TimeDelta frame_delay,
+ DataSize frame_size,
+ bool incomplete_frame = false);
- // Returns the current jitter estimate in milliseconds and adds an RTT
- // dependent term in cases of retransmission.
+ // Returns the current jitter estimate and adds an RTT dependent term in cases
+ // of retransmission.
// Input:
- // - rttMultiplier : RTT param multiplier (when applicable).
+ // - rtt_multiplier : RTT param multiplier (when applicable).
+ // - rtt_mult_add_cap : Multiplier cap from the RTTMultExperiment.
//
- // Return value : Jitter estimate in milliseconds.
- virtual int GetJitterEstimate(double rttMultiplier,
- absl::optional<double> rttMultAddCapMs);
+ // Return value : Jitter estimate.
+ virtual TimeDelta GetJitterEstimate(
+ double rtt_multiplier,
+ absl::optional<TimeDelta> rtt_mult_add_cap);
// Updates the nack counter.
void FrameNacked();
@@ -56,45 +62,47 @@
// Updates the RTT filter.
//
// Input:
- // - rttMs : RTT in ms.
- void UpdateRtt(int64_t rttMs);
+ // - rtt : Round trip time.
+ void UpdateRtt(TimeDelta rtt);
// A constant describing the delay from the jitter buffer to the delay on the
// receiving side which is not accounted for by the jitter buffer nor the
// decoding delay estimate.
- static const uint32_t OPERATING_SYSTEM_JITTER = 10;
+ static constexpr TimeDelta OPERATING_SYSTEM_JITTER = TimeDelta::Millis(10);
protected:
// These are protected for better testing possibilities.
- double _theta[2]; // Estimated line parameters (slope, offset)
- double _varNoise; // Variance of the time-deviation from the line
+ double theta_[2]; // Estimated line parameters (slope, offset)
+ double var_noise_; // Variance of the time-deviation from the line
private:
// Updates the Kalman filter for the line describing the frame size dependent
// jitter.
//
// Input:
- // - frameDelayMS : Delay-delta calculated by UTILDelayEstimate in
- // milliseconds.
- // - deltaFSBytes : Frame size delta, i.e. frame size at time T
- // : minus frame size at time T-1.
- void KalmanEstimateChannel(int64_t frameDelayMS, int32_t deltaFSBytes);
+ // - frame_delay
+ // Delay-delta calculated by UTILDelayEstimate.
+ // - delta_frame_size_bytes
+ // Frame size delta, i.e. frame size at time T minus frame size
+ // at time T-1.
+ void KalmanEstimateChannel(TimeDelta frame_delay,
+ double delta_frame_size_bytes);
// Updates the random jitter estimate, i.e. the variance of the time
// deviations from the line given by the Kalman filter.
//
// Input:
// - d_dT : The deviation from the kalman estimate.
- // - incompleteFrame : True if the frame used to update the
+ // - incomplete_frame : True if the frame used to update the
// estimate with was incomplete.
- void EstimateRandomJitter(double d_dT, bool incompleteFrame);
+ void EstimateRandomJitter(double d_dT, bool incomplete_frame);
double NoiseThreshold() const;
// Calculates the current jitter estimate.
//
- // Return value : The current jitter estimate in milliseconds.
- double CalculateEstimate();
+ // Return value : The current jitter estimate.
+ TimeDelta CalculateEstimate();
// Post process the calculated estimate.
void PostProcessEstimate();
@@ -103,52 +111,48 @@
// estimated by the Kalman filter.
//
// Input:
- // - frameDelayMS : Delay-delta calculated by UTILDelayEstimate in
- // milliseconds.
- // - deltaFS : Frame size delta, i.e. frame size at time
- // T minus frame size at time T-1.
+ // - frame_delay : Delay-delta calculated by UTILDelayEstimate.
+ // - delta_frame_size_bytes : Frame size delta, i.e. frame size at
+ // time
+ // T minus frame size at time T-1.
//
- // Return value : The difference in milliseconds.
- double DeviationFromExpectedDelay(int64_t frameDelayMS,
- int32_t deltaFSBytes) const;
+ // Return value : The delay difference in ms.
+ double DeviationFromExpectedDelay(TimeDelta frame_delay,
+ double delta_frame_size_bytes) const;
- double GetFrameRate() const;
+ Frequency GetFrameRate() const;
- // Constants, filter parameters.
- const double _phi;
- const double _psi;
- const uint32_t _alphaCountMax;
- const double _thetaLow;
- const uint32_t _nackLimit;
- const int32_t _numStdDevDelayOutlier;
- const int32_t _numStdDevFrameSizeOutlier;
- const double _noiseStdDevs;
- const double _noiseStdDevOffset;
+ double theta_cov_[2][2]; // Estimate covariance
+ double q_cov_[2][2]; // Process noise covariance
- double _thetaCov[2][2]; // Estimate covariance
- double _Qcov[2][2]; // Process noise covariance
- double _avgFrameSize; // Average frame size
- double _varFrameSize; // Frame size variance
- double _maxFrameSize; // Largest frame size received (descending
- // with a factor _psi)
- uint32_t _fsSum;
- uint32_t _fsCount;
+ static constexpr DataSize kDefaultAvgAndMaxFrameSize = DataSize::Bytes(500);
+ DataSize avg_frame_size_ = kDefaultAvgAndMaxFrameSize; // Average frame size
+ double var_frame_size_; // Frame size variance. Unit is bytes^2.
+ // Largest frame size received (descending with a factor kPsi)
+ DataSize max_frame_size_ = kDefaultAvgAndMaxFrameSize;
+ DataSize frame_size_sum_ = DataSize::Zero();
+ uint32_t frame_size_count_;
- int64_t _lastUpdateT;
- double _prevEstimate; // The previously returned jitter estimate
- uint32_t _prevFrameSize; // Frame size of the previous frame
- double _avgNoise; // Average of the random jitter
- uint32_t _alphaCount;
- double _filterJitterEstimate; // The filtered sum of jitter estimates
+ absl::optional<Timestamp> last_update_time_;
+ // The previously returned jitter estimate
+ absl::optional<TimeDelta> prev_estimate_;
+ // Frame size of the previous frame
+ absl::optional<DataSize> prev_frame_size_;
+ // Average of the random jitter
+ double avg_noise_;
+ uint32_t alpha_count_;
+ // The filtered sum of jitter estimates
+ TimeDelta filter_jitter_estimate_ = TimeDelta::Zero();
- uint32_t _startupCount;
+ uint32_t startup_count_;
+ // Time when the latest nack was seen
+ Timestamp latest_nack_ = Timestamp::Zero();
+ // Keeps track of the number of nacks received, but never goes above
+ // kNackLimit.
+ uint32_t nack_count_;
+ VCMRttFilter rtt_filter_;
- int64_t
- _latestNackTimestamp; // Timestamp in ms when the latest nack was seen
- uint32_t _nackCount; // Keeps track of the number of nacks received,
- // but never goes above _nackLimit
- VCMRttFilter _rttFilter;
-
+ // Tracks frame rates in microseconds.
rtc::RollingAccumulator<uint64_t> fps_counter_;
const double time_deviation_upper_bound_;
const bool enable_reduced_delay_;
diff --git a/modules/video_coding/jitter_estimator_tests.cc b/modules/video_coding/jitter_estimator_tests.cc
index 14baae7..f4bb7fc 100644
--- a/modules/video_coding/jitter_estimator_tests.cc
+++ b/modules/video_coding/jitter_estimator_tests.cc
@@ -14,6 +14,9 @@
#include "absl/types/optional.h"
#include "api/array_view.h"
+#include "api/units/data_size.h"
+#include "api/units/frequency.h"
+#include "api/units/time_delta.h"
#include "modules/video_coding/jitter_estimator.h"
#include "rtc_base/experiments/jitter_upper_bound_experiment.h"
#include "rtc_base/numerics/histogram_percentile_counter.h"
@@ -33,10 +36,6 @@
estimator_ = std::make_unique<VCMJitterEstimator>(&fake_clock_);
}
- void AdvanceClock(int64_t microseconds) {
- fake_clock_.AdvanceTimeMicroseconds(microseconds);
- }
-
SimulatedClock fake_clock_;
std::unique_ptr<VCMJitterEstimator> estimator_;
};
@@ -46,11 +45,16 @@
public:
explicit ValueGenerator(int32_t amplitude)
: amplitude_(amplitude), counter_(0) {}
- virtual ~ValueGenerator() {}
- int64_t Delay() const { return ((counter_ % 11) - 5) * amplitude_; }
+ virtual ~ValueGenerator() = default;
- uint32_t FrameSize() const { return 1000 + Delay(); }
+ TimeDelta Delay() const {
+ return TimeDelta::Millis((counter_ % 11) - 5) * amplitude_;
+ }
+
+ DataSize FrameSize() const {
+ return DataSize::Bytes(1000 + Delay().ms() / 5);
+ }
void Advance() { ++counter_; }
@@ -62,12 +66,13 @@
// 5 fps, disable jitter delay altogether.
TEST_F(TestVCMJitterEstimator, TestLowRate) {
ValueGenerator gen(10);
- uint64_t time_delta_us = rtc::kNumMicrosecsPerSec / 5;
+ TimeDelta time_delta = 1 / Frequency::Hertz(5);
for (int i = 0; i < 60; ++i) {
estimator_->UpdateEstimate(gen.Delay(), gen.FrameSize());
- AdvanceClock(time_delta_us);
+ fake_clock_.AdvanceTime(time_delta);
if (i > 2)
- EXPECT_EQ(estimator_->GetJitterEstimate(0, absl::nullopt), 0);
+ EXPECT_EQ(estimator_->GetJitterEstimate(0, absl::nullopt),
+ TimeDelta::Zero());
gen.Advance();
}
}
@@ -78,12 +83,13 @@
SetUp();
ValueGenerator gen(10);
- uint64_t time_delta_us = rtc::kNumMicrosecsPerSec / 5;
+ TimeDelta time_delta = 1 / Frequency::Hertz(5);
for (int i = 0; i < 60; ++i) {
estimator_->UpdateEstimate(gen.Delay(), gen.FrameSize());
- AdvanceClock(time_delta_us);
+ fake_clock_.AdvanceTime(time_delta);
if (i > 2)
- EXPECT_GT(estimator_->GetJitterEstimate(0, absl::nullopt), 0);
+ EXPECT_GT(estimator_->GetJitterEstimate(0, absl::nullopt),
+ TimeDelta::Zero());
gen.Advance();
}
}
@@ -97,7 +103,7 @@
percentiles(1000) {}
double upper_bound;
double rtt_mult;
- absl::optional<double> rtt_mult_add_cap_ms;
+ absl::optional<TimeDelta> rtt_mult_add_cap_ms;
rtc::HistogramPercentileCounter percentiles;
};
std::vector<TestContext> test_cases(4);
@@ -113,11 +119,11 @@
// Large upper bound, rtt_mult = 1, and large rtt_mult addition cap value.
test_cases[2].upper_bound = 1000.0;
test_cases[2].rtt_mult = 1.0;
- test_cases[2].rtt_mult_add_cap_ms = 200.0;
+ test_cases[2].rtt_mult_add_cap_ms = TimeDelta::Millis(200);
// Large upper bound, rtt_mult = 1, and small rtt_mult addition cap value.
test_cases[3].upper_bound = 1000.0;
test_cases[3].rtt_mult = 1.0;
- test_cases[3].rtt_mult_add_cap_ms = 10.0;
+ test_cases[3].rtt_mult_add_cap_ms = TimeDelta::Millis(10);
// Test jitter buffer upper_bound and rtt_mult addition cap sizes.
for (TestContext& context : test_cases) {
@@ -130,16 +136,17 @@
SetUp();
ValueGenerator gen(50);
- uint64_t time_delta_us = rtc::kNumMicrosecsPerSec / 30;
- constexpr int64_t kRttMs = 250;
+ TimeDelta time_delta = 1 / Frequency::Hertz(30);
+ constexpr TimeDelta kRtt = TimeDelta::Millis(250);
for (int i = 0; i < 100; ++i) {
estimator_->UpdateEstimate(gen.Delay(), gen.FrameSize());
- AdvanceClock(time_delta_us);
+ fake_clock_.AdvanceTime(time_delta);
estimator_->FrameNacked(); // To test rtt_mult.
- estimator_->UpdateRtt(kRttMs); // To test rtt_mult.
+ estimator_->UpdateRtt(kRtt); // To test rtt_mult.
context.percentiles.Add(
- static_cast<uint32_t>(estimator_->GetJitterEstimate(
- context.rtt_mult, context.rtt_mult_add_cap_ms)));
+ estimator_
+ ->GetJitterEstimate(context.rtt_mult, context.rtt_mult_add_cap_ms)
+ .ms());
gen.Advance();
}
}
diff --git a/video/BUILD.gn b/video/BUILD.gn
index e8f7417..e5ba48b 100644
--- a/video/BUILD.gn
+++ b/video/BUILD.gn
@@ -100,6 +100,7 @@
"../modules/video_coding:codec_globals_headers",
"../modules/video_coding:frame_buffer",
"../modules/video_coding:frame_helpers",
+ "../modules/video_coding:jitter_estimator",
"../modules/video_coding:nack_requester",
"../modules/video_coding:packet_buffer",
"../modules/video_coding:timing",
@@ -308,6 +309,7 @@
"../api:sequence_checker",
"../api/metronome",
"../api/task_queue",
+ "../api/units:data_size",
"../api/video:encoded_frame",
"../api/video:video_rtp_headers",
"../modules/video_coding",
diff --git a/video/frame_buffer_proxy.cc b/video/frame_buffer_proxy.cc
index d277a36..c7fce7a 100644
--- a/video/frame_buffer_proxy.cc
+++ b/video/frame_buffer_proxy.cc
@@ -17,6 +17,7 @@
#include "absl/base/attributes.h"
#include "absl/functional/bind_front.h"
#include "api/sequence_checker.h"
+#include "api/units/data_size.h"
#include "api/video/encoded_frame.h"
#include "api/video/video_content_type.h"
#include "modules/video_coding/frame_buffer2.h"
@@ -261,7 +262,7 @@
void UpdateRtt(int64_t max_rtt_ms) override {
RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
- jitter_estimator_.UpdateRtt(max_rtt_ms);
+ jitter_estimator_.UpdateRtt(TimeDelta::Millis(max_rtt_ms));
}
void StartNextDecode(bool keyframe_required) override {
@@ -298,7 +299,7 @@
Timestamp now = clock_->CurrentTime();
bool superframe_delayed_by_retransmission = false;
- size_t superframe_size = 0;
+ DataSize superframe_size = DataSize::Zero();
const EncodedFrame& first_frame = *frames.front();
int64_t receive_time_ms = first_frame.ReceivedTime();
@@ -319,7 +320,7 @@
superframe_delayed_by_retransmission |=
frame->delayed_by_retransmission();
receive_time_ms = std::max(receive_time_ms, frame->ReceivedTime());
- superframe_size += frame->size();
+ superframe_size += DataSize::Bytes(frame->size());
}
if (!superframe_delayed_by_retransmission) {
@@ -327,17 +328,19 @@
if (inter_frame_delay_.CalculateDelay(first_frame.Timestamp(),
&frame_delay, receive_time_ms)) {
- jitter_estimator_.UpdateEstimate(frame_delay, superframe_size);
+ jitter_estimator_.UpdateEstimate(TimeDelta::Millis(frame_delay),
+ superframe_size);
}
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
- absl::optional<float> rtt_mult_add_cap_ms = absl::nullopt;
+ absl::optional<TimeDelta> rtt_mult_add_cap_ms = absl::nullopt;
if (rtt_mult_settings_.has_value()) {
rtt_mult = rtt_mult_settings_->rtt_mult_setting;
- rtt_mult_add_cap_ms = rtt_mult_settings_->rtt_mult_add_cap_ms;
+ rtt_mult_add_cap_ms =
+ TimeDelta::Millis(rtt_mult_settings_->rtt_mult_add_cap_ms);
}
- timing_->SetJitterDelay(TimeDelta::Millis(
- jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms)));
+ timing_->SetJitterDelay(
+ jitter_estimator_.GetJitterEstimate(rtt_mult, rtt_mult_add_cap_ms));
timing_->UpdateCurrentDelay(render_time, now);
} else if (RttMultExperiment::RttMultEnabled()) {
jitter_estimator_.FrameNacked();
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index 290180b..c2e7946 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -692,6 +692,7 @@
void VideoReceiveStream2::OnRttUpdate(int64_t avg_rtt_ms, int64_t max_rtt_ms) {
RTC_DCHECK_RUN_ON(&worker_sequence_checker_);
+ // TODO(bugs.webrtc.org/13757): Replace with TimeDelta.
frame_buffer_->UpdateRtt(max_rtt_ms);
rtp_video_stream_receiver_.UpdateRtt(max_rtt_ms);
stats_proxy_.OnRttUpdate(avg_rtt_ms);