Refactor AbsoluteCaptureTimeSender and AbsoluteCaptureTimeInterpolator
Removed thread safety: for a low level helper it adds overhead that users may not need. In particular RtpSenderVideo doesn't need it because calls to SendVideo are already synchronized. Added a feature to force producing extension as requested by downstream. Cleanup and document api: Changed rtp_frequency type to int as it has no reason to use uint32_t per style guide Changed absolute_capture_time to NtpTime to clarify both units and offset of the time. NtpTime has trivial conversion to/from uint64_t Documented all the parameters. Cleanup tests. Bug: b/307553606 Change-Id: I0922ca4d3c89f124eeb561742dca79ed5c2327fd Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/325022 Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Reviewed-by: Chen Xing <chxg@google.com> Cr-Commit-Position: refs/heads/main@{#41023}
This commit is contained in:
parent
3f64824b73
commit
6634c91194
@ -15,15 +15,9 @@
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
constexpr Timestamp kInvalidLastReceiveTime = Timestamp::MinusInfinity();
|
||||
} // namespace
|
||||
|
||||
constexpr TimeDelta AbsoluteCaptureTimeInterpolator::kInterpolationMaxInterval;
|
||||
|
||||
AbsoluteCaptureTimeInterpolator::AbsoluteCaptureTimeInterpolator(Clock* clock)
|
||||
: clock_(clock), last_receive_time_(kInvalidLastReceiveTime) {}
|
||||
: clock_(clock) {}
|
||||
|
||||
uint32_t AbsoluteCaptureTimeInterpolator::GetSource(
|
||||
uint32_t ssrc,
|
||||
@ -39,68 +33,59 @@ absl::optional<AbsoluteCaptureTime>
|
||||
AbsoluteCaptureTimeInterpolator::OnReceivePacket(
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
int rtp_clock_frequency_hz,
|
||||
const absl::optional<AbsoluteCaptureTime>& received_extension) {
|
||||
const Timestamp receive_time = clock_->CurrentTime();
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
AbsoluteCaptureTime extension;
|
||||
if (received_extension == absl::nullopt) {
|
||||
if (!ShouldInterpolateExtension(receive_time, source, rtp_timestamp,
|
||||
rtp_clock_frequency)) {
|
||||
last_receive_time_ = kInvalidLastReceiveTime;
|
||||
rtp_clock_frequency_hz)) {
|
||||
last_receive_time_ = Timestamp::MinusInfinity();
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
extension.absolute_capture_timestamp = InterpolateAbsoluteCaptureTimestamp(
|
||||
rtp_timestamp, rtp_clock_frequency, last_rtp_timestamp_,
|
||||
last_absolute_capture_timestamp_);
|
||||
extension.estimated_capture_clock_offset =
|
||||
last_estimated_capture_clock_offset_;
|
||||
return AbsoluteCaptureTime{
|
||||
.absolute_capture_timestamp = InterpolateAbsoluteCaptureTimestamp(
|
||||
rtp_timestamp, rtp_clock_frequency_hz, last_rtp_timestamp_,
|
||||
last_received_extension_.absolute_capture_timestamp),
|
||||
.estimated_capture_clock_offset =
|
||||
last_received_extension_.estimated_capture_clock_offset,
|
||||
};
|
||||
} else {
|
||||
last_source_ = source;
|
||||
last_rtp_timestamp_ = rtp_timestamp;
|
||||
last_rtp_clock_frequency_ = rtp_clock_frequency;
|
||||
last_absolute_capture_timestamp_ =
|
||||
received_extension->absolute_capture_timestamp;
|
||||
last_estimated_capture_clock_offset_ =
|
||||
received_extension->estimated_capture_clock_offset;
|
||||
last_rtp_clock_frequency_hz_ = rtp_clock_frequency_hz;
|
||||
last_received_extension_ = *received_extension;
|
||||
|
||||
last_receive_time_ = receive_time;
|
||||
|
||||
extension = *received_extension;
|
||||
return received_extension;
|
||||
}
|
||||
|
||||
return extension;
|
||||
}
|
||||
|
||||
uint64_t AbsoluteCaptureTimeInterpolator::InterpolateAbsoluteCaptureTimestamp(
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
int rtp_clock_frequency_hz,
|
||||
uint32_t last_rtp_timestamp,
|
||||
uint64_t last_absolute_capture_timestamp) {
|
||||
RTC_DCHECK_GT(rtp_clock_frequency, 0);
|
||||
RTC_DCHECK_GT(rtp_clock_frequency_hz, 0);
|
||||
|
||||
return last_absolute_capture_timestamp +
|
||||
static_cast<int64_t>(
|
||||
rtc::dchecked_cast<uint64_t>(rtp_timestamp - last_rtp_timestamp)
|
||||
<< 32) /
|
||||
rtp_clock_frequency;
|
||||
static_cast<int64_t>(uint64_t{rtp_timestamp - last_rtp_timestamp}
|
||||
<< 32) /
|
||||
rtp_clock_frequency_hz;
|
||||
}
|
||||
|
||||
bool AbsoluteCaptureTimeInterpolator::ShouldInterpolateExtension(
|
||||
Timestamp receive_time,
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency) const {
|
||||
// Shouldn't if we don't have a previously received extension stored.
|
||||
if (last_receive_time_ == kInvalidLastReceiveTime) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Shouldn't if the last received extension is too old.
|
||||
if ((receive_time - last_receive_time_) > kInterpolationMaxInterval) {
|
||||
int rtp_clock_frequency_hz) const {
|
||||
// Shouldn't if the last received extension is not eligible for interpolation,
|
||||
// in particular if we don't have a previously received extension stored.
|
||||
if (receive_time - last_receive_time_ > kInterpolationMaxInterval) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -110,12 +95,12 @@ bool AbsoluteCaptureTimeInterpolator::ShouldInterpolateExtension(
|
||||
}
|
||||
|
||||
// Shouldn't if the RTP clock frequency has changed.
|
||||
if (last_rtp_clock_frequency_ != rtp_clock_frequency) {
|
||||
if (last_rtp_clock_frequency_hz_ != rtp_clock_frequency_hz) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Shouldn't if the RTP clock frequency is invalid.
|
||||
if (rtp_clock_frequency <= 0) {
|
||||
if (rtp_clock_frequency_hz <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -35,8 +35,7 @@ namespace webrtc {
|
||||
//
|
||||
class AbsoluteCaptureTimeInterpolator {
|
||||
public:
|
||||
static constexpr TimeDelta kInterpolationMaxInterval =
|
||||
TimeDelta::Millis(5000);
|
||||
static constexpr TimeDelta kInterpolationMaxInterval = TimeDelta::Seconds(5);
|
||||
|
||||
explicit AbsoluteCaptureTimeInterpolator(Clock* clock);
|
||||
|
||||
@ -49,7 +48,7 @@ class AbsoluteCaptureTimeInterpolator {
|
||||
absl::optional<AbsoluteCaptureTime> OnReceivePacket(
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
int rtp_clock_frequency_hz,
|
||||
const absl::optional<AbsoluteCaptureTime>& received_extension);
|
||||
|
||||
private:
|
||||
@ -57,29 +56,31 @@ class AbsoluteCaptureTimeInterpolator {
|
||||
|
||||
static uint64_t InterpolateAbsoluteCaptureTimestamp(
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
int rtp_clock_frequency_hz,
|
||||
uint32_t last_rtp_timestamp,
|
||||
uint64_t last_absolute_capture_timestamp);
|
||||
|
||||
bool ShouldInterpolateExtension(Timestamp receive_time,
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency) const
|
||||
int rtp_clock_frequency_hz) const
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
Clock* const clock_;
|
||||
|
||||
Mutex mutex_;
|
||||
|
||||
Timestamp last_receive_time_ RTC_GUARDED_BY(mutex_);
|
||||
// Time of the last received header extension eligible for interpolation,
|
||||
// MinusInfinity() if no extension was received, or last received one is
|
||||
// not eligible for interpolation.
|
||||
Timestamp last_receive_time_ RTC_GUARDED_BY(mutex_) =
|
||||
Timestamp::MinusInfinity();
|
||||
|
||||
uint32_t last_source_ RTC_GUARDED_BY(mutex_);
|
||||
uint32_t last_rtp_timestamp_ RTC_GUARDED_BY(mutex_);
|
||||
uint32_t last_rtp_clock_frequency_ RTC_GUARDED_BY(mutex_);
|
||||
uint64_t last_absolute_capture_timestamp_ RTC_GUARDED_BY(mutex_);
|
||||
absl::optional<int64_t> last_estimated_capture_clock_offset_
|
||||
RTC_GUARDED_BY(mutex_);
|
||||
}; // AbsoluteCaptureTimeInterpolator
|
||||
int last_rtp_clock_frequency_hz_ RTC_GUARDED_BY(mutex_);
|
||||
AbsoluteCaptureTime last_received_extension_ RTC_GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -32,13 +32,13 @@ TEST(AbsoluteCaptureTimeInterpolatorTest, GetSourceWithCsrcs) {
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest, ReceiveExtensionReturnsExtension) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9020), absl::nullopt};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9020),
|
||||
absl::nullopt};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
@ -55,299 +55,291 @@ TEST(AbsoluteCaptureTimeInterpolatorTest, ReceiveExtensionReturnsExtension) {
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest,
|
||||
ReceiveNoExtensionReturnsNoExtension) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp1,
|
||||
kRtpClockFrequency, kExtension1),
|
||||
absl::nullopt);
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest, InterpolateLaterPacketArrivingLater) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
absl::optional<AbsoluteCaptureTime> extension = interpolator.OnReceivePacket(
|
||||
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
absl::optional<AbsoluteCaptureTime> extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 20);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) + 20);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
|
||||
extension = interpolator.OnReceivePacket(kSource, kRtpTimestamp2,
|
||||
kRtpClockFrequency, kExtension2);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 40);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) + 40);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest,
|
||||
InterpolateEarlierPacketArrivingLater) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 - 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 - 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
absl::optional<AbsoluteCaptureTime> extension = interpolator.OnReceivePacket(
|
||||
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
absl::optional<AbsoluteCaptureTime> extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 20);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) - 20);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
|
||||
extension = interpolator.OnReceivePacket(kSource, kRtpTimestamp2,
|
||||
kRtpClockFrequency, kExtension2);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 40);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) - 40);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest,
|
||||
InterpolateLaterPacketArrivingLaterWithRtpTimestampWrapAround) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr uint32_t kRtpTimestamp0 = ~uint32_t{0} - 79;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = uint32_t{0} - 80;
|
||||
constexpr uint32_t kRtpTimestamp1 = 1280 - 80;
|
||||
constexpr uint32_t kRtpTimestamp2 = 2560 - 80;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
absl::optional<AbsoluteCaptureTime> extension = interpolator.OnReceivePacket(
|
||||
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
absl::optional<AbsoluteCaptureTime> extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 20);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) + 20);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
|
||||
extension = interpolator.OnReceivePacket(kSource, kRtpTimestamp2,
|
||||
kRtpClockFrequency, kExtension2);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 40);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) + 40);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest,
|
||||
InterpolateEarlierPacketArrivingLaterWithRtpTimestampWrapAround) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 799;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 - 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 - 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
absl::optional<AbsoluteCaptureTime> extension = interpolator.OnReceivePacket(
|
||||
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
absl::optional<AbsoluteCaptureTime> extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 20);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) - 20);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
|
||||
extension = interpolator.OnReceivePacket(kSource, kRtpTimestamp2,
|
||||
kRtpClockFrequency, kExtension2);
|
||||
EXPECT_TRUE(extension.has_value());
|
||||
extension =
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt);
|
||||
ASSERT_TRUE(extension.has_value());
|
||||
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
|
||||
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 40);
|
||||
UQ32x32ToInt64Ms(kExtension.absolute_capture_timestamp) - 40);
|
||||
EXPECT_EQ(extension->estimated_capture_clock_offset,
|
||||
kExtension0->estimated_capture_clock_offset);
|
||||
kExtension.estimated_capture_clock_offset);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest, SkipInterpolateIfTooLate) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp1 + 1280;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
clock.AdvanceTime(AbsoluteCaptureTimeInterpolator::kInterpolationMaxInterval);
|
||||
|
||||
EXPECT_TRUE(interpolator
|
||||
.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1)
|
||||
.has_value());
|
||||
EXPECT_NE(
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
|
||||
clock.AdvanceTimeMilliseconds(1);
|
||||
clock.AdvanceTime(TimeDelta::Millis(1));
|
||||
|
||||
EXPECT_FALSE(interpolator
|
||||
.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2)
|
||||
.has_value());
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest, SkipInterpolateIfSourceChanged) {
|
||||
constexpr uint32_t kSource0 = 1337;
|
||||
constexpr uint32_t kSource1 = 1338;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource0, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
EXPECT_FALSE(interpolator
|
||||
.OnReceivePacket(kSource1, kRtpTimestamp1,
|
||||
kRtpClockFrequency, kExtension1)
|
||||
.has_value());
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource1, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest,
|
||||
SkipInterpolateIfRtpClockFrequencyChanged) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency0 = 64000;
|
||||
constexpr uint32_t kRtpClockFrequency1 = 32000;
|
||||
constexpr int kRtpClockFrequency0 = 64'000;
|
||||
constexpr int kRtpClockFrequency1 = 32'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 640;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency0, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency0, kExtension),
|
||||
kExtension);
|
||||
|
||||
EXPECT_FALSE(interpolator
|
||||
.OnReceivePacket(kSource, kRtpTimestamp1,
|
||||
kRtpClockFrequency1, kExtension1)
|
||||
.has_value());
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency1,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest,
|
||||
SkipInterpolateIfRtpClockFrequencyIsInvalid) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 0;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 640;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource, kRtpTimestamp0,
|
||||
/*rtp_clock_frequency_hz=*/0, kExtension),
|
||||
kExtension);
|
||||
|
||||
EXPECT_FALSE(interpolator
|
||||
.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1)
|
||||
.has_value());
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource, kRtpTimestamp1,
|
||||
/*rtp_clock_frequency_hz=*/0,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeInterpolatorTest, SkipInterpolateIsSticky) {
|
||||
constexpr uint32_t kSource0 = 1337;
|
||||
constexpr uint32_t kSource1 = 1338;
|
||||
constexpr uint32_t kSource2 = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp1 + 1280;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 = absl::nullopt;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 = absl::nullopt;
|
||||
const AbsoluteCaptureTime kExtension = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeInterpolator interpolator(&clock);
|
||||
|
||||
EXPECT_EQ(interpolator.OnReceivePacket(kSource0, kRtpTimestamp0,
|
||||
kRtpClockFrequency, kExtension0),
|
||||
kExtension0);
|
||||
kRtpClockFrequency, kExtension),
|
||||
kExtension);
|
||||
|
||||
EXPECT_FALSE(interpolator
|
||||
.OnReceivePacket(kSource1, kRtpTimestamp1,
|
||||
kRtpClockFrequency, kExtension1)
|
||||
.has_value());
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource1, kRtpTimestamp1, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_FALSE(interpolator
|
||||
.OnReceivePacket(kSource2, kRtpTimestamp2,
|
||||
kRtpClockFrequency, kExtension2)
|
||||
.has_value());
|
||||
EXPECT_EQ(
|
||||
interpolator.OnReceivePacket(kSource0, kRtpTimestamp2, kRtpClockFrequency,
|
||||
/*received_extension=*/absl::nullopt),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -16,14 +16,6 @@
|
||||
#include "system_wrappers/include/ntp_time.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
|
||||
constexpr Timestamp kInvalidLastSendTime = Timestamp::MinusInfinity();
|
||||
|
||||
} // namespace
|
||||
|
||||
constexpr TimeDelta AbsoluteCaptureTimeSender::kInterpolationMaxInterval;
|
||||
constexpr TimeDelta AbsoluteCaptureTimeSender::kInterpolationMaxError;
|
||||
|
||||
static_assert(
|
||||
AbsoluteCaptureTimeInterpolator::kInterpolationMaxInterval >=
|
||||
@ -31,7 +23,7 @@ static_assert(
|
||||
"Receivers should be as willing to interpolate timestamps as senders.");
|
||||
|
||||
AbsoluteCaptureTimeSender::AbsoluteCaptureTimeSender(Clock* clock)
|
||||
: clock_(clock), last_send_time_(kInvalidLastSendTime) {}
|
||||
: clock_(clock) {}
|
||||
|
||||
uint32_t AbsoluteCaptureTimeSender::GetSource(
|
||||
uint32_t ssrc,
|
||||
@ -45,44 +37,48 @@ absl::optional<AbsoluteCaptureTime> AbsoluteCaptureTimeSender::OnSendPacket(
|
||||
uint32_t rtp_clock_frequency,
|
||||
uint64_t absolute_capture_timestamp,
|
||||
absl::optional<int64_t> estimated_capture_clock_offset) {
|
||||
const Timestamp send_time = clock_->CurrentTime();
|
||||
return OnSendPacket(source, rtp_timestamp, rtp_clock_frequency,
|
||||
NtpTime(absolute_capture_timestamp),
|
||||
estimated_capture_clock_offset, /*force=*/false);
|
||||
}
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
if (!ShouldSendExtension(send_time, source, rtp_timestamp,
|
||||
rtp_clock_frequency, absolute_capture_timestamp,
|
||||
estimated_capture_clock_offset)) {
|
||||
absl::optional<AbsoluteCaptureTime> AbsoluteCaptureTimeSender::OnSendPacket(
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
int rtp_clock_frequency_hz,
|
||||
NtpTime absolute_capture_time,
|
||||
absl::optional<int64_t> estimated_capture_clock_offset,
|
||||
bool force) {
|
||||
Timestamp send_time = clock_->CurrentTime();
|
||||
if (!(force || ShouldSendExtension(
|
||||
send_time, source, rtp_timestamp, rtp_clock_frequency_hz,
|
||||
absolute_capture_time, estimated_capture_clock_offset))) {
|
||||
return absl::nullopt;
|
||||
}
|
||||
|
||||
last_source_ = source;
|
||||
last_rtp_timestamp_ = rtp_timestamp;
|
||||
last_rtp_clock_frequency_ = rtp_clock_frequency;
|
||||
last_absolute_capture_timestamp_ = absolute_capture_timestamp;
|
||||
last_rtp_clock_frequency_hz_ = rtp_clock_frequency_hz;
|
||||
last_absolute_capture_time_ = absolute_capture_time;
|
||||
last_estimated_capture_clock_offset_ = estimated_capture_clock_offset;
|
||||
|
||||
last_send_time_ = send_time;
|
||||
|
||||
AbsoluteCaptureTime extension;
|
||||
extension.absolute_capture_timestamp = absolute_capture_timestamp;
|
||||
extension.estimated_capture_clock_offset = estimated_capture_clock_offset;
|
||||
return extension;
|
||||
return AbsoluteCaptureTime{
|
||||
.absolute_capture_timestamp = uint64_t{absolute_capture_time},
|
||||
.estimated_capture_clock_offset = estimated_capture_clock_offset,
|
||||
};
|
||||
}
|
||||
|
||||
bool AbsoluteCaptureTimeSender::ShouldSendExtension(
|
||||
Timestamp send_time,
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
uint64_t absolute_capture_timestamp,
|
||||
int rtp_clock_frequency_hz,
|
||||
NtpTime absolute_capture_time,
|
||||
absl::optional<int64_t> estimated_capture_clock_offset) const {
|
||||
// Should if we've never sent anything before.
|
||||
if (last_send_time_ == kInvalidLastSendTime) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should if the last sent extension is too old.
|
||||
if ((send_time - last_send_time_) > kInterpolationMaxInterval) {
|
||||
// Should if the last sent extension is too old, in particular if we've never
|
||||
// sent anything before.
|
||||
if (send_time - last_send_time_ > kInterpolationMaxInterval) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -92,12 +88,12 @@ bool AbsoluteCaptureTimeSender::ShouldSendExtension(
|
||||
}
|
||||
|
||||
// Should if the RTP clock frequency has changed.
|
||||
if (last_rtp_clock_frequency_ != rtp_clock_frequency) {
|
||||
if (last_rtp_clock_frequency_hz_ != rtp_clock_frequency_hz) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Should if the RTP clock frequency is invalid.
|
||||
if (rtp_clock_frequency <= 0) {
|
||||
if (rtp_clock_frequency_hz <= 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -109,8 +105,9 @@ bool AbsoluteCaptureTimeSender::ShouldSendExtension(
|
||||
// Should if interpolation would introduce too much error.
|
||||
const uint64_t interpolated_absolute_capture_timestamp =
|
||||
AbsoluteCaptureTimeInterpolator::InterpolateAbsoluteCaptureTimestamp(
|
||||
rtp_timestamp, rtp_clock_frequency, last_rtp_timestamp_,
|
||||
last_absolute_capture_timestamp_);
|
||||
rtp_timestamp, rtp_clock_frequency_hz, last_rtp_timestamp_,
|
||||
uint64_t{last_absolute_capture_time_});
|
||||
const uint64_t absolute_capture_timestamp = uint64_t{absolute_capture_time};
|
||||
const int64_t interpolation_error_ms = UQ32x32ToInt64Ms(std::min(
|
||||
interpolated_absolute_capture_timestamp - absolute_capture_timestamp,
|
||||
absolute_capture_timestamp - interpolated_absolute_capture_timestamp));
|
||||
|
||||
@ -15,9 +15,8 @@
|
||||
#include "api/rtp_headers.h"
|
||||
#include "api/units/time_delta.h"
|
||||
#include "api/units/timestamp.h"
|
||||
#include "rtc_base/synchronization/mutex.h"
|
||||
#include "rtc_base/thread_annotations.h"
|
||||
#include "system_wrappers/include/clock.h"
|
||||
#include "system_wrappers/include/ntp_time.h"
|
||||
|
||||
namespace webrtc {
|
||||
|
||||
@ -40,8 +39,7 @@ namespace webrtc {
|
||||
//
|
||||
class AbsoluteCaptureTimeSender {
|
||||
public:
|
||||
static constexpr TimeDelta kInterpolationMaxInterval =
|
||||
TimeDelta::Millis(1000);
|
||||
static constexpr TimeDelta kInterpolationMaxInterval = TimeDelta::Seconds(1);
|
||||
static constexpr TimeDelta kInterpolationMaxError = TimeDelta::Millis(1);
|
||||
|
||||
explicit AbsoluteCaptureTimeSender(Clock* clock);
|
||||
@ -50,9 +48,34 @@ class AbsoluteCaptureTimeSender {
|
||||
static uint32_t GetSource(uint32_t ssrc,
|
||||
rtc::ArrayView<const uint32_t> csrcs);
|
||||
|
||||
// Returns value to write into AbsoluteCaptureTime RTP header extension to be
|
||||
// sent, or `absl::nullopt` if the header extension shouldn't be attached to
|
||||
// the outgoing packet.
|
||||
//
|
||||
// - `source` - id of the capture system.
|
||||
// - `rtp_timestamp` - capture time represented as rtp timestamp in the
|
||||
// outgoing packet
|
||||
// - `rtp_clock_frequency_hz` - description of the `rtp_timestamp` units -
|
||||
// `rtp_timetamp` delta of `rtp_clock_freqnecy_hz` represents 1 second.
|
||||
// - `absolute_capture_time` - time when a frame was captured by the capture
|
||||
// system.
|
||||
// - `estimated_capture_clock_offset` - estimated offset between capture
|
||||
// system clock and local `clock` passed as the AbsoluteCaptureTimeSender
|
||||
// construction paramter. Uses the same units as `absolute_capture_time`,
|
||||
// i.e. delta of 2^32 represents 1 second. See AbsoluteCaptureTime type
|
||||
// comments for more details.
|
||||
// - `force` - when set to true, OnSendPacket is forced to return non-nullopt.
|
||||
absl::optional<AbsoluteCaptureTime> OnSendPacket(
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
int rtp_clock_frequency_hz,
|
||||
NtpTime absolute_capture_time,
|
||||
absl::optional<int64_t> estimated_capture_clock_offset,
|
||||
bool force = false);
|
||||
|
||||
// Returns a header extension to be sent, or `absl::nullopt` if the header
|
||||
// extension shouldn't be sent.
|
||||
absl::optional<AbsoluteCaptureTime> OnSendPacket(
|
||||
[[deprecated]] absl::optional<AbsoluteCaptureTime> OnSendPacket(
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
@ -64,24 +87,20 @@ class AbsoluteCaptureTimeSender {
|
||||
Timestamp send_time,
|
||||
uint32_t source,
|
||||
uint32_t rtp_timestamp,
|
||||
uint32_t rtp_clock_frequency,
|
||||
uint64_t absolute_capture_timestamp,
|
||||
absl::optional<int64_t> estimated_capture_clock_offset) const
|
||||
RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
int rtp_clock_frequency_hz,
|
||||
NtpTime absolute_capture_time,
|
||||
absl::optional<int64_t> estimated_capture_clock_offset) const;
|
||||
|
||||
Clock* const clock_;
|
||||
|
||||
Mutex mutex_;
|
||||
Timestamp last_send_time_ = Timestamp::MinusInfinity();
|
||||
|
||||
Timestamp last_send_time_ RTC_GUARDED_BY(mutex_);
|
||||
|
||||
uint32_t last_source_ RTC_GUARDED_BY(mutex_);
|
||||
uint32_t last_rtp_timestamp_ RTC_GUARDED_BY(mutex_);
|
||||
uint32_t last_rtp_clock_frequency_ RTC_GUARDED_BY(mutex_);
|
||||
uint64_t last_absolute_capture_timestamp_ RTC_GUARDED_BY(mutex_);
|
||||
absl::optional<int64_t> last_estimated_capture_clock_offset_
|
||||
RTC_GUARDED_BY(mutex_);
|
||||
}; // AbsoluteCaptureTimeSender
|
||||
uint32_t last_source_;
|
||||
uint32_t last_rtp_timestamp_;
|
||||
int last_rtp_clock_frequency_hz_;
|
||||
NtpTime last_absolute_capture_time_;
|
||||
absl::optional<int64_t> last_estimated_capture_clock_offset_;
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ namespace webrtc {
|
||||
TEST(AbsoluteCaptureTimeSenderTest, GetSourceWithoutCsrcs) {
|
||||
constexpr uint32_t kSsrc = 12;
|
||||
|
||||
EXPECT_EQ(AbsoluteCaptureTimeSender::GetSource(kSsrc, nullptr), kSsrc);
|
||||
EXPECT_EQ(AbsoluteCaptureTimeSender::GetSource(kSsrc, {}), kSsrc);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, GetSourceWithCsrcs) {
|
||||
@ -31,343 +31,368 @@ TEST(AbsoluteCaptureTimeSenderTest, GetSourceWithCsrcs) {
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, InterpolateLaterPacketSentLater) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, InterpolateEarlierPacketSentLater) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 - 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 - 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 - 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 - 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 - 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 - 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest,
|
||||
InterpolateLaterPacketSentLaterWithRtpTimestampWrapAround) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr uint32_t kRtpTimestamp0 = ~uint32_t{0} - 79;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = uint32_t{0} - 80;
|
||||
constexpr uint32_t kRtpTimestamp1 = 1280 - 80;
|
||||
constexpr uint32_t kRtpTimestamp2 = 2560 - 80;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest,
|
||||
InterpolateEarlierPacketSentLaterWithRtpTimestampWrapAround) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 799;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 - 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 - 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 - 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 - 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 - 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 - 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, SkipInterpolateIfTooLate) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
clock.AdvanceTime(AbsoluteCaptureTimeSender::kInterpolationMaxInterval);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
|
||||
clock.AdvanceTimeMicroseconds(1);
|
||||
clock.AdvanceTime(TimeDelta::Millis(1));
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
kExtension2);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, SkipInterpolateIfSourceChanged) {
|
||||
constexpr uint32_t kSource0 = 1337;
|
||||
constexpr uint32_t kSource1 = 1338;
|
||||
constexpr uint32_t kSource2 = 1338;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource0, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource1, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
kExtension1);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource2, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource1, kRtpTimestamp2, kRtpClockFrequency,
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, SkipInterpolateWhenForced) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset,
|
||||
/*force=*/true),
|
||||
kExtension1);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset,
|
||||
/*force=*/false),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest, SkipInterpolateIfRtpClockFrequencyChanged) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency0 = 64000;
|
||||
constexpr uint32_t kRtpClockFrequency1 = 32000;
|
||||
constexpr uint32_t kRtpClockFrequency2 = 32000;
|
||||
constexpr int kRtpClockFrequency0 = 64'000;
|
||||
constexpr int kRtpClockFrequency1 = 32'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 640;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 1280;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency0,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency1,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
kExtension1);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency2,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency1,
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest,
|
||||
SkipInterpolateIfRtpClockFrequencyIsInvalid) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency0 = 0;
|
||||
constexpr uint32_t kRtpClockFrequency1 = 0;
|
||||
constexpr uint32_t kRtpClockFrequency2 = 0;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), Int64MsToQ32x32(-350)};
|
||||
constexpr int kRtpClockFrequency = 0;
|
||||
constexpr uint32_t kRtpTimestamp = 1020300000;
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency0,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp, kRtpClockFrequency,
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency1,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp, kRtpClockFrequency,
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
kExtension1);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency2,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp, kRtpClockFrequency,
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
kExtension2);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest,
|
||||
SkipInterpolateIfEstimatedCaptureClockOffsetChanged) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 20), Int64MsToQ32x32(370)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000 + 40), absl::nullopt};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {Int64MsToUQ32x32(9000 + 20),
|
||||
Int64MsToQ32x32(370)};
|
||||
const AbsoluteCaptureTime kExtension2 = {Int64MsToUQ32x32(9000 + 40),
|
||||
absl::nullopt};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
kExtension1);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
kExtension2);
|
||||
}
|
||||
|
||||
TEST(AbsoluteCaptureTimeSenderTest,
|
||||
SkipInterpolateIfTooMuchInterpolationError) {
|
||||
constexpr uint32_t kSource = 1337;
|
||||
constexpr uint32_t kRtpClockFrequency = 64000;
|
||||
constexpr int kRtpClockFrequency = 64'000;
|
||||
constexpr uint32_t kRtpTimestamp0 = 1020300000;
|
||||
constexpr uint32_t kRtpTimestamp1 = kRtpTimestamp0 + 1280;
|
||||
constexpr uint32_t kRtpTimestamp2 = kRtpTimestamp0 + 2560;
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension0 =
|
||||
AbsoluteCaptureTime{Int64MsToUQ32x32(9000), Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension1 =
|
||||
AbsoluteCaptureTime{
|
||||
Int64MsToUQ32x32(
|
||||
9000 + 20 +
|
||||
AbsoluteCaptureTimeSender::kInterpolationMaxError.ms()),
|
||||
Int64MsToQ32x32(-350)};
|
||||
static const absl::optional<AbsoluteCaptureTime> kExtension2 =
|
||||
AbsoluteCaptureTime{
|
||||
Int64MsToUQ32x32(
|
||||
9000 + 40 +
|
||||
AbsoluteCaptureTimeSender::kInterpolationMaxError.ms() + 1),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension0 = {Int64MsToUQ32x32(9000),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension1 = {
|
||||
Int64MsToUQ32x32(9000 + 20 +
|
||||
AbsoluteCaptureTimeSender::kInterpolationMaxError.ms()),
|
||||
Int64MsToQ32x32(-350)};
|
||||
const AbsoluteCaptureTime kExtension2 = {
|
||||
Int64MsToUQ32x32(9000 + 40 +
|
||||
AbsoluteCaptureTimeSender::kInterpolationMaxError.ms() +
|
||||
1),
|
||||
Int64MsToQ32x32(-350)};
|
||||
|
||||
SimulatedClock clock(0);
|
||||
AbsoluteCaptureTimeSender sender(&clock);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
|
||||
kExtension0->absolute_capture_timestamp,
|
||||
kExtension0->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension0.absolute_capture_timestamp),
|
||||
kExtension0.estimated_capture_clock_offset),
|
||||
kExtension0);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
|
||||
kExtension1->absolute_capture_timestamp,
|
||||
kExtension1->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension1.absolute_capture_timestamp),
|
||||
kExtension1.estimated_capture_clock_offset),
|
||||
absl::nullopt);
|
||||
|
||||
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
|
||||
kExtension2->absolute_capture_timestamp,
|
||||
kExtension2->estimated_capture_clock_offset),
|
||||
NtpTime(kExtension2.absolute_capture_timestamp),
|
||||
kExtension2.estimated_capture_clock_offset),
|
||||
kExtension2);
|
||||
}
|
||||
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "modules/rtp_rtcp/source/time_util.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "rtc_base/trace_event.h"
|
||||
#include "system_wrappers/include/ntp_time.h"
|
||||
|
||||
@ -92,7 +93,7 @@ int32_t RTPSenderAudio::RegisterAudioPayload(absl::string_view payload_name,
|
||||
return 0;
|
||||
} else if (payload_name == "audio") {
|
||||
MutexLock lock(&send_audio_mutex_);
|
||||
encoder_rtp_timestamp_frequency_ = frequency;
|
||||
encoder_rtp_timestamp_frequency_ = rtc::dchecked_cast<int>(frequency);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
@ -154,11 +155,22 @@ bool RTPSenderAudio::SendAudio(const RtpAudioFrame& frame) {
|
||||
// updates, with a value of 50 ms RECOMMENDED.
|
||||
constexpr int kDtmfIntervalTimeMs = 50;
|
||||
uint32_t dtmf_payload_freq = 0;
|
||||
absl::optional<uint32_t> encoder_rtp_timestamp_frequency;
|
||||
absl::optional<AbsoluteCaptureTime> absolute_capture_time;
|
||||
{
|
||||
MutexLock lock(&send_audio_mutex_);
|
||||
dtmf_payload_freq = dtmf_payload_freq_;
|
||||
encoder_rtp_timestamp_frequency = encoder_rtp_timestamp_frequency_;
|
||||
if (frame.capture_time.has_value()) {
|
||||
// Send absolute capture time periodically in order to optimize and save
|
||||
// network traffic. Missing absolute capture times can be interpolated on
|
||||
// the receiving end if sending intervals are small enough.
|
||||
absolute_capture_time = absolute_capture_time_sender_.OnSendPacket(
|
||||
rtp_sender_->SSRC(), frame.rtp_timestamp,
|
||||
// Replace missing value with 0 (invalid frequency), this will trigger
|
||||
// absolute capture time sending.
|
||||
encoder_rtp_timestamp_frequency_.value_or(0),
|
||||
clock_->ConvertTimestampToNtpTime(*frame.capture_time),
|
||||
/*estimated_capture_clock_offset=*/0);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we have pending DTMFs to send
|
||||
@ -252,25 +264,10 @@ bool RTPSenderAudio::SendAudio(const RtpAudioFrame& frame) {
|
||||
frame.type == AudioFrameType::kAudioFrameSpeech,
|
||||
frame.audio_level_dbov.value_or(127));
|
||||
|
||||
if (frame.capture_time.has_value()) {
|
||||
// Send absolute capture time periodically in order to optimize and save
|
||||
// network traffic. Missing absolute capture times can be interpolated on
|
||||
// the receiving end if sending intervals are small enough.
|
||||
auto absolute_capture_time = absolute_capture_time_sender_.OnSendPacket(
|
||||
AbsoluteCaptureTimeSender::GetSource(packet->Ssrc(), packet->Csrcs()),
|
||||
packet->Timestamp(),
|
||||
// Replace missing value with 0 (invalid frequency), this will trigger
|
||||
// absolute capture time sending.
|
||||
encoder_rtp_timestamp_frequency.value_or(0),
|
||||
static_cast<uint64_t>(
|
||||
clock_->ConvertTimestampToNtpTime(*frame.capture_time)),
|
||||
/*estimated_capture_clock_offset=*/0);
|
||||
if (absolute_capture_time) {
|
||||
// It also checks that extension was registered during SDP negotiation. If
|
||||
// not then setter won't do anything.
|
||||
packet->SetExtension<AbsoluteCaptureTimeExtension>(
|
||||
*absolute_capture_time);
|
||||
}
|
||||
if (absolute_capture_time.has_value()) {
|
||||
// It also checks that extension was registered during SDP negotiation. If
|
||||
// not then setter won't do anything.
|
||||
packet->SetExtension<AbsoluteCaptureTimeExtension>(*absolute_capture_time);
|
||||
}
|
||||
|
||||
uint8_t* payload = packet->AllocatePayload(frame.payload.size());
|
||||
|
||||
@ -104,10 +104,11 @@ class RTPSenderAudio {
|
||||
|
||||
OneTimeEvent first_packet_sent_;
|
||||
|
||||
absl::optional<uint32_t> encoder_rtp_timestamp_frequency_
|
||||
absl::optional<int> encoder_rtp_timestamp_frequency_
|
||||
RTC_GUARDED_BY(send_audio_mutex_);
|
||||
|
||||
AbsoluteCaptureTimeSender absolute_capture_time_sender_;
|
||||
AbsoluteCaptureTimeSender absolute_capture_time_sender_
|
||||
RTC_GUARDED_BY(send_audio_mutex_);
|
||||
};
|
||||
|
||||
} // namespace webrtc
|
||||
|
||||
@ -548,10 +548,10 @@ bool RTPSenderVideo::SendVideo(int payload_type,
|
||||
if (video_header.absolute_capture_time.has_value()) {
|
||||
video_header.absolute_capture_time =
|
||||
absolute_capture_time_sender_.OnSendPacket(
|
||||
AbsoluteCaptureTimeSender::GetSource(single_packet->Ssrc(),
|
||||
single_packet->Csrcs()),
|
||||
AbsoluteCaptureTimeSender::GetSource(single_packet->Ssrc(), csrcs),
|
||||
single_packet->Timestamp(), kVideoPayloadTypeFrequency,
|
||||
video_header.absolute_capture_time->absolute_capture_timestamp,
|
||||
NtpTime(
|
||||
video_header.absolute_capture_time->absolute_capture_timestamp),
|
||||
video_header.absolute_capture_time->estimated_capture_clock_offset);
|
||||
}
|
||||
|
||||
|
||||
@ -244,7 +244,8 @@ class RTPSenderVideo : public RTPVideoFrameSenderInterface {
|
||||
// Set to true if the generic descriptor should be authenticated.
|
||||
const bool generic_descriptor_auth_experiment_;
|
||||
|
||||
AbsoluteCaptureTimeSender absolute_capture_time_sender_;
|
||||
AbsoluteCaptureTimeSender absolute_capture_time_sender_
|
||||
RTC_GUARDED_BY(send_checker_);
|
||||
// Tracks updates to the active decode targets and decides when active decode
|
||||
// targets bitmask should be attached to the dependency descriptor.
|
||||
ActiveDecodeTargetsHelper active_decode_targets_tracker_;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user