Add helper classes to send and receive abs-capture-time extensions.

This change adds helper classes to manipulate Absolute Capture Time header extensions. Both classes support the "timestamp interpolation" optimization.

Bug: webrtc:10739
Change-Id: I08eff46eb8910842a6dbaa3288b976004fabe1c7
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/149801
Commit-Queue: Chen Xing <chxg@google.com>
Reviewed-by: Erik Språng <sprang@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#28936}
This commit is contained in:
Chen Xing 2019-08-22 10:05:01 +02:00 committed by Commit Bot
parent 9fd2908f2e
commit 05f8f1d273
7 changed files with 1260 additions and 0 deletions

View File

@ -131,6 +131,10 @@ rtc_static_library("rtp_rtcp") {
"include/rtp_header_parser.h",
"include/rtp_rtcp.h",
"include/ulpfec_receiver.h",
"source/absolute_capture_time_receiver.cc",
"source/absolute_capture_time_receiver.h",
"source/absolute_capture_time_sender.cc",
"source/absolute_capture_time_sender.h",
"source/dtmf_queue.cc",
"source/dtmf_queue.h",
"source/fec_private_tables_bursty.cc",
@ -224,6 +228,8 @@ rtc_static_library("rtp_rtcp") {
"../../api/rtc_event_log",
"../../api/transport:field_trial_based_config",
"../../api/transport:webrtc_key_value_config",
"../../api/units:time_delta",
"../../api/units:timestamp",
"../../api/video:video_bitrate_allocation",
"../../api/video:video_bitrate_allocator",
"../../api/video:video_frame",
@ -385,6 +391,8 @@ if (rtc_include_tests) {
testonly = true
sources = [
"source/absolute_capture_time_receiver_unittest.cc",
"source/absolute_capture_time_sender_unittest.cc",
"source/byte_io_unittest.cc",
"source/fec_private_tables_bursty_unittest.cc",
"source/flexfec_header_reader_writer_unittest.cc",

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/rtp_rtcp/source/absolute_capture_time_receiver.h"
#include <limits>
#include "rtc_base/checks.h"
namespace webrtc {
namespace {
constexpr Timestamp kInvalidLastReceiveTime = Timestamp::MinusInfinity();
} // namespace
constexpr TimeDelta AbsoluteCaptureTimeReceiver::kInterpolationMaxInterval;
AbsoluteCaptureTimeReceiver::AbsoluteCaptureTimeReceiver(Clock* clock)
: clock_(clock),
remote_to_local_clock_offset_(absl::nullopt),
last_receive_time_(kInvalidLastReceiveTime) {}
uint32_t AbsoluteCaptureTimeReceiver::GetSource(
uint32_t ssrc,
rtc::ArrayView<const uint32_t> csrcs) {
if (csrcs.empty()) {
return ssrc;
}
return csrcs[0];
}
void AbsoluteCaptureTimeReceiver::SetRemoteToLocalClockOffset(
absl::optional<int64_t> value_q32x32) {
rtc::CritScope cs(&crit_);
remote_to_local_clock_offset_ = value_q32x32;
}
absl::optional<AbsoluteCaptureTime>
AbsoluteCaptureTimeReceiver::OnReceivePacket(
uint32_t source,
uint32_t rtp_timestamp,
uint32_t rtp_clock_frequency,
const absl::optional<AbsoluteCaptureTime>& received_extension) {
const Timestamp receive_time = clock_->CurrentTime();
rtc::CritScope cs(&crit_);
AbsoluteCaptureTime extension;
if (received_extension == absl::nullopt) {
if (!ShouldInterpolateExtension(receive_time, source, rtp_timestamp,
rtp_clock_frequency)) {
last_receive_time_ = kInvalidLastReceiveTime;
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_;
} 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_receive_time_ = receive_time;
extension = *received_extension;
}
extension.estimated_capture_clock_offset = AdjustEstimatedCaptureClockOffset(
extension.estimated_capture_clock_offset);
return extension;
}
uint64_t AbsoluteCaptureTimeReceiver::InterpolateAbsoluteCaptureTimestamp(
uint32_t rtp_timestamp,
uint32_t rtp_clock_frequency,
uint32_t last_rtp_timestamp,
uint64_t last_absolute_capture_timestamp) {
RTC_DCHECK_GT(rtp_clock_frequency, 0);
return last_absolute_capture_timestamp +
static_cast<int64_t>(
rtc::dchecked_cast<uint64_t>(rtp_timestamp - last_rtp_timestamp)
<< 32) /
rtp_clock_frequency;
}
bool AbsoluteCaptureTimeReceiver::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) {
return false;
}
// Shouldn't if the source has changed.
if (last_source_ != source) {
return false;
}
// Shouldn't if the RTP clock frequency has changed.
if (last_rtp_clock_frequency_ != rtp_clock_frequency) {
return false;
}
// Shouldn't if the RTP clock frequency is invalid.
if (rtp_clock_frequency <= 0) {
return false;
}
return true;
}
absl::optional<int64_t>
AbsoluteCaptureTimeReceiver::AdjustEstimatedCaptureClockOffset(
absl::optional<int64_t> received_value) const {
if (received_value == absl::nullopt ||
remote_to_local_clock_offset_ == absl::nullopt) {
return absl::nullopt;
}
// Do calculations as "unsigned" to make overflows deterministic.
return static_cast<uint64_t>(*received_value) +
static_cast<uint64_t>(*remote_to_local_clock_offset_);
}
} // namespace webrtc

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_RTP_RTCP_SOURCE_ABSOLUTE_CAPTURE_TIME_RECEIVER_H_
#define MODULES_RTP_RTCP_SOURCE_ABSOLUTE_CAPTURE_TIME_RECEIVER_H_
#include "api/array_view.h"
#include "api/rtp_headers.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/thread_annotations.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
//
// Helper class for receiving the |AbsoluteCaptureTime| header extension.
//
// Supports the "timestamp interpolation" optimization:
// A receiver SHOULD memorize the capture system (i.e. CSRC/SSRC), capture
// timestamp, and RTP timestamp of the most recently received abs-capture-time
// packet on each received stream. It can then use that information, in
// combination with RTP timestamps of packets without abs-capture-time, to
// extrapolate missing capture timestamps.
//
// See: https://webrtc.org/experiments/rtp-hdrext/abs-capture-time/
//
class AbsoluteCaptureTimeReceiver {
public:
static constexpr TimeDelta kInterpolationMaxInterval =
TimeDelta::Millis<5000>();
explicit AbsoluteCaptureTimeReceiver(Clock* clock);
// Returns the source (i.e. SSRC or CSRC) of the capture system.
static uint32_t GetSource(uint32_t ssrc,
rtc::ArrayView<const uint32_t> csrcs);
// Sets the NTP clock offset between the sender system (which may be different
// from the capture system) and the local system. This information is normally
// provided by passing half the value of the Round-Trip Time estimation given
// by RTCP sender reports (see DLSR/DLRR).
//
// Note that the value must be in Q32.32-formatted fixed-point seconds.
void SetRemoteToLocalClockOffset(absl::optional<int64_t> value_q32x32);
// Returns a received header extension, an interpolated header extension, or
// |absl::nullopt| if it's not possible to interpolate a header extension.
absl::optional<AbsoluteCaptureTime> OnReceivePacket(
uint32_t source,
uint32_t rtp_timestamp,
uint32_t rtp_clock_frequency,
const absl::optional<AbsoluteCaptureTime>& received_extension);
private:
friend class AbsoluteCaptureTimeSender;
static uint64_t InterpolateAbsoluteCaptureTimestamp(
uint32_t rtp_timestamp,
uint32_t rtp_clock_frequency,
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
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
absl::optional<int64_t> AdjustEstimatedCaptureClockOffset(
absl::optional<int64_t> received_value) const
RTC_EXCLUSIVE_LOCKS_REQUIRED(crit_);
Clock* const clock_;
rtc::CriticalSection crit_;
absl::optional<int64_t> remote_to_local_clock_offset_ RTC_GUARDED_BY(crit_);
Timestamp last_receive_time_ RTC_GUARDED_BY(crit_);
uint32_t last_source_ RTC_GUARDED_BY(crit_);
uint32_t last_rtp_timestamp_ RTC_GUARDED_BY(crit_);
uint32_t last_rtp_clock_frequency_ RTC_GUARDED_BY(crit_);
uint64_t last_absolute_capture_timestamp_ RTC_GUARDED_BY(crit_);
absl::optional<int64_t> last_estimated_capture_clock_offset_
RTC_GUARDED_BY(crit_);
}; // AbsoluteCaptureTimeReceiver
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_ABSOLUTE_CAPTURE_TIME_RECEIVER_H_

View File

@ -0,0 +1,416 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/rtp_rtcp/source/absolute_capture_time_receiver.h"
#include "system_wrappers/include/ntp_time.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
TEST(AbsoluteCaptureTimeReceiverTest, GetSourceWithoutCsrcs) {
constexpr uint32_t kSsrc = 12;
EXPECT_EQ(AbsoluteCaptureTimeReceiver::GetSource(kSsrc, nullptr), kSsrc);
}
TEST(AbsoluteCaptureTimeReceiverTest, GetSourceWithCsrcs) {
constexpr uint32_t kSsrc = 12;
constexpr uint32_t kCsrcs[] = {34, 56, 78, 90};
EXPECT_EQ(AbsoluteCaptureTimeReceiver::GetSource(kSsrc, kCsrcs), kCsrcs[0]);
}
TEST(AbsoluteCaptureTimeReceiverTest, ReceiveExtensionReturnsExtension) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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};
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp1,
kRtpClockFrequency, kExtension1),
kExtension1);
}
TEST(AbsoluteCaptureTimeReceiverTest, ReceiveNoExtensionReturnsNoExtension) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
absl::nullopt);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp1,
kRtpClockFrequency, kExtension1),
absl::nullopt);
}
TEST(AbsoluteCaptureTimeReceiverTest, InterpolateLaterPacketArrivingLater) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
absl::optional<AbsoluteCaptureTime> extension = receiver.OnReceivePacket(
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 20);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
extension = receiver.OnReceivePacket(kSource, kRtpTimestamp2,
kRtpClockFrequency, kExtension2);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 40);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
}
TEST(AbsoluteCaptureTimeReceiverTest, InterpolateEarlierPacketArrivingLater) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
absl::optional<AbsoluteCaptureTime> extension = receiver.OnReceivePacket(
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 20);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
extension = receiver.OnReceivePacket(kSource, kRtpTimestamp2,
kRtpClockFrequency, kExtension2);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 40);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
}
TEST(AbsoluteCaptureTimeReceiverTest,
InterpolateLaterPacketArrivingLaterWithRtpTimestampWrapAround) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
constexpr uint32_t kRtpTimestamp0 = ~uint32_t{0} - 79;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
absl::optional<AbsoluteCaptureTime> extension = receiver.OnReceivePacket(
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 20);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
extension = receiver.OnReceivePacket(kSource, kRtpTimestamp2,
kRtpClockFrequency, kExtension2);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 40);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
}
TEST(AbsoluteCaptureTimeReceiverTest,
InterpolateEarlierPacketArrivingLaterWithRtpTimestampWrapAround) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
absl::optional<AbsoluteCaptureTime> extension = receiver.OnReceivePacket(
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 20);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
extension = receiver.OnReceivePacket(kSource, kRtpTimestamp2,
kRtpClockFrequency, kExtension2);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) - 40);
EXPECT_EQ(extension->estimated_capture_clock_offset,
kExtension0->estimated_capture_clock_offset);
}
TEST(AbsoluteCaptureTimeReceiverTest,
SkipEstimatedCaptureClockOffsetIfRemoteToLocalClockOffsetIsUnknown) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
static const absl::optional<int64_t> kRemoteToLocalClockOffset2 =
Int64MsToQ32x32(-7000007);
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
receiver.SetRemoteToLocalClockOffset(absl::nullopt);
absl::optional<AbsoluteCaptureTime> extension = receiver.OnReceivePacket(
kSource, kRtpTimestamp1, kRtpClockFrequency, kExtension1);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 20);
EXPECT_EQ(extension->estimated_capture_clock_offset, absl::nullopt);
receiver.SetRemoteToLocalClockOffset(kRemoteToLocalClockOffset2);
extension = receiver.OnReceivePacket(kSource, kRtpTimestamp2,
kRtpClockFrequency, kExtension2);
EXPECT_TRUE(extension.has_value());
EXPECT_EQ(UQ32x32ToInt64Ms(extension->absolute_capture_timestamp),
UQ32x32ToInt64Ms(kExtension0->absolute_capture_timestamp) + 40);
EXPECT_EQ(extension->estimated_capture_clock_offset,
*kExtension0->estimated_capture_clock_offset +
*kRemoteToLocalClockOffset2);
}
TEST(AbsoluteCaptureTimeReceiverTest, SkipInterpolateIfTooLate) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
clock.AdvanceTime(AbsoluteCaptureTimeReceiver::kInterpolationMaxInterval);
EXPECT_TRUE(receiver
.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
kExtension1)
.has_value());
clock.AdvanceTimeMilliseconds(1);
EXPECT_FALSE(receiver
.OnReceivePacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
kExtension2)
.has_value());
}
TEST(AbsoluteCaptureTimeReceiverTest, SkipInterpolateIfSourceChanged) {
constexpr uint32_t kSource0 = 1337;
constexpr uint32_t kSource1 = 1338;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource0, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
EXPECT_FALSE(receiver
.OnReceivePacket(kSource1, kRtpTimestamp1,
kRtpClockFrequency, kExtension1)
.has_value());
}
TEST(AbsoluteCaptureTimeReceiverTest,
SkipInterpolateIfRtpClockFrequencyChanged) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency0 = 64000;
constexpr uint32_t kRtpClockFrequency1 = 32000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency0, kExtension0),
kExtension0);
EXPECT_FALSE(receiver
.OnReceivePacket(kSource, kRtpTimestamp1,
kRtpClockFrequency1, kExtension1)
.has_value());
}
TEST(AbsoluteCaptureTimeReceiverTest,
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
EXPECT_FALSE(receiver
.OnReceivePacket(kSource, kRtpTimestamp1, kRtpClockFrequency,
kExtension1)
.has_value());
}
TEST(AbsoluteCaptureTimeReceiverTest, SkipInterpolateIsSticky) {
constexpr uint32_t kSource0 = 1337;
constexpr uint32_t kSource1 = 1338;
constexpr uint32_t kSource2 = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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;
SimulatedClock clock(0);
AbsoluteCaptureTimeReceiver receiver(&clock);
receiver.SetRemoteToLocalClockOffset(0);
EXPECT_EQ(receiver.OnReceivePacket(kSource0, kRtpTimestamp0,
kRtpClockFrequency, kExtension0),
kExtension0);
EXPECT_FALSE(receiver
.OnReceivePacket(kSource1, kRtpTimestamp1,
kRtpClockFrequency, kExtension1)
.has_value());
EXPECT_FALSE(receiver
.OnReceivePacket(kSource2, kRtpTimestamp2,
kRtpClockFrequency, kExtension2)
.has_value());
}
} // namespace webrtc

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/rtp_rtcp/source/absolute_capture_time_sender.h"
#include <limits>
#include "modules/rtp_rtcp/source/absolute_capture_time_receiver.h"
#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(
AbsoluteCaptureTimeReceiver::kInterpolationMaxInterval >=
AbsoluteCaptureTimeSender::kInterpolationMaxInterval,
"Receivers should be as willing to interpolate timestamps as senders.");
AbsoluteCaptureTimeSender::AbsoluteCaptureTimeSender(Clock* clock)
: clock_(clock), last_send_time_(kInvalidLastSendTime) {}
uint32_t AbsoluteCaptureTimeSender::GetSource(
uint32_t ssrc,
rtc::ArrayView<const uint32_t> csrcs) {
return AbsoluteCaptureTimeReceiver::GetSource(ssrc, csrcs);
}
absl::optional<AbsoluteCaptureTime> AbsoluteCaptureTimeSender::OnSendPacket(
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 Timestamp send_time = clock_->CurrentTime();
rtc::CritScope cs(&crit_);
if (!ShouldSendExtension(send_time, source, rtp_timestamp,
rtp_clock_frequency, absolute_capture_timestamp,
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_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;
}
bool AbsoluteCaptureTimeSender::ShouldSendExtension(
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 {
// 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) {
return true;
}
// Should if the source has changed.
if (last_source_ != source) {
return true;
}
// Should if the RTP clock frequency has changed.
if (last_rtp_clock_frequency_ != rtp_clock_frequency) {
return true;
}
// Should if the RTP clock frequency is invalid.
if (rtp_clock_frequency <= 0) {
return true;
}
// Should if the estimated capture clock offset has changed.
if (last_estimated_capture_clock_offset_ != estimated_capture_clock_offset) {
return true;
}
// Should if interpolation would introduce too much error.
const uint64_t interpolated_absolute_capture_timestamp =
AbsoluteCaptureTimeReceiver::InterpolateAbsoluteCaptureTimestamp(
rtp_timestamp, rtp_clock_frequency, last_rtp_timestamp_,
last_absolute_capture_timestamp_);
const int64_t interpolation_error_ms = UQ32x32ToInt64Ms(std::min(
interpolated_absolute_capture_timestamp - absolute_capture_timestamp,
absolute_capture_timestamp - interpolated_absolute_capture_timestamp));
if (interpolation_error_ms > kInterpolationMaxError.ms()) {
return true;
}
return false;
}
} // namespace webrtc

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef MODULES_RTP_RTCP_SOURCE_ABSOLUTE_CAPTURE_TIME_SENDER_H_
#define MODULES_RTP_RTCP_SOURCE_ABSOLUTE_CAPTURE_TIME_SENDER_H_
#include "api/array_view.h"
#include "api/rtp_headers.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/critical_section.h"
#include "rtc_base/thread_annotations.h"
#include "system_wrappers/include/clock.h"
namespace webrtc {
//
// Helper class for sending the |AbsoluteCaptureTime| header extension.
//
// Supports the "timestamp interpolation" optimization:
// A sender SHOULD save bandwidth by not sending abs-capture-time with every
// RTP packet. It SHOULD still send them at regular intervals (e.g. every
// second) to help mitigate the impact of clock drift and packet loss. Mixers
// SHOULD always send abs-capture-time with the first RTP packet after
// changing capture system.
//
// Timestamp interpolation works fine as long as theres reasonably low
// NTP/RTP clock drift. This is not always true. Senders that detect “jumps”
// between its NTP and RTP clock mappings SHOULD send abs-capture-time with
// the first RTP packet after such a thing happening.
//
// See: https://webrtc.org/experiments/rtp-hdrext/abs-capture-time/
//
class AbsoluteCaptureTimeSender {
public:
static constexpr TimeDelta kInterpolationMaxInterval =
TimeDelta::Millis<1000>();
static constexpr TimeDelta kInterpolationMaxError = TimeDelta::Millis<1>();
explicit AbsoluteCaptureTimeSender(Clock* clock);
// Returns the source (i.e. SSRC or CSRC) of the capture system.
static uint32_t GetSource(uint32_t ssrc,
rtc::ArrayView<const uint32_t> csrcs);
// Returns a header extension to be sent, or |absl::nullopt| if the header
// extension shouldn't be sent.
absl::optional<AbsoluteCaptureTime> OnSendPacket(
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);
private:
bool ShouldSendExtension(
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(crit_);
Clock* const clock_;
rtc::CriticalSection crit_;
Timestamp last_send_time_ RTC_GUARDED_BY(crit_);
uint32_t last_source_ RTC_GUARDED_BY(crit_);
uint32_t last_rtp_timestamp_ RTC_GUARDED_BY(crit_);
uint32_t last_rtp_clock_frequency_ RTC_GUARDED_BY(crit_);
uint64_t last_absolute_capture_timestamp_ RTC_GUARDED_BY(crit_);
absl::optional<int64_t> last_estimated_capture_clock_offset_
RTC_GUARDED_BY(crit_);
}; // AbsoluteCaptureTimeSender
} // namespace webrtc
#endif // MODULES_RTP_RTCP_SOURCE_ABSOLUTE_CAPTURE_TIME_SENDER_H_

View File

@ -0,0 +1,374 @@
/*
* Copyright (c) 2019 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "modules/rtp_rtcp/source/absolute_capture_time_sender.h"
#include "system_wrappers/include/ntp_time.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
TEST(AbsoluteCaptureTimeSenderTest, GetSourceWithoutCsrcs) {
constexpr uint32_t kSsrc = 12;
EXPECT_EQ(AbsoluteCaptureTimeSender::GetSource(kSsrc, nullptr), kSsrc);
}
TEST(AbsoluteCaptureTimeSenderTest, GetSourceWithCsrcs) {
constexpr uint32_t kSsrc = 12;
constexpr uint32_t kCsrcs[] = {34, 56, 78, 90};
EXPECT_EQ(AbsoluteCaptureTimeSender::GetSource(kSsrc, kCsrcs), kCsrcs[0]);
}
TEST(AbsoluteCaptureTimeSenderTest, InterpolateLaterPacketSentLater) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
absl::nullopt);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
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 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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
absl::nullopt);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
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 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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
absl::nullopt);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
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 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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
absl::nullopt);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
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 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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
absl::nullopt);
clock.AdvanceTimeMicroseconds(1);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
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 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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource0, kRtpTimestamp0, kRtpClockFrequency,
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),
kExtension1);
EXPECT_EQ(sender.OnSendPacket(kSource2, kRtpTimestamp2, kRtpClockFrequency,
kExtension2->absolute_capture_timestamp,
kExtension2->estimated_capture_clock_offset),
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 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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency0,
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),
kExtension1);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency2,
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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency0,
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),
kExtension1);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency2,
kExtension2->absolute_capture_timestamp,
kExtension2->estimated_capture_clock_offset),
kExtension2);
}
TEST(AbsoluteCaptureTimeSenderTest,
SkipInterpolateIfEstimatedCaptureClockOffsetChanged) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
kExtension1);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
kExtension2->absolute_capture_timestamp,
kExtension2->estimated_capture_clock_offset),
kExtension2);
}
TEST(AbsoluteCaptureTimeSenderTest,
SkipInterpolateIfTooMuchInterpolationError) {
constexpr uint32_t kSource = 1337;
constexpr uint32_t kRtpClockFrequency = 64000;
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)};
SimulatedClock clock(0);
AbsoluteCaptureTimeSender sender(&clock);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp0, kRtpClockFrequency,
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),
absl::nullopt);
EXPECT_EQ(sender.OnSendPacket(kSource, kRtpTimestamp2, kRtpClockFrequency,
kExtension2->absolute_capture_timestamp,
kExtension2->estimated_capture_clock_offset),
kExtension2);
}
} // namespace webrtc