Rename InterFrameDelay -> InterFrameDelayVariationCalculator.
This class name better reflects the nomenclature defined by RFC5481: https://datatracker.ietf.org/doc/html/rfc5481#section-1. Some code style improvements were performed. No functional changes are intended. Bug: webrtc:14905 Change-Id: I84b9deb7b2ac7f1a07ae00670eaff9656a50c2cc Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/295661 Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Rasmus Brandt <brandtr@webrtc.org> Cr-Commit-Position: refs/heads/main@{#39466}
This commit is contained in:
parent
ca6481d37f
commit
65a6ecab33
@ -265,7 +265,7 @@ rtc_library("video_coding") {
|
|||||||
"../rtp_rtcp:rtp_video_header",
|
"../rtp_rtcp:rtp_video_header",
|
||||||
"codecs/av1:av1_svc_config",
|
"codecs/av1:av1_svc_config",
|
||||||
"svc:scalability_mode_util",
|
"svc:scalability_mode_util",
|
||||||
"timing:inter_frame_delay",
|
"timing:inter_frame_delay_variation_calculator",
|
||||||
"timing:jitter_estimator",
|
"timing:jitter_estimator",
|
||||||
"timing:rtt_filter",
|
"timing:rtt_filter",
|
||||||
"timing:timing_module",
|
"timing:timing_module",
|
||||||
@ -358,7 +358,7 @@ rtc_library("video_coding_legacy") {
|
|||||||
"../rtp_rtcp:rtp_rtcp_format",
|
"../rtp_rtcp:rtp_rtcp_format",
|
||||||
"../rtp_rtcp:rtp_video_header",
|
"../rtp_rtcp:rtp_video_header",
|
||||||
"deprecated:deprecated_packet",
|
"deprecated:deprecated_packet",
|
||||||
"timing:inter_frame_delay",
|
"timing:inter_frame_delay_variation_calculator",
|
||||||
"timing:jitter_estimator",
|
"timing:jitter_estimator",
|
||||||
"timing:timing_module",
|
"timing:timing_module",
|
||||||
]
|
]
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
#include "modules/video_coding/include/video_coding.h"
|
#include "modules/video_coding/include/video_coding.h"
|
||||||
#include "modules/video_coding/internal_defines.h"
|
#include "modules/video_coding/internal_defines.h"
|
||||||
#include "modules/video_coding/jitter_buffer_common.h"
|
#include "modules/video_coding/jitter_buffer_common.h"
|
||||||
#include "modules/video_coding/timing/inter_frame_delay.h"
|
#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
|
||||||
#include "modules/video_coding/timing/jitter_estimator.h"
|
#include "modules/video_coding/timing/jitter_estimator.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
@ -873,7 +873,7 @@ void VCMJitterBuffer::UpdateJitterEstimate(int64_t latest_packet_time_ms,
|
|||||||
if (latest_packet_time_ms == -1) {
|
if (latest_packet_time_ms == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto frame_delay = inter_frame_delay_.CalculateDelay(
|
auto frame_delay = inter_frame_delay_.Calculate(
|
||||||
timestamp, Timestamp::Millis(latest_packet_time_ms));
|
timestamp, Timestamp::Millis(latest_packet_time_ms));
|
||||||
|
|
||||||
bool not_reordered = frame_delay.has_value();
|
bool not_reordered = frame_delay.has_value();
|
||||||
|
|||||||
@ -25,7 +25,7 @@
|
|||||||
#include "modules/video_coding/include/video_coding.h"
|
#include "modules/video_coding/include/video_coding.h"
|
||||||
#include "modules/video_coding/include/video_coding_defines.h"
|
#include "modules/video_coding/include/video_coding_defines.h"
|
||||||
#include "modules/video_coding/jitter_buffer_common.h"
|
#include "modules/video_coding/jitter_buffer_common.h"
|
||||||
#include "modules/video_coding/timing/inter_frame_delay.h"
|
#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
|
||||||
#include "modules/video_coding/timing/jitter_estimator.h"
|
#include "modules/video_coding/timing/jitter_estimator.h"
|
||||||
#include "rtc_base/synchronization/mutex.h"
|
#include "rtc_base/synchronization/mutex.h"
|
||||||
#include "rtc_base/thread_annotations.h"
|
#include "rtc_base/thread_annotations.h"
|
||||||
@ -254,7 +254,7 @@ class VCMJitterBuffer {
|
|||||||
// Filter for estimating jitter.
|
// Filter for estimating jitter.
|
||||||
JitterEstimator jitter_estimate_;
|
JitterEstimator jitter_estimate_;
|
||||||
// Calculates network delays used for jitter calculations.
|
// Calculates network delays used for jitter calculations.
|
||||||
InterFrameDelay inter_frame_delay_;
|
InterFrameDelayVariationCalculator inter_frame_delay_;
|
||||||
VCMJitterSample waiting_for_completion_;
|
VCMJitterSample waiting_for_completion_;
|
||||||
|
|
||||||
// Holds the internal NACK list (the missing sequence numbers).
|
// Holds the internal NACK list (the missing sequence numbers).
|
||||||
|
|||||||
@ -16,10 +16,10 @@ rtc_library("decode_time_percentile_filter") {
|
|||||||
deps = [ "../../../rtc_base:rtc_numerics" ]
|
deps = [ "../../../rtc_base:rtc_numerics" ]
|
||||||
}
|
}
|
||||||
|
|
||||||
rtc_library("inter_frame_delay") {
|
rtc_library("inter_frame_delay_variation_calculator") {
|
||||||
sources = [
|
sources = [
|
||||||
"inter_frame_delay.cc",
|
"inter_frame_delay_variation_calculator.cc",
|
||||||
"inter_frame_delay.h",
|
"inter_frame_delay_variation_calculator.h",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
"../..:module_api_public",
|
"../..:module_api_public",
|
||||||
@ -124,7 +124,7 @@ rtc_library("timing_unittests") {
|
|||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
"frame_delay_variation_kalman_filter_unittest.cc",
|
"frame_delay_variation_kalman_filter_unittest.cc",
|
||||||
"inter_frame_delay_unittest.cc",
|
"inter_frame_delay_variation_calculator_unittest.cc",
|
||||||
"jitter_estimator_unittest.cc",
|
"jitter_estimator_unittest.cc",
|
||||||
"rtt_filter_unittest.cc",
|
"rtt_filter_unittest.cc",
|
||||||
"timestamp_extrapolator_unittest.cc",
|
"timestamp_extrapolator_unittest.cc",
|
||||||
@ -132,7 +132,7 @@ rtc_library("timing_unittests") {
|
|||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
":frame_delay_variation_kalman_filter",
|
":frame_delay_variation_kalman_filter",
|
||||||
":inter_frame_delay",
|
":inter_frame_delay_variation_calculator",
|
||||||
":jitter_estimator",
|
":jitter_estimator",
|
||||||
":rtt_filter",
|
":rtt_filter",
|
||||||
":timestamp_extrapolator",
|
":timestamp_extrapolator",
|
||||||
|
|||||||
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
||||||
*
|
|
||||||
* Use of this source code is governed by a BSD-style license
|
|
||||||
* that can be found in the LICENSE file in the root of the source
|
|
||||||
* tree. An additional intellectual property rights grant can be found
|
|
||||||
* in the file PATENTS. All contributing project authors may
|
|
||||||
* be found in the AUTHORS file in the root of the source tree.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MODULES_VIDEO_CODING_TIMING_INTER_FRAME_DELAY_H_
|
|
||||||
#define MODULES_VIDEO_CODING_TIMING_INTER_FRAME_DELAY_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
#include "absl/types/optional.h"
|
|
||||||
#include "api/units/time_delta.h"
|
|
||||||
#include "api/units/timestamp.h"
|
|
||||||
#include "rtc_base/numerics/sequence_number_unwrapper.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
class InterFrameDelay {
|
|
||||||
public:
|
|
||||||
InterFrameDelay();
|
|
||||||
|
|
||||||
// Resets the estimate. Zeros are given as parameters.
|
|
||||||
void Reset();
|
|
||||||
|
|
||||||
// Calculates the delay of a frame with the given timestamp.
|
|
||||||
// This method is called when the frame is complete.
|
|
||||||
absl::optional<TimeDelta> CalculateDelay(uint32_t rtp_timestamp,
|
|
||||||
Timestamp now);
|
|
||||||
|
|
||||||
private:
|
|
||||||
// The previous rtp timestamp passed to the delay estimate
|
|
||||||
int64_t prev_rtp_timestamp_unwrapped_;
|
|
||||||
RtpTimestampUnwrapper unwrapper_;
|
|
||||||
|
|
||||||
// The previous wall clock timestamp used by the delay estimate
|
|
||||||
absl::optional<Timestamp> prev_wall_clock_;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
||||||
|
|
||||||
#endif // MODULES_VIDEO_CODING_TIMING_INTER_FRAME_DELAY_H_
|
|
||||||
@ -8,7 +8,7 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "modules/video_coding/timing/inter_frame_delay.h"
|
#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
|
||||||
|
|
||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/units/frequency.h"
|
#include "api/units/frequency.h"
|
||||||
@ -21,51 +21,51 @@ namespace {
|
|||||||
constexpr Frequency k90kHz = Frequency::KiloHertz(90);
|
constexpr Frequency k90kHz = Frequency::KiloHertz(90);
|
||||||
}
|
}
|
||||||
|
|
||||||
InterFrameDelay::InterFrameDelay() {
|
InterFrameDelayVariationCalculator::InterFrameDelayVariationCalculator() {
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resets the delay estimate.
|
void InterFrameDelayVariationCalculator::Reset() {
|
||||||
void InterFrameDelay::Reset() {
|
|
||||||
prev_wall_clock_ = absl::nullopt;
|
prev_wall_clock_ = absl::nullopt;
|
||||||
prev_rtp_timestamp_unwrapped_ = 0;
|
prev_rtp_timestamp_unwrapped_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculates the delay of a frame with the given timestamp.
|
absl::optional<TimeDelta> InterFrameDelayVariationCalculator::Calculate(
|
||||||
// This method is called when the frame is complete.
|
|
||||||
absl::optional<TimeDelta> InterFrameDelay::CalculateDelay(
|
|
||||||
uint32_t rtp_timestamp,
|
uint32_t rtp_timestamp,
|
||||||
Timestamp now) {
|
Timestamp now) {
|
||||||
int64_t rtp_timestamp_unwrapped = unwrapper_.Unwrap(rtp_timestamp);
|
int64_t rtp_timestamp_unwrapped = unwrapper_.Unwrap(rtp_timestamp);
|
||||||
|
|
||||||
if (!prev_wall_clock_) {
|
if (!prev_wall_clock_) {
|
||||||
// First set of data, initialization, wait for next frame.
|
|
||||||
prev_wall_clock_ = now;
|
prev_wall_clock_ = now;
|
||||||
prev_rtp_timestamp_unwrapped_ = rtp_timestamp_unwrapped;
|
prev_rtp_timestamp_unwrapped_ = rtp_timestamp_unwrapped;
|
||||||
|
// Inter-frame delay variation is undefined for a single frame.
|
||||||
|
// TODO(brandtr): Should this return absl::nullopt instead?
|
||||||
return TimeDelta::Zero();
|
return TimeDelta::Zero();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Account for reordering in jitter variance estimate in the future?
|
// Account for reordering in jitter variance estimate in the future?
|
||||||
// Note that this also captures incomplete frames which are grabbed for
|
// Note that this also captures incomplete frames which are grabbed for
|
||||||
// decoding after a later frame has been complete, i.e. real packet losses.
|
// decoding after a later frame has been complete, i.e. real packet losses.
|
||||||
uint32_t cropped_last = static_cast<uint32_t>(prev_rtp_timestamp_unwrapped_);
|
uint32_t cropped_prev = static_cast<uint32_t>(prev_rtp_timestamp_unwrapped_);
|
||||||
if (rtp_timestamp_unwrapped < prev_rtp_timestamp_unwrapped_ ||
|
if (rtp_timestamp_unwrapped < prev_rtp_timestamp_unwrapped_ ||
|
||||||
!IsNewerTimestamp(rtp_timestamp, cropped_last)) {
|
!IsNewerTimestamp(rtp_timestamp, cropped_prev)) {
|
||||||
return absl::nullopt;
|
return absl::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compute the compensated timestamp difference.
|
// Compute the compensated timestamp difference.
|
||||||
|
TimeDelta delta_wall = now - *prev_wall_clock_;
|
||||||
int64_t d_rtp_ticks = rtp_timestamp_unwrapped - prev_rtp_timestamp_unwrapped_;
|
int64_t d_rtp_ticks = rtp_timestamp_unwrapped - prev_rtp_timestamp_unwrapped_;
|
||||||
TimeDelta dts = d_rtp_ticks / k90kHz;
|
TimeDelta delta_rtp = d_rtp_ticks / k90kHz;
|
||||||
TimeDelta dt = now - *prev_wall_clock_;
|
|
||||||
|
|
||||||
// frameDelay is the difference of dT and dTS -- i.e. the difference of the
|
// The inter-frame delay variation is the second order difference between the
|
||||||
// wall clock time difference and the timestamp difference between two
|
// RTP and wall clocks of the two frames, or in other words, the first order
|
||||||
// following frames.
|
// difference between `delta_rtp` and `delta_wall`.
|
||||||
TimeDelta delay = dt - dts;
|
TimeDelta inter_frame_delay_variation = delta_wall - delta_rtp;
|
||||||
|
|
||||||
prev_rtp_timestamp_unwrapped_ = rtp_timestamp_unwrapped;
|
|
||||||
prev_wall_clock_ = now;
|
prev_wall_clock_ = now;
|
||||||
return delay;
|
prev_rtp_timestamp_unwrapped_ = rtp_timestamp_unwrapped;
|
||||||
|
|
||||||
|
return inter_frame_delay_variation;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by a BSD-style license
|
||||||
|
* that can be found in the LICENSE file in the root of the source
|
||||||
|
* tree. An additional intellectual property rights grant can be found
|
||||||
|
* in the file PATENTS. All contributing project authors may
|
||||||
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MODULES_VIDEO_CODING_TIMING_INTER_FRAME_DELAY_VARIATION_CALCULATOR_H_
|
||||||
|
#define MODULES_VIDEO_CODING_TIMING_INTER_FRAME_DELAY_VARIATION_CALCULATOR_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "absl/types/optional.h"
|
||||||
|
#include "api/units/time_delta.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
|
#include "rtc_base/numerics/sequence_number_unwrapper.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
|
||||||
|
// This class calculates the inter-frame delay variation (see RFC5481) between
|
||||||
|
// the current frame (as supplied through the current call to `Calculate`) and
|
||||||
|
// the previous frame (as supplied through the previous call to `Calculate`).
|
||||||
|
class InterFrameDelayVariationCalculator {
|
||||||
|
public:
|
||||||
|
InterFrameDelayVariationCalculator();
|
||||||
|
|
||||||
|
// Resets the calculator.
|
||||||
|
void Reset();
|
||||||
|
|
||||||
|
// Calculates the inter-frame delay variation of a frame with the given
|
||||||
|
// RTP timestamp. This method is called when the frame is complete.
|
||||||
|
absl::optional<TimeDelta> Calculate(uint32_t rtp_timestamp, Timestamp now);
|
||||||
|
|
||||||
|
private:
|
||||||
|
// The previous wall clock timestamp used in the calculation.
|
||||||
|
absl::optional<Timestamp> prev_wall_clock_;
|
||||||
|
// The previous RTP timestamp used in the calculation.
|
||||||
|
int64_t prev_rtp_timestamp_unwrapped_;
|
||||||
|
|
||||||
|
RtpTimestampUnwrapper unwrapper_;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace webrtc
|
||||||
|
|
||||||
|
#endif // MODULES_VIDEO_CODING_TIMING_INTER_FRAME_DELAY_VARIATION_CALCULATOR_H_
|
||||||
@ -8,7 +8,7 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "modules/video_coding/timing/inter_frame_delay.h"
|
#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
|
||||||
@ -36,76 +36,75 @@ constexpr Timestamp kStartTime = Timestamp::Millis(1337);
|
|||||||
using ::testing::Eq;
|
using ::testing::Eq;
|
||||||
using ::testing::Optional;
|
using ::testing::Optional;
|
||||||
|
|
||||||
TEST(InterFrameDelayTest, OldRtpTimestamp) {
|
TEST(InterFrameDelayVariationCalculatorTest, OldRtpTimestamp) {
|
||||||
InterFrameDelay inter_frame_delay;
|
InterFrameDelayVariationCalculator ifdv_calculator;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(180000, kStartTime),
|
EXPECT_THAT(ifdv_calculator.Calculate(180000, kStartTime),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(90000, kStartTime),
|
EXPECT_THAT(ifdv_calculator.Calculate(90000, kStartTime), Eq(absl::nullopt));
|
||||||
Eq(absl::nullopt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InterFrameDelayTest, NegativeWrapAroundIsSameAsOldRtpTimestamp) {
|
TEST(InterFrameDelayVariationCalculatorTest,
|
||||||
InterFrameDelay inter_frame_delay;
|
NegativeWrapAroundIsSameAsOldRtpTimestamp) {
|
||||||
|
InterFrameDelayVariationCalculator ifdv_calculator;
|
||||||
uint32_t rtp = 1500;
|
uint32_t rtp = 1500;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, kStartTime),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, kStartTime),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
// RTP has wrapped around backwards.
|
// RTP has wrapped around backwards.
|
||||||
rtp -= 3000;
|
rtp -= 3000;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, kStartTime),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, kStartTime), Eq(absl::nullopt));
|
||||||
Eq(absl::nullopt));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InterFrameDelayTest, CorrectDelayForFrames) {
|
TEST(InterFrameDelayVariationCalculatorTest, CorrectDelayForFrames) {
|
||||||
InterFrameDelay inter_frame_delay;
|
InterFrameDelayVariationCalculator ifdv_calculator;
|
||||||
// Use a fake clock to simplify time keeping.
|
// Use a fake clock to simplify time keeping.
|
||||||
SimulatedClock clock(kStartTime);
|
SimulatedClock clock(kStartTime);
|
||||||
|
|
||||||
// First frame is always delay 0.
|
// First frame is always delay variation 0.
|
||||||
uint32_t rtp = 90000;
|
uint32_t rtp = 90000;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
|
|
||||||
// Perfectly timed frame has 0 delay.
|
// Perfectly timed frame has 0 delay variation.
|
||||||
clock.AdvanceTime(kFrameDelay);
|
clock.AdvanceTime(kFrameDelay);
|
||||||
rtp += kRtpTicksPerFrame;
|
rtp += kRtpTicksPerFrame;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
|
|
||||||
// Slightly early frame will have a negative delay.
|
// Slightly early frame will have a negative delay variation.
|
||||||
clock.AdvanceTime(kFrameDelay - TimeDelta::Millis(3));
|
clock.AdvanceTime(kFrameDelay - TimeDelta::Millis(3));
|
||||||
rtp += kRtpTicksPerFrame;
|
rtp += kRtpTicksPerFrame;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(-TimeDelta::Millis(3)));
|
Optional(-TimeDelta::Millis(3)));
|
||||||
|
|
||||||
// Slightly late frame will have positive delay.
|
// Slightly late frame will have positive delay variation.
|
||||||
clock.AdvanceTime(kFrameDelay + TimeDelta::Micros(5125));
|
clock.AdvanceTime(kFrameDelay + TimeDelta::Micros(5125));
|
||||||
rtp += kRtpTicksPerFrame;
|
rtp += kRtpTicksPerFrame;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Micros(5125)));
|
Optional(TimeDelta::Micros(5125)));
|
||||||
|
|
||||||
// Simulate faster frame RTP at the same clock delay. The frame arrives late,
|
// Simulate faster frame RTP at the same clock delay. The frame arrives late,
|
||||||
// since the RTP timestamp is faster than the delay, and thus is positive.
|
// since the RTP timestamp is faster than the delay, and thus is positive.
|
||||||
clock.AdvanceTime(kFrameDelay);
|
clock.AdvanceTime(kFrameDelay);
|
||||||
rtp += kRtpTicksPerFrame / 2;
|
rtp += kRtpTicksPerFrame / 2;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(kFrameDelay / 2.0));
|
Optional(kFrameDelay / 2.0));
|
||||||
|
|
||||||
// Simulate slower frame RTP at the same clock delay. The frame is early,
|
// Simulate slower frame RTP at the same clock delay. The frame is early,
|
||||||
// since the RTP timestamp advanced more than the delay, and thus is negative.
|
// since the RTP timestamp advanced more than the delay, and thus is negative.
|
||||||
clock.AdvanceTime(kFrameDelay);
|
clock.AdvanceTime(kFrameDelay);
|
||||||
rtp += 1.5 * kRtpTicksPerFrame;
|
rtp += 1.5 * kRtpTicksPerFrame;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(-kFrameDelay / 2.0));
|
Optional(-kFrameDelay / 2.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InterFrameDelayTest, PositiveWrapAround) {
|
TEST(InterFrameDelayVariationCalculatorTest, PositiveWrapAround) {
|
||||||
InterFrameDelay inter_frame_delay;
|
InterFrameDelayVariationCalculator ifdv_calculator;
|
||||||
// Use a fake clock to simplify time keeping.
|
// Use a fake clock to simplify time keeping.
|
||||||
SimulatedClock clock(kStartTime);
|
SimulatedClock clock(kStartTime);
|
||||||
|
|
||||||
// First frame is behind the max RTP by 1500.
|
// First frame is behind the max RTP by 1500.
|
||||||
uint32_t rtp = std::numeric_limits<uint32_t>::max() - 1500;
|
uint32_t rtp = std::numeric_limits<uint32_t>::max() - 1500;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
|
|
||||||
// Rtp wraps around, now 1499.
|
// Rtp wraps around, now 1499.
|
||||||
@ -113,77 +112,78 @@ TEST(InterFrameDelayTest, PositiveWrapAround) {
|
|||||||
|
|
||||||
// Frame delay should be as normal, in this case simulated as 1ms late.
|
// Frame delay should be as normal, in this case simulated as 1ms late.
|
||||||
clock.AdvanceTime(kFrameDelay + TimeDelta::Millis(1));
|
clock.AdvanceTime(kFrameDelay + TimeDelta::Millis(1));
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Millis(1)));
|
Optional(TimeDelta::Millis(1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InterFrameDelayTest, MultipleWrapArounds) {
|
TEST(InterFrameDelayVariationCalculatorTest, MultipleWrapArounds) {
|
||||||
// Simulate a long pauses which cause wrap arounds multiple times.
|
// Simulate a long pauses which cause wrap arounds multiple times.
|
||||||
constexpr Frequency k90Khz = Frequency::KiloHertz(90);
|
constexpr Frequency k90Khz = Frequency::KiloHertz(90);
|
||||||
constexpr uint32_t kHalfRtp = std::numeric_limits<uint32_t>::max() / 2;
|
constexpr uint32_t kHalfRtp = std::numeric_limits<uint32_t>::max() / 2;
|
||||||
constexpr TimeDelta kWrapAroundDelay = kHalfRtp / k90Khz;
|
constexpr TimeDelta kWrapAroundDelay = kHalfRtp / k90Khz;
|
||||||
|
|
||||||
InterFrameDelay inter_frame_delay;
|
InterFrameDelayVariationCalculator ifdv_calculator;
|
||||||
// Use a fake clock to simplify time keeping.
|
// Use a fake clock to simplify time keeping.
|
||||||
SimulatedClock clock(kStartTime);
|
SimulatedClock clock(kStartTime);
|
||||||
uint32_t rtp = 0;
|
uint32_t rtp = 0;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
|
|
||||||
rtp += kHalfRtp;
|
rtp += kHalfRtp;
|
||||||
clock.AdvanceTime(kWrapAroundDelay);
|
clock.AdvanceTime(kWrapAroundDelay);
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
// 1st wrap around.
|
// 1st wrap around.
|
||||||
rtp += kHalfRtp + 1;
|
rtp += kHalfRtp + 1;
|
||||||
clock.AdvanceTime(kWrapAroundDelay + TimeDelta::Millis(1));
|
clock.AdvanceTime(kWrapAroundDelay + TimeDelta::Millis(1));
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Millis(1) - (1 / k90Khz)));
|
Optional(TimeDelta::Millis(1) - (1 / k90Khz)));
|
||||||
|
|
||||||
rtp += kHalfRtp;
|
rtp += kHalfRtp;
|
||||||
clock.AdvanceTime(kWrapAroundDelay);
|
clock.AdvanceTime(kWrapAroundDelay);
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
// 2nd wrap arounds.
|
// 2nd wrap arounds.
|
||||||
rtp += kHalfRtp + 1;
|
rtp += kHalfRtp + 1;
|
||||||
clock.AdvanceTime(kWrapAroundDelay - TimeDelta::Millis(1));
|
clock.AdvanceTime(kWrapAroundDelay - TimeDelta::Millis(1));
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(-TimeDelta::Millis(1) - (1 / k90Khz)));
|
Optional(-TimeDelta::Millis(1) - (1 / k90Khz)));
|
||||||
|
|
||||||
// Ensure short delay (large RTP delay) between wrap-arounds has correct
|
// Ensure short delay (large RTP delay) between wrap-arounds has correct
|
||||||
// jitter.
|
// jitter.
|
||||||
rtp += kHalfRtp;
|
rtp += kHalfRtp;
|
||||||
clock.AdvanceTime(TimeDelta::Millis(10));
|
clock.AdvanceTime(TimeDelta::Millis(10));
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(-(kWrapAroundDelay - TimeDelta::Millis(10))));
|
Optional(-(kWrapAroundDelay - TimeDelta::Millis(10))));
|
||||||
// 3nd wrap arounds, this time with large RTP delay.
|
// 3nd wrap arounds, this time with large RTP delay.
|
||||||
rtp += kHalfRtp + 1;
|
rtp += kHalfRtp + 1;
|
||||||
clock.AdvanceTime(TimeDelta::Millis(10));
|
clock.AdvanceTime(TimeDelta::Millis(10));
|
||||||
EXPECT_THAT(
|
EXPECT_THAT(
|
||||||
inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(-(kWrapAroundDelay - TimeDelta::Millis(10) + (1 / k90Khz))));
|
Optional(-(kWrapAroundDelay - TimeDelta::Millis(10) + (1 / k90Khz))));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(InterFrameDelayTest, NegativeWrapAroundAfterPositiveWrapAround) {
|
TEST(InterFrameDelayVariationCalculatorTest,
|
||||||
InterFrameDelay inter_frame_delay;
|
NegativeWrapAroundAfterPositiveWrapAround) {
|
||||||
|
InterFrameDelayVariationCalculator ifdv_calculator;
|
||||||
// Use a fake clock to simplify time keeping.
|
// Use a fake clock to simplify time keeping.
|
||||||
SimulatedClock clock(kStartTime);
|
SimulatedClock clock(kStartTime);
|
||||||
uint32_t rtp = std::numeric_limits<uint32_t>::max() - 1500;
|
uint32_t rtp = std::numeric_limits<uint32_t>::max() - 1500;
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
|
|
||||||
// Rtp wraps around, now 1499.
|
// Rtp wraps around, now 1499.
|
||||||
rtp += kRtpTicksPerFrame;
|
rtp += kRtpTicksPerFrame;
|
||||||
// Frame delay should be as normal, in this case simulated as 1ms late.
|
// Frame delay should be as normal, in this case simulated as 1ms late.
|
||||||
clock.AdvanceTime(kFrameDelay);
|
clock.AdvanceTime(kFrameDelay);
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Optional(TimeDelta::Zero()));
|
Optional(TimeDelta::Zero()));
|
||||||
|
|
||||||
// Wrap back.
|
// Wrap back.
|
||||||
rtp -= kRtpTicksPerFrame;
|
rtp -= kRtpTicksPerFrame;
|
||||||
// Frame delay should be as normal, in this case simulated as 1ms late.
|
// Frame delay should be as normal, in this case simulated as 1ms late.
|
||||||
clock.AdvanceTime(kFrameDelay);
|
clock.AdvanceTime(kFrameDelay);
|
||||||
EXPECT_THAT(inter_frame_delay.CalculateDelay(rtp, clock.CurrentTime()),
|
EXPECT_THAT(ifdv_calculator.Calculate(rtp, clock.CurrentTime()),
|
||||||
Eq(absl::nullopt));
|
Eq(absl::nullopt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,13 +247,14 @@ rtc_library("video_stream_buffer_controller") {
|
|||||||
"../api/metronome",
|
"../api/metronome",
|
||||||
"../api/task_queue",
|
"../api/task_queue",
|
||||||
"../api/units:data_size",
|
"../api/units:data_size",
|
||||||
|
"../api/units:time_delta",
|
||||||
"../api/video:encoded_frame",
|
"../api/video:encoded_frame",
|
||||||
"../api/video:frame_buffer",
|
"../api/video:frame_buffer",
|
||||||
"../api/video:video_rtp_headers",
|
"../api/video:video_rtp_headers",
|
||||||
"../modules/video_coding",
|
"../modules/video_coding",
|
||||||
"../modules/video_coding:frame_helpers",
|
"../modules/video_coding:frame_helpers",
|
||||||
"../modules/video_coding:video_codec_interface",
|
"../modules/video_coding:video_codec_interface",
|
||||||
"../modules/video_coding/timing:inter_frame_delay",
|
"../modules/video_coding/timing:inter_frame_delay_variation_calculator",
|
||||||
"../modules/video_coding/timing:jitter_estimator",
|
"../modules/video_coding/timing:jitter_estimator",
|
||||||
"../modules/video_coding/timing:timing_module",
|
"../modules/video_coding/timing:timing_module",
|
||||||
"../rtc_base:checks",
|
"../rtc_base:checks",
|
||||||
|
|||||||
@ -16,14 +16,16 @@
|
|||||||
|
|
||||||
#include "absl/base/attributes.h"
|
#include "absl/base/attributes.h"
|
||||||
#include "absl/functional/bind_front.h"
|
#include "absl/functional/bind_front.h"
|
||||||
|
#include "absl/types/optional.h"
|
||||||
#include "api/sequence_checker.h"
|
#include "api/sequence_checker.h"
|
||||||
#include "api/task_queue/task_queue_base.h"
|
#include "api/task_queue/task_queue_base.h"
|
||||||
#include "api/units/data_size.h"
|
#include "api/units/data_size.h"
|
||||||
|
#include "api/units/time_delta.h"
|
||||||
#include "api/video/encoded_frame.h"
|
#include "api/video/encoded_frame.h"
|
||||||
#include "api/video/frame_buffer.h"
|
#include "api/video/frame_buffer.h"
|
||||||
#include "api/video/video_content_type.h"
|
#include "api/video/video_content_type.h"
|
||||||
#include "modules/video_coding/frame_helpers.h"
|
#include "modules/video_coding/frame_helpers.h"
|
||||||
#include "modules/video_coding/timing/inter_frame_delay.h"
|
#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
|
||||||
#include "modules/video_coding/timing/jitter_estimator.h"
|
#include "modules/video_coding/timing/jitter_estimator.h"
|
||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
@ -225,10 +227,11 @@ void VideoStreamBufferController::OnFrameReady(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!superframe_delayed_by_retransmission) {
|
if (!superframe_delayed_by_retransmission) {
|
||||||
auto frame_delay = inter_frame_delay_.CalculateDelay(
|
absl::optional<TimeDelta> inter_frame_delay_variation =
|
||||||
first_frame.Timestamp(), receive_time);
|
ifdv_calculator_.Calculate(first_frame.Timestamp(), receive_time);
|
||||||
if (frame_delay) {
|
if (inter_frame_delay_variation) {
|
||||||
jitter_estimator_.UpdateEstimate(*frame_delay, superframe_size);
|
jitter_estimator_.UpdateEstimate(*inter_frame_delay_variation,
|
||||||
|
superframe_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
|
float rtt_mult = protection_mode_ == kProtectionNackFEC ? 0.0 : 1.0;
|
||||||
|
|||||||
@ -18,7 +18,7 @@
|
|||||||
#include "api/video/encoded_frame.h"
|
#include "api/video/encoded_frame.h"
|
||||||
#include "api/video/frame_buffer.h"
|
#include "api/video/frame_buffer.h"
|
||||||
#include "modules/video_coding/include/video_coding_defines.h"
|
#include "modules/video_coding/include/video_coding_defines.h"
|
||||||
#include "modules/video_coding/timing/inter_frame_delay.h"
|
#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
|
||||||
#include "modules/video_coding/timing/jitter_estimator.h"
|
#include "modules/video_coding/timing/jitter_estimator.h"
|
||||||
#include "modules/video_coding/timing/timing.h"
|
#include "modules/video_coding/timing/timing.h"
|
||||||
#include "rtc_base/experiments/rtt_mult_experiment.h"
|
#include "rtc_base/experiments/rtt_mult_experiment.h"
|
||||||
@ -85,7 +85,8 @@ class VideoStreamBufferController {
|
|||||||
RTC_GUARDED_BY(&worker_sequence_checker_);
|
RTC_GUARDED_BY(&worker_sequence_checker_);
|
||||||
|
|
||||||
JitterEstimator jitter_estimator_ RTC_GUARDED_BY(&worker_sequence_checker_);
|
JitterEstimator jitter_estimator_ RTC_GUARDED_BY(&worker_sequence_checker_);
|
||||||
InterFrameDelay inter_frame_delay_ RTC_GUARDED_BY(&worker_sequence_checker_);
|
InterFrameDelayVariationCalculator ifdv_calculator_
|
||||||
|
RTC_GUARDED_BY(&worker_sequence_checker_);
|
||||||
bool keyframe_required_ RTC_GUARDED_BY(&worker_sequence_checker_) = false;
|
bool keyframe_required_ RTC_GUARDED_BY(&worker_sequence_checker_) = false;
|
||||||
std::unique_ptr<FrameBuffer> buffer_
|
std::unique_ptr<FrameBuffer> buffer_
|
||||||
RTC_GUARDED_BY(&worker_sequence_checker_);
|
RTC_GUARDED_BY(&worker_sequence_checker_);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user