Consolidate the different NTP clocks into one.

WebRTC code has two ways of querying for the NTP time:
- rtc::TimeMillis() + NtpOffsetMs()
- Clock::CurrentNtpTime

`Clock::CurrentNtpTime` is not monotonic and is platform dependent.
This CL changes its implementation return `rtc::TimeMillis() +
NtpOffsetMs()`

More info is available in the attached bug.

Bug: webrtc:11327
Change-Id: I34fe4cc2d321c2b63275c93be21122c9de1ab403
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/213425
Commit-Queue: Paul Hallak <phallak@google.com>
Reviewed-by: Minyue Li <minyue@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#33655}
This commit is contained in:
Paul Hallak 2021-04-08 14:57:45 +02:00 committed by Commit Bot
parent 00f4fd9b1a
commit 704d6e518a
2 changed files with 75 additions and 51 deletions

View File

@ -32,18 +32,24 @@ const double kMagicNtpFractionalUnit = 4.294967296E+9;
class RTC_EXPORT Clock {
public:
virtual ~Clock() {}
// Return a timestamp relative to an unspecified epoch.
// TODO(bugs.webrtc.org/11327): Make this a pure virtual function.
virtual Timestamp CurrentTime() {
return Timestamp::Micros(TimeInMicroseconds());
}
// TODO(bugs.webrtc.org/11327): Make the following two methods non-virtual
// or completely remove them.
virtual int64_t TimeInMilliseconds() { return CurrentTime().ms(); }
virtual int64_t TimeInMicroseconds() { return CurrentTime().us(); }
// Retrieve an NTP absolute timestamp.
// Retrieve an NTP absolute timestamp (with an epoch of Jan 1, 1900).
virtual NtpTime CurrentNtpTime() = 0;
// Retrieve an NTP absolute timestamp in milliseconds.
virtual int64_t CurrentNtpInMilliseconds() = 0;
// TODO(bugs.webrtc.org/11327): Make the following method non-virtual
// or completely remove it.
virtual int64_t CurrentNtpInMilliseconds() { return CurrentNtpTime().ToMs(); }
// Returns an instance of the real-time system clock implementation.
static Clock* GetRealTimeClock();
@ -51,21 +57,16 @@ class RTC_EXPORT Clock {
class SimulatedClock : public Clock {
public:
// The constructors assume an epoch of Jan 1, 1970.
explicit SimulatedClock(int64_t initial_time_us);
explicit SimulatedClock(Timestamp initial_time);
~SimulatedClock() override;
// Return a timestamp relative to some arbitrary source; the source is fixed
// for this clock.
// Return a timestamp with an epoch of Jan 1, 1970.
Timestamp CurrentTime() override;
// Retrieve an NTP absolute timestamp.
NtpTime CurrentNtpTime() override;
// Converts an NTP timestamp to a millisecond timestamp.
int64_t CurrentNtpInMilliseconds() override;
// Advance the simulated clock with a given number of milliseconds or
// microseconds.
void AdvanceTimeMilliseconds(int64_t milliseconds);

View File

@ -10,6 +10,8 @@
#include "system_wrappers/include/clock.h"
#include "system_wrappers/include/field_trial.h"
#if defined(WEBRTC_WIN)
// Windows needs to be included before mmsystem.h
@ -29,57 +31,82 @@
#include "rtc_base/time_utils.h"
namespace webrtc {
namespace {
int64_t NtpOffsetUsCalledOnce() {
constexpr int64_t kNtpJan1970Sec = 2208988800;
int64_t clock_time = rtc::TimeMicros();
int64_t utc_time = rtc::TimeUTCMicros();
return utc_time - clock_time + kNtpJan1970Sec * rtc::kNumMicrosecsPerSec;
}
NtpTime TimeMicrosToNtp(int64_t time_us) {
static int64_t ntp_offset_us = NtpOffsetUsCalledOnce();
int64_t time_ntp_us = time_us + ntp_offset_us;
RTC_DCHECK_GE(time_ntp_us, 0); // Time before year 1900 is unsupported.
// Convert seconds to uint32 through uint64 for a well-defined cast.
// A wrap around, which will happen in 2036, is expected for NTP time.
uint32_t ntp_seconds =
static_cast<uint64_t>(time_ntp_us / rtc::kNumMicrosecsPerSec);
// Scale fractions of the second to NTP resolution.
constexpr int64_t kNtpFractionsInSecond = 1LL << 32;
int64_t us_fractions = time_ntp_us % rtc::kNumMicrosecsPerSec;
uint32_t ntp_fractions =
us_fractions * kNtpFractionsInSecond / rtc::kNumMicrosecsPerSec;
return NtpTime(ntp_seconds, ntp_fractions);
}
void GetSecondsAndFraction(const timeval& time,
uint32_t* seconds,
double* fraction) {
*seconds = time.tv_sec + kNtpJan1970;
*fraction = time.tv_usec / 1e6;
while (*fraction >= 1) {
--*fraction;
++*seconds;
}
while (*fraction < 0) {
++*fraction;
--*seconds;
}
}
} // namespace
class RealTimeClock : public Clock {
public:
RealTimeClock()
: use_system_independent_ntp_time_(!field_trial::IsEnabled(
"WebRTC-SystemIndependentNtpTimeKillSwitch")) {}
Timestamp CurrentTime() override {
return Timestamp::Micros(rtc::TimeMicros());
}
// Return a timestamp in milliseconds relative to some arbitrary source; the
// source is fixed for this clock.
int64_t TimeInMilliseconds() override { return rtc::TimeMillis(); }
// Return a timestamp in microseconds relative to some arbitrary source; the
// source is fixed for this clock.
int64_t TimeInMicroseconds() override { return rtc::TimeMicros(); }
// Retrieve an NTP absolute timestamp.
NtpTime CurrentNtpTime() override {
timeval tv = CurrentTimeVal();
double microseconds_in_seconds;
uint32_t seconds;
Adjust(tv, &seconds, &microseconds_in_seconds);
uint32_t fractions = static_cast<uint32_t>(
microseconds_in_seconds * kMagicNtpFractionalUnit + 0.5);
return NtpTime(seconds, fractions);
}
// Retrieve an NTP absolute timestamp in milliseconds.
int64_t CurrentNtpInMilliseconds() override {
timeval tv = CurrentTimeVal();
uint32_t seconds;
double microseconds_in_seconds;
Adjust(tv, &seconds, &microseconds_in_seconds);
return 1000 * static_cast<int64_t>(seconds) +
static_cast<int64_t>(1000.0 * microseconds_in_seconds + 0.5);
return use_system_independent_ntp_time_ ? TimeMicrosToNtp(rtc::TimeMicros())
: SystemDependentNtpTime();
}
protected:
virtual timeval CurrentTimeVal() = 0;
static void Adjust(const timeval& tv,
uint32_t* adjusted_s,
double* adjusted_us_in_s) {
*adjusted_s = tv.tv_sec + kNtpJan1970;
*adjusted_us_in_s = tv.tv_usec / 1e6;
private:
NtpTime SystemDependentNtpTime() {
uint32_t seconds;
double fraction;
GetSecondsAndFraction(CurrentTimeVal(), &seconds, &fraction);
if (*adjusted_us_in_s >= 1) {
*adjusted_us_in_s -= 1;
++*adjusted_s;
} else if (*adjusted_us_in_s < -1) {
*adjusted_us_in_s += 1;
--*adjusted_s;
}
return NtpTime(seconds, static_cast<uint32_t>(
fraction * kMagicNtpFractionalUnit + 0.5));
}
bool use_system_independent_ntp_time_;
};
#if defined(WINUWP)
@ -257,10 +284,6 @@ NtpTime SimulatedClock::CurrentNtpTime() {
return NtpTime(seconds, fractions);
}
int64_t SimulatedClock::CurrentNtpInMilliseconds() {
return TimeInMilliseconds() + 1000 * static_cast<int64_t>(kNtpJan1970);
}
void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) {
AdvanceTime(TimeDelta::Millis(milliseconds));
}