From b59e9045bf215aaec869412b16d0fd39bf0df4ec Mon Sep 17 00:00:00 2001 From: Paul Hallak Date: Thu, 20 May 2021 17:21:49 +0200 Subject: [PATCH] Add the ability to convert a timestamp to NTP time. The timestamps returned by the clocks do not have an epoch. Each clock should be able to convert a timestamp it returns to an NTP time. The default implementation for querying for an NTP time is converting the current timestamp. This is favored over returning the offset between the relative and the NTP time because there is a field trial that makes the real clock revert to using system dependent methods for getting the NTP time. Bug: webrtc:11327 Change-Id: Ia139b2744b407cae94420bf9112212ec577efb16 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/219687 Reviewed-by: Minyue Li Reviewed-by: Niels Moller Commit-Queue: Paul Hallak Cr-Commit-Position: refs/heads/master@{#34071} --- system_wrappers/include/clock.h | 18 ++++++++++++++++-- system_wrappers/source/clock.cc | 16 +++++++++++----- test/drifting_clock.cc | 9 ++++----- test/drifting_clock.h | 9 +++++++-- 4 files changed, 38 insertions(+), 14 deletions(-) diff --git a/system_wrappers/include/clock.h b/system_wrappers/include/clock.h index 914fbda922..62d2216d9f 100644 --- a/system_wrappers/include/clock.h +++ b/system_wrappers/include/clock.h @@ -39,9 +39,23 @@ class RTC_EXPORT Clock { int64_t TimeInMicroseconds() { return CurrentTime().us(); } // Retrieve an NTP absolute timestamp (with an epoch of Jan 1, 1900). - virtual NtpTime CurrentNtpTime() = 0; + // TODO(bugs.webrtc.org/11327): Make this non-virtual once + // "WebRTC-SystemIndependentNtpTimeKillSwitch" is removed. + virtual NtpTime CurrentNtpTime() { + return ConvertTimestampToNtpTime(CurrentTime()); + } int64_t CurrentNtpInMilliseconds() { return CurrentNtpTime().ToMs(); } + // Converts between a relative timestamp returned by this clock, to NTP time. + // TODO(bugs.webrtc.org/11327): Make this method pure virtual, + // and delete default dummy implementation. + virtual NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) { + return NtpTime(); + } + int64_t ConvertTimestampToNtpTimeInMilliseconds(int64_t timestamp_ms) { + return ConvertTimestampToNtpTime(Timestamp::Millis(timestamp_ms)).ToMs(); + } + // Returns an instance of the real-time system clock implementation. static Clock* GetRealTimeClock(); }; @@ -56,7 +70,7 @@ class SimulatedClock : public Clock { // Return a timestamp with an epoch of Jan 1, 1970. Timestamp CurrentTime() override; - NtpTime CurrentNtpTime() override; + NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override; // Advance the simulated clock with a given number of milliseconds or // microseconds. diff --git a/system_wrappers/source/clock.cc b/system_wrappers/source/clock.cc index 2c3981a5a4..77c1d36327 100644 --- a/system_wrappers/source/clock.cc +++ b/system_wrappers/source/clock.cc @@ -93,6 +93,12 @@ class RealTimeClock : public Clock { : SystemDependentNtpTime(); } + NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override { + // This method does not check |use_system_independent_ntp_time_| because + // all callers never used the old behavior of |CurrentNtpTime|. + return TimeMicrosToNtp(timestamp.us()); + } + protected: virtual timeval CurrentTimeVal() = 0; @@ -276,11 +282,11 @@ Timestamp SimulatedClock::CurrentTime() { return Timestamp::Micros(time_us_.load(std::memory_order_relaxed)); } -NtpTime SimulatedClock::CurrentNtpTime() { - int64_t now_ms = TimeInMilliseconds(); - uint32_t seconds = (now_ms / 1000) + kNtpJan1970; - uint32_t fractions = - static_cast((now_ms % 1000) * kMagicNtpFractionalUnit / 1000); +NtpTime SimulatedClock::ConvertTimestampToNtpTime(Timestamp timestamp) { + int64_t now_us = timestamp.us(); + uint32_t seconds = (now_us / 1'000'000) + kNtpJan1970; + uint32_t fractions = static_cast( + (now_us % 1'000'000) * kMagicNtpFractionalUnit / 1'000'000); return NtpTime(seconds, fractions); } diff --git a/test/drifting_clock.cc b/test/drifting_clock.cc index 29b28ddc89..47c8e56916 100644 --- a/test/drifting_clock.cc +++ b/test/drifting_clock.cc @@ -28,16 +28,15 @@ TimeDelta DriftingClock::Drift() const { return (now - start_time_) * drift_; } -Timestamp DriftingClock::CurrentTime() { - return clock_->CurrentTime() + Drift() / 1000.; +Timestamp DriftingClock::Drift(Timestamp timestamp) const { + return timestamp + Drift() / 1000.; } -NtpTime DriftingClock::CurrentNtpTime() { +NtpTime DriftingClock::Drift(NtpTime ntp_time) const { // NTP precision is 1/2^32 seconds, i.e. 2^32 ntp fractions = 1 second. const double kNtpFracPerMicroSecond = 4294.967296; // = 2^32 / 10^6 - NtpTime ntp = clock_->CurrentNtpTime(); - uint64_t total_fractions = static_cast(ntp); + uint64_t total_fractions = static_cast(ntp_time); total_fractions += Drift().us() * kNtpFracPerMicroSecond; return NtpTime(total_fractions); } diff --git a/test/drifting_clock.h b/test/drifting_clock.h index 820b2f0550..3471c008a1 100644 --- a/test/drifting_clock.h +++ b/test/drifting_clock.h @@ -30,11 +30,16 @@ class DriftingClock : public Clock { return 1.0f - percent / 100.0f; } - Timestamp CurrentTime() override; - NtpTime CurrentNtpTime() override; + Timestamp CurrentTime() override { return Drift(clock_->CurrentTime()); } + NtpTime CurrentNtpTime() override { return Drift(clock_->CurrentNtpTime()); } + NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override { + return Drift(clock_->ConvertTimestampToNtpTime(timestamp)); + } private: TimeDelta Drift() const; + Timestamp Drift(Timestamp timestamp) const; + NtpTime Drift(NtpTime ntp_time) const; Clock* const clock_; const float drift_;