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:
Danil Chapovalov 2023-10-26 11:46:02 +02:00 committed by WebRTC LUCI CQ
parent 3f64824b73
commit 6634c91194
10 changed files with 452 additions and 434 deletions

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);
}

View File

@ -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());

View File

@ -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

View File

@ -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);
}

View File

@ -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_;