Revert "Migrate RemoteNtpTimeEstimator to more precise time representations"

This reverts commit a154a15c978a0eae133d957dcad3581fd5f98c7b.

Reason for revert: breaks downstream tests

Original change's description:
> Migrate RemoteNtpTimeEstimator to more precise time representations
>
> Bug: webrtc:13757
> Change-Id: I880ab3cc6e4f72da587ae42ddca051332907c07f
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261311
> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
> Reviewed-by: Jakob Ivarsson‎ <jakobi@webrtc.org>
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Reviewed-by: Emil Lundmark <lndmrk@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#36817}

Bug: webrtc:13757
Change-Id: Id21edb1378e6e944b24955396250ddc33fa70663
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/261722
Reviewed-by: Tomas Gunnarsson <tommi@webrtc.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36819}
This commit is contained in:
Danil Chapovalov 2022-05-09 15:40:05 +00:00 committed by WebRTC LUCI CQ
parent cb7c7366d0
commit 853a407273
9 changed files with 117 additions and 171 deletions

View File

@ -748,13 +748,12 @@ void ChannelReceive::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
{ {
MutexLock lock(&ts_stats_lock_); MutexLock lock(&ts_stats_lock_);
ntp_estimator_.UpdateRtcpTimestamp( ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
TimeDelta::Millis(rtt), NtpTime(ntp_secs, ntp_frac), rtp_timestamp); absl::optional<int64_t> remote_to_local_clock_offset_ms =
absl::optional<int64_t> remote_to_local_clock_offset = ntp_estimator_.EstimateRemoteToLocalClockOffsetMs();
ntp_estimator_.EstimateRemoteToLocalClockOffset(); if (remote_to_local_clock_offset_ms.has_value()) {
if (remote_to_local_clock_offset.has_value()) {
capture_clock_offset_updater_.SetRemoteToLocalClockOffset( capture_clock_offset_updater_.SetRemoteToLocalClockOffset(
*remote_to_local_clock_offset); Int64MsToQ32x32(*remote_to_local_clock_offset_ms));
} }
} }
} }

View File

@ -226,8 +226,7 @@ void AudioIngress::ReceivedRTCPPacket(
{ {
MutexLock lock(&lock_); MutexLock lock(&lock_);
ntp_estimator_.UpdateRtcpTimestamp( ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
TimeDelta::Millis(rtt), NtpTime(ntp_secs, ntp_frac), rtp_timestamp);
} }
} }

View File

@ -13,10 +13,7 @@
#include <stdint.h> #include <stdint.h>
#include "absl/base/attributes.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/numerics/moving_median_filter.h" #include "rtc_base/numerics/moving_median_filter.h"
#include "system_wrappers/include/rtp_to_ntp_estimator.h" #include "system_wrappers/include/rtp_to_ntp_estimator.h"
@ -31,63 +28,32 @@ class Clock;
class RemoteNtpTimeEstimator { class RemoteNtpTimeEstimator {
public: public:
explicit RemoteNtpTimeEstimator(Clock* clock); explicit RemoteNtpTimeEstimator(Clock* clock);
~RemoteNtpTimeEstimator();
RemoteNtpTimeEstimator(const RemoteNtpTimeEstimator&) = delete; RemoteNtpTimeEstimator(const RemoteNtpTimeEstimator&) = delete;
RemoteNtpTimeEstimator& operator=(const RemoteNtpTimeEstimator&) = delete; RemoteNtpTimeEstimator& operator=(const RemoteNtpTimeEstimator&) = delete;
~RemoteNtpTimeEstimator() = default;
// Updates the estimator with round trip time `rtt`, NTP seconds `ntp_secs`, // Updates the estimator with round trip time `rtt`, NTP seconds `ntp_secs`,
// NTP fraction `ntp_frac` and RTP timestamp `rtp_timestamp`. // NTP fraction `ntp_frac` and RTP timestamp `rtp_timestamp`.
ABSL_DEPRECATED(
"Use UpdateRtcpTimestamp with strict time types: TimeDelta and NtpTime.")
bool UpdateRtcpTimestamp(int64_t rtt, bool UpdateRtcpTimestamp(int64_t rtt,
uint32_t ntp_secs, uint32_t ntp_secs,
uint32_t ntp_frac, uint32_t ntp_frac,
uint32_t rtp_timestamp) {
return UpdateRtcpTimestamp(TimeDelta::Millis(rtt),
NtpTime(ntp_secs, ntp_frac), rtp_timestamp);
}
bool UpdateRtcpTimestamp(TimeDelta rtt,
NtpTime sender_send_time,
uint32_t rtp_timestamp); uint32_t rtp_timestamp);
// Estimates the NTP timestamp in local timebase from `rtp_timestamp`. // Estimates the NTP timestamp in local timebase from `rtp_timestamp`.
// Returns the NTP timestamp in ms when success. -1 if failed. // Returns the NTP timestamp in ms when success. -1 if failed.
int64_t Estimate(uint32_t rtp_timestamp) { int64_t Estimate(uint32_t rtp_timestamp);
NtpTime ntp_time = EstimateNtp(rtp_timestamp);
if (!ntp_time.Valid()) {
return -1;
}
return ntp_time.ToMs();
}
// Estimates the NTP timestamp in local timebase from `rtp_timestamp`.
// Returns invalid NtpTime (i.e. NtpTime(0)) on failure.
NtpTime EstimateNtp(uint32_t rtp_timestamp);
// Estimates the offset, in milliseconds, between the remote clock and the // Estimates the offset, in milliseconds, between the remote clock and the
// local one. This is equal to local NTP clock - remote NTP clock. // local one. This is equal to local NTP clock - remote NTP clock.
ABSL_DEPRECATED("Use EstimateRemoteToLocalClockOffset.") absl::optional<int64_t> EstimateRemoteToLocalClockOffsetMs();
absl::optional<int64_t> EstimateRemoteToLocalClockOffsetMs() {
if (absl::optional<int64_t> offset = EstimateRemoteToLocalClockOffset()) {
return (*offset * 1'000) / (int64_t{1} << 32);
}
return absl::nullopt;
}
// Estimates the offset between the remote clock and the
// local one. This is equal to local NTP clock - remote NTP clock.
// The offset is returned in ntp time resolution, i.e. 1/2^32 sec ~= 0.2 ns.
// Returns nullopt on failure.
absl::optional<int64_t> EstimateRemoteToLocalClockOffset();
private: private:
Clock* clock_; Clock* clock_;
// Offset is measured with the same precision as NtpTime: in 1/2^32 seconds ~=
// 0.2 ns.
MovingMedianFilter<int64_t> ntp_clocks_offset_estimator_; MovingMedianFilter<int64_t> ntp_clocks_offset_estimator_;
RtpToNtpEstimator rtp_to_ntp_; RtpToNtpEstimator rtp_to_ntp_;
Timestamp last_timing_log_ = Timestamp::MinusInfinity(); int64_t last_timing_log_ms_;
}; };
} // namespace webrtc } // namespace webrtc

View File

@ -22,37 +22,25 @@ namespace webrtc {
namespace { namespace {
constexpr int kMinimumNumberOfSamples = 2; constexpr int kMinimumNumberOfSamples = 2;
constexpr TimeDelta kTimingLogInterval = TimeDelta::Seconds(10); constexpr int kTimingLogIntervalMs = 10000;
constexpr int kClocksOffsetSmoothingWindow = 100; constexpr int kClocksOffsetSmoothingWindow = 100;
// Subtracts two NtpTime values keeping maximum precision.
int64_t Subtract(NtpTime minuend, NtpTime subtrahend) {
uint64_t a = static_cast<uint64_t>(minuend);
uint64_t b = static_cast<uint64_t>(subtrahend);
return a >= b ? static_cast<int64_t>(a - b) : -static_cast<int64_t>(b - a);
}
NtpTime Add(NtpTime lhs, int64_t rhs) {
uint64_t result = static_cast<uint64_t>(lhs);
if (rhs >= 0) {
result += static_cast<uint64_t>(rhs);
} else {
result -= static_cast<uint64_t>(-rhs);
}
return NtpTime(result);
}
} // namespace } // namespace
// TODO(wu): Refactor this class so that it can be shared with // TODO(wu): Refactor this class so that it can be shared with
// vie_sync_module.cc. // vie_sync_module.cc.
RemoteNtpTimeEstimator::RemoteNtpTimeEstimator(Clock* clock) RemoteNtpTimeEstimator::RemoteNtpTimeEstimator(Clock* clock)
: clock_(clock), : clock_(clock),
ntp_clocks_offset_estimator_(kClocksOffsetSmoothingWindow) {} ntp_clocks_offset_estimator_(kClocksOffsetSmoothingWindow),
last_timing_log_ms_(-1) {}
bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(TimeDelta rtt, RemoteNtpTimeEstimator::~RemoteNtpTimeEstimator() {}
NtpTime sender_send_time,
bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(int64_t rtt,
uint32_t ntp_secs,
uint32_t ntp_frac,
uint32_t rtp_timestamp) { uint32_t rtp_timestamp) {
NtpTime sender_send_time(ntp_secs, ntp_frac);
switch (rtp_to_ntp_.UpdateMeasurements(sender_send_time, rtp_timestamp)) { switch (rtp_to_ntp_.UpdateMeasurements(sender_send_time, rtp_timestamp)) {
case RtpToNtpEstimator::kInvalidMeasurement: case RtpToNtpEstimator::kInvalidMeasurement:
return false; return false;
@ -63,42 +51,42 @@ bool RemoteNtpTimeEstimator::UpdateRtcpTimestamp(TimeDelta rtt,
break; break;
} }
// Assume connection is symmetric and thus time to deliver the packet is half
// the round trip time.
int64_t deliver_time_ntp = ToNtpUnits(rtt) / 2;
// Update extrapolator with the new arrival time. // Update extrapolator with the new arrival time.
NtpTime receiver_arrival_time = clock_->CurrentNtpTime(); // The extrapolator assumes the ntp time.
int64_t receiver_arrival_time_ms = clock_->CurrentNtpInMilliseconds();
int64_t sender_arrival_time_ms = sender_send_time.ToMs() + rtt / 2;
int64_t remote_to_local_clocks_offset = int64_t remote_to_local_clocks_offset =
Subtract(receiver_arrival_time, sender_send_time) - deliver_time_ntp; receiver_arrival_time_ms - sender_arrival_time_ms;
ntp_clocks_offset_estimator_.Insert(remote_to_local_clocks_offset); ntp_clocks_offset_estimator_.Insert(remote_to_local_clocks_offset);
return true; return true;
} }
NtpTime RemoteNtpTimeEstimator::EstimateNtp(uint32_t rtp_timestamp) { int64_t RemoteNtpTimeEstimator::Estimate(uint32_t rtp_timestamp) {
NtpTime sender_capture = rtp_to_ntp_.Estimate(rtp_timestamp); NtpTime sender_capture = rtp_to_ntp_.Estimate(rtp_timestamp);
if (!sender_capture.Valid()) { if (!sender_capture.Valid()) {
return sender_capture; return -1;
} }
int64_t sender_capture_ntp_ms = sender_capture.ToMs();
int64_t remote_to_local_clocks_offset = int64_t remote_to_local_clocks_offset =
ntp_clocks_offset_estimator_.GetFilteredValue(); ntp_clocks_offset_estimator_.GetFilteredValue();
NtpTime receiver_capture = Add(sender_capture, remote_to_local_clocks_offset); int64_t receiver_capture_ntp_ms =
sender_capture_ntp_ms + remote_to_local_clocks_offset;
Timestamp now = clock_->CurrentTime(); int64_t now_ms = clock_->TimeInMilliseconds();
if (now - last_timing_log_ > kTimingLogInterval) { if (now_ms - last_timing_log_ms_ > kTimingLogIntervalMs) {
RTC_LOG(LS_INFO) << "RTP timestamp: " << rtp_timestamp RTC_LOG(LS_INFO) << "RTP timestamp: " << rtp_timestamp
<< " in NTP clock: " << sender_capture.ToMs() << " in NTP clock: " << sender_capture_ntp_ms
<< " estimated time in receiver NTP clock: " << " estimated time in receiver NTP clock: "
<< receiver_capture.ToMs(); << receiver_capture_ntp_ms;
last_timing_log_ = now; last_timing_log_ms_ = now_ms;
} }
return receiver_capture; return receiver_capture_ntp_ms;
} }
absl::optional<int64_t> absl::optional<int64_t>
RemoteNtpTimeEstimator::EstimateRemoteToLocalClockOffset() { RemoteNtpTimeEstimator::EstimateRemoteToLocalClockOffsetMs() {
if (ntp_clocks_offset_estimator_.GetNumberOfSamplesStored() < if (ntp_clocks_offset_estimator_.GetNumberOfSamplesStored() <
kMinimumNumberOfSamples) { kMinimumNumberOfSamples) {
return absl::nullopt; return absl::nullopt;

View File

@ -9,29 +9,32 @@
*/ */
#include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h" #include "modules/rtp_rtcp/include/remote_ntp_time_estimator.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "modules/rtp_rtcp/source/time_util.h"
#include "system_wrappers/include/clock.h" #include "system_wrappers/include/clock.h"
#include "system_wrappers/include/ntp_time.h" #include "system_wrappers/include/ntp_time.h"
#include "test/gmock.h" #include "test/gmock.h"
#include "test/gtest.h" #include "test/gtest.h"
namespace webrtc { namespace webrtc {
namespace {
constexpr TimeDelta kTestRtt = TimeDelta::Millis(10); constexpr int64_t kTestRtt = 10;
constexpr Timestamp kLocalClockInitialTime = Timestamp::Millis(123); constexpr int64_t kLocalClockInitialTimeMs = 123;
constexpr Timestamp kRemoteClockInitialTime = Timestamp::Millis(373); constexpr int64_t kRemoteClockInitialTimeMs = 345;
constexpr uint32_t kTimestampOffset = 567; constexpr uint32_t kTimestampOffset = 567;
constexpr int64_t kRemoteToLocalClockOffsetNtp = constexpr int64_t kRemoteToLocalClockOffsetMs =
ToNtpUnits(kLocalClockInitialTime - kRemoteClockInitialTime); kLocalClockInitialTimeMs - kRemoteClockInitialTimeMs;
class RemoteNtpTimeEstimatorTest : public ::testing::Test { class RemoteNtpTimeEstimatorTest : public ::testing::Test {
protected: protected:
void AdvanceTime(TimeDelta delta) { RemoteNtpTimeEstimatorTest()
local_clock_.AdvanceTime(delta); : local_clock_(kLocalClockInitialTimeMs * 1000),
remote_clock_.AdvanceTime(delta); remote_clock_(kRemoteClockInitialTimeMs * 1000),
estimator_(new RemoteNtpTimeEstimator(&local_clock_)) {}
~RemoteNtpTimeEstimatorTest() override = default;
void AdvanceTimeMilliseconds(int64_t ms) {
local_clock_.AdvanceTimeMilliseconds(ms);
remote_clock_.AdvanceTimeMilliseconds(ms);
} }
uint32_t GetRemoteTimestamp() { uint32_t GetRemoteTimestamp() {
@ -39,90 +42,107 @@ class RemoteNtpTimeEstimatorTest : public ::testing::Test {
kTimestampOffset; kTimestampOffset;
} }
NtpTime GetRemoteNtpTime() { return remote_clock_.CurrentNtpTime(); }
void SendRtcpSr() { void SendRtcpSr() {
uint32_t rtcp_timestamp = GetRemoteTimestamp(); uint32_t rtcp_timestamp = GetRemoteTimestamp();
NtpTime ntp = remote_clock_.CurrentNtpTime(); NtpTime ntp = GetRemoteNtpTime();
AdvanceTime(kTestRtt / 2); AdvanceTimeMilliseconds(kTestRtt / 2);
RTC_DCHECK(estimator_.UpdateRtcpTimestamp(kTestRtt, ntp, rtcp_timestamp)); ReceiveRtcpSr(kTestRtt, rtcp_timestamp, ntp.seconds(), ntp.fractions());
} }
void SendRtcpSrInaccurately(TimeDelta ntp_error, TimeDelta networking_delay) { void SendRtcpSrInaccurately(int64_t ntp_error_ms,
int64_t networking_delay_ms) {
uint32_t rtcp_timestamp = GetRemoteTimestamp(); uint32_t rtcp_timestamp = GetRemoteTimestamp();
int64_t ntp_error_fractions = ToNtpUnits(ntp_error); int64_t ntp_error_fractions =
NtpTime ntp(static_cast<uint64_t>(remote_clock_.CurrentNtpTime()) + ntp_error_ms * static_cast<int64_t>(NtpTime::kFractionsPerSecond) /
1000;
NtpTime ntp(static_cast<uint64_t>(GetRemoteNtpTime()) +
ntp_error_fractions); ntp_error_fractions);
AdvanceTime(kTestRtt / 2 + networking_delay); AdvanceTimeMilliseconds(kTestRtt / 2 + networking_delay_ms);
RTC_DCHECK(estimator_.UpdateRtcpTimestamp(kTestRtt, ntp, rtcp_timestamp)); ReceiveRtcpSr(kTestRtt, rtcp_timestamp, ntp.seconds(), ntp.fractions());
} }
SimulatedClock local_clock_{kLocalClockInitialTime}; void UpdateRtcpTimestamp(int64_t rtt,
SimulatedClock remote_clock_{kRemoteClockInitialTime}; uint32_t ntp_secs,
RemoteNtpTimeEstimator estimator_{&local_clock_}; uint32_t ntp_frac,
uint32_t rtp_timestamp,
bool expected_result) {
EXPECT_EQ(expected_result, estimator_->UpdateRtcpTimestamp(
rtt, ntp_secs, ntp_frac, rtp_timestamp));
}
void ReceiveRtcpSr(int64_t rtt,
uint32_t rtcp_timestamp,
uint32_t ntp_seconds,
uint32_t ntp_fractions) {
UpdateRtcpTimestamp(rtt, ntp_seconds, ntp_fractions, rtcp_timestamp, true);
}
SimulatedClock local_clock_;
SimulatedClock remote_clock_;
std::unique_ptr<RemoteNtpTimeEstimator> estimator_;
}; };
TEST_F(RemoteNtpTimeEstimatorTest, FailsWithoutValidNtpTime) {
EXPECT_FALSE(
estimator_.UpdateRtcpTimestamp(kTestRtt, NtpTime(), /*rtp_timestamp=*/0));
}
TEST_F(RemoteNtpTimeEstimatorTest, Estimate) { TEST_F(RemoteNtpTimeEstimatorTest, Estimate) {
// Failed without valid NTP.
UpdateRtcpTimestamp(kTestRtt, 0, 0, 0, false);
AdvanceTimeMilliseconds(1000);
// Remote peer sends first RTCP SR. // Remote peer sends first RTCP SR.
SendRtcpSr(); SendRtcpSr();
// Remote sends a RTP packet. // Remote sends a RTP packet.
AdvanceTime(TimeDelta::Millis(15)); AdvanceTimeMilliseconds(15);
uint32_t rtp_timestamp = GetRemoteTimestamp(); uint32_t rtp_timestamp = GetRemoteTimestamp();
int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds(); int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
// Local peer needs at least 2 RTCP SR to calculate the capture time. // Local peer needs at least 2 RTCP SR to calculate the capture time.
const int64_t kNotEnoughRtcpSr = -1; const int64_t kNotEnoughRtcpSr = -1;
EXPECT_EQ(kNotEnoughRtcpSr, estimator_.Estimate(rtp_timestamp)); EXPECT_EQ(kNotEnoughRtcpSr, estimator_->Estimate(rtp_timestamp));
EXPECT_EQ(estimator_.EstimateRemoteToLocalClockOffset(), absl::nullopt); EXPECT_EQ(absl::nullopt, estimator_->EstimateRemoteToLocalClockOffsetMs());
AdvanceTime(TimeDelta::Millis(800)); AdvanceTimeMilliseconds(800);
// Remote sends second RTCP SR. // Remote sends second RTCP SR.
SendRtcpSr(); SendRtcpSr();
// Local peer gets enough RTCP SR to calculate the capture time. // Local peer gets enough RTCP SR to calculate the capture time.
EXPECT_EQ(capture_ntp_time_ms, estimator_.Estimate(rtp_timestamp)); EXPECT_EQ(capture_ntp_time_ms, estimator_->Estimate(rtp_timestamp));
EXPECT_EQ(estimator_.EstimateRemoteToLocalClockOffset(), EXPECT_EQ(kRemoteToLocalClockOffsetMs,
kRemoteToLocalClockOffsetNtp); estimator_->EstimateRemoteToLocalClockOffsetMs());
} }
TEST_F(RemoteNtpTimeEstimatorTest, AveragesErrorsOut) { TEST_F(RemoteNtpTimeEstimatorTest, AveragesErrorsOut) {
// Remote peer sends first 10 RTCP SR without errors. // Remote peer sends first 10 RTCP SR without errors.
for (int i = 0; i < 10; ++i) { for (int i = 0; i < 10; ++i) {
AdvanceTime(TimeDelta::Seconds(1)); AdvanceTimeMilliseconds(1000);
SendRtcpSr(); SendRtcpSr();
} }
AdvanceTime(TimeDelta::Millis(150)); AdvanceTimeMilliseconds(150);
uint32_t rtp_timestamp = GetRemoteTimestamp(); uint32_t rtp_timestamp = GetRemoteTimestamp();
int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds(); int64_t capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
// Local peer gets enough RTCP SR to calculate the capture time. // Local peer gets enough RTCP SR to calculate the capture time.
EXPECT_EQ(capture_ntp_time_ms, estimator_.Estimate(rtp_timestamp)); EXPECT_EQ(capture_ntp_time_ms, estimator_->Estimate(rtp_timestamp));
EXPECT_EQ(kRemoteToLocalClockOffsetNtp, EXPECT_EQ(kRemoteToLocalClockOffsetMs,
estimator_.EstimateRemoteToLocalClockOffset()); estimator_->EstimateRemoteToLocalClockOffsetMs());
// Remote sends corrupted RTCP SRs // Remote sends corrupted RTCP SRs
AdvanceTime(TimeDelta::Seconds(1)); AdvanceTimeMilliseconds(1000);
SendRtcpSrInaccurately(/*ntp_error=*/TimeDelta::Millis(2), SendRtcpSrInaccurately(/*ntp_error_ms=*/2, /*networking_delay_ms=*/-1);
/*networking_delay=*/TimeDelta::Millis(-1)); AdvanceTimeMilliseconds(1000);
AdvanceTime(TimeDelta::Seconds(1)); SendRtcpSrInaccurately(/*ntp_error_ms=*/-2, /*networking_delay_ms=*/1);
SendRtcpSrInaccurately(/*ntp_error=*/TimeDelta::Millis(-2),
/*networking_delay=*/TimeDelta::Millis(1));
// New RTP packet to estimate timestamp. // New RTP packet to estimate timestamp.
AdvanceTime(TimeDelta::Millis(150)); AdvanceTimeMilliseconds(150);
rtp_timestamp = GetRemoteTimestamp(); rtp_timestamp = GetRemoteTimestamp();
capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds(); capture_ntp_time_ms = local_clock_.CurrentNtpInMilliseconds();
// Errors should be averaged out. // Errors should be averaged out.
EXPECT_EQ(capture_ntp_time_ms, estimator_.Estimate(rtp_timestamp)); EXPECT_EQ(capture_ntp_time_ms, estimator_->Estimate(rtp_timestamp));
EXPECT_EQ(kRemoteToLocalClockOffsetNtp, EXPECT_EQ(kRemoteToLocalClockOffsetMs,
estimator_.EstimateRemoteToLocalClockOffset()); estimator_->EstimateRemoteToLocalClockOffsetMs());
} }
} // namespace
} // namespace webrtc } // namespace webrtc

View File

@ -34,14 +34,6 @@ inline uint32_t CompactNtp(NtpTime ntp) {
// Negative values converted to 0, Overlarge values converted to max uint32_t. // Negative values converted to 0, Overlarge values converted to max uint32_t.
uint32_t SaturatedToCompactNtp(TimeDelta delta); uint32_t SaturatedToCompactNtp(TimeDelta delta);
// Convert interval to the NTP time resolution (1/2^32 seconds ~= 0.2 ns).
inline constexpr int64_t ToNtpUnits(TimeDelta delta) {
// For better precision `delta` is taken with best TimeDelta precision (us),
// then multiplaction and conversion to seconds are swapped to avoid float
// arithmetic.
return (delta.us() * (int64_t{1} << 32)) / 1'000'000;
}
// Converts interval from compact ntp (1/2^16 seconds) resolution to TimeDelta. // Converts interval from compact ntp (1/2^16 seconds) resolution to TimeDelta.
// This interval can be up to ~9.1 hours (2^15 seconds). // This interval can be up to ~9.1 hours (2^15 seconds).
// Values close to 2^16 seconds are considered negative and are converted to // Values close to 2^16 seconds are considered negative and are converted to

View File

@ -95,20 +95,4 @@ TEST(TimeUtilTest, SaturatedToCompactNtp) {
5'515, 16); 5'515, 16);
} }
TEST(TimeUtilTest, ToNtpUnits) {
EXPECT_EQ(ToNtpUnits(TimeDelta::Zero()), 0);
EXPECT_EQ(ToNtpUnits(TimeDelta::Seconds(1)), int64_t{1} << 32);
EXPECT_EQ(ToNtpUnits(TimeDelta::Seconds(-1)), -(int64_t{1} << 32));
EXPECT_EQ(ToNtpUnits(TimeDelta::Millis(500)), int64_t{1} << 31);
EXPECT_EQ(ToNtpUnits(TimeDelta::Millis(-1'500)), -(int64_t{3} << 31));
// Smallest TimeDelta that can be converted without precision loss.
EXPECT_EQ(ToNtpUnits(TimeDelta::Micros(15'625)), int64_t{1} << 26);
// 1 us ~= 4'294.97 NTP units. ToNtpUnits makes no rounding promises.
EXPECT_GE(ToNtpUnits(TimeDelta::Micros(1)), 4'294);
EXPECT_LE(ToNtpUnits(TimeDelta::Micros(1)), 4'295);
}
} // namespace webrtc } // namespace webrtc

View File

@ -1122,13 +1122,12 @@ bool RtpVideoStreamReceiver::DeliverRtcp(const uint8_t* rtcp_packet,
clock_->CurrentNtpInMilliseconds() - received_ntp.ToMs(); clock_->CurrentNtpInMilliseconds() - received_ntp.ToMs();
// Don't use old SRs to estimate time. // Don't use old SRs to estimate time.
if (time_since_received <= 1) { if (time_since_received <= 1) {
ntp_estimator_.UpdateRtcpTimestamp( ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
TimeDelta::Millis(rtt), NtpTime(ntp_secs, ntp_frac), rtp_timestamp); absl::optional<int64_t> remote_to_local_clock_offset_ms =
absl::optional<int64_t> remote_to_local_clock_offset = ntp_estimator_.EstimateRemoteToLocalClockOffsetMs();
ntp_estimator_.EstimateRemoteToLocalClockOffset(); if (remote_to_local_clock_offset_ms.has_value()) {
if (remote_to_local_clock_offset.has_value()) {
capture_clock_offset_updater_.SetRemoteToLocalClockOffset( capture_clock_offset_updater_.SetRemoteToLocalClockOffset(
*remote_to_local_clock_offset); Int64MsToQ32x32(*remote_to_local_clock_offset_ms));
} }
} }

View File

@ -1042,13 +1042,12 @@ bool RtpVideoStreamReceiver2::DeliverRtcp(const uint8_t* rtcp_packet,
clock_->CurrentNtpInMilliseconds() - received_ntp.ToMs(); clock_->CurrentNtpInMilliseconds() - received_ntp.ToMs();
// Don't use old SRs to estimate time. // Don't use old SRs to estimate time.
if (time_since_received <= 1) { if (time_since_received <= 1) {
ntp_estimator_.UpdateRtcpTimestamp( ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
TimeDelta::Millis(rtt), NtpTime(ntp_secs, ntp_frac), rtp_timestamp); absl::optional<int64_t> remote_to_local_clock_offset_ms =
absl::optional<int64_t> remote_to_local_clock_offset = ntp_estimator_.EstimateRemoteToLocalClockOffsetMs();
ntp_estimator_.EstimateRemoteToLocalClockOffset(); if (remote_to_local_clock_offset_ms.has_value()) {
if (remote_to_local_clock_offset.has_value()) {
capture_clock_offset_updater_.SetRemoteToLocalClockOffset( capture_clock_offset_updater_.SetRemoteToLocalClockOffset(
*remote_to_local_clock_offset); Int64MsToQ32x32(*remote_to_local_clock_offset_ms));
} }
} }