blob: 88c99d6a68a2e0f47ca60c5491ba06dc6fe570e9 [file] [log] [blame]
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +00001/*
2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020011#include "system_wrappers/include/clock.h"
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000012
Steve Anton10542f22019-01-11 09:11:00 -080013#include "rtc_base/time_utils.h"
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000014
15namespace webrtc {
Paul Hallak704d6e52021-04-08 14:57:45 +020016namespace {
17
18int64_t NtpOffsetUsCalledOnce() {
19 constexpr int64_t kNtpJan1970Sec = 2208988800;
20 int64_t clock_time = rtc::TimeMicros();
21 int64_t utc_time = rtc::TimeUTCMicros();
22 return utc_time - clock_time + kNtpJan1970Sec * rtc::kNumMicrosecsPerSec;
23}
24
25NtpTime TimeMicrosToNtp(int64_t time_us) {
26 static int64_t ntp_offset_us = NtpOffsetUsCalledOnce();
27
28 int64_t time_ntp_us = time_us + ntp_offset_us;
29 RTC_DCHECK_GE(time_ntp_us, 0); // Time before year 1900 is unsupported.
30
31 // Convert seconds to uint32 through uint64 for a well-defined cast.
32 // A wrap around, which will happen in 2036, is expected for NTP time.
33 uint32_t ntp_seconds =
34 static_cast<uint64_t>(time_ntp_us / rtc::kNumMicrosecsPerSec);
35
36 // Scale fractions of the second to NTP resolution.
37 constexpr int64_t kNtpFractionsInSecond = 1LL << 32;
38 int64_t us_fractions = time_ntp_us % rtc::kNumMicrosecsPerSec;
39 uint32_t ntp_fractions =
40 us_fractions * kNtpFractionsInSecond / rtc::kNumMicrosecsPerSec;
41
42 return NtpTime(ntp_seconds, ntp_fractions);
43}
44
Paul Hallak704d6e52021-04-08 14:57:45 +020045} // namespace
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000046
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000047class RealTimeClock : public Clock {
Paul Hallak704d6e52021-04-08 14:57:45 +020048 public:
Danil Chapovalovfbe66722022-05-11 13:59:57 +020049 RealTimeClock() = default;
Paul Hallak704d6e52021-04-08 14:57:45 +020050
Danil Chapovalov0c626af2020-02-10 11:16:00 +010051 Timestamp CurrentTime() override {
52 return Timestamp::Micros(rtc::TimeMicros());
53 }
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000054
Paul Hallakb59e9042021-05-20 17:21:49 +020055 NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override {
Paul Hallakb59e9042021-05-20 17:21:49 +020056 return TimeMicrosToNtp(timestamp.us());
57 }
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000058};
59
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000060Clock* Clock::GetRealTimeClock() {
Danil Chapovalovfbe66722022-05-11 13:59:57 +020061 static Clock* const clock = new RealTimeClock();
Mirko Bonadei6c092d22018-09-10 13:27:11 +020062 return clock;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000063}
64
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000065SimulatedClock::SimulatedClock(int64_t initial_time_us)
Niels Möller9308b7a2020-11-03 13:55:44 +010066 : time_us_(initial_time_us) {}
Sebastian Jansson4de31152019-06-11 08:52:11 +020067
68SimulatedClock::SimulatedClock(Timestamp initial_time)
Niels Möller9308b7a2020-11-03 13:55:44 +010069 : SimulatedClock(initial_time.us()) {}
henrik.lundin@webrtc.org59336e82014-05-27 09:34:58 +000070
Karl Wiberg79eb1d92017-11-08 12:26:07 +010071SimulatedClock::~SimulatedClock() {}
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000072
Sebastian Jansson4de31152019-06-11 08:52:11 +020073Timestamp SimulatedClock::CurrentTime() {
Niels Möller9308b7a2020-11-03 13:55:44 +010074 return Timestamp::Micros(time_us_.load(std::memory_order_relaxed));
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000075}
76
Paul Hallakb59e9042021-05-20 17:21:49 +020077NtpTime SimulatedClock::ConvertTimestampToNtpTime(Timestamp timestamp) {
78 int64_t now_us = timestamp.us();
79 uint32_t seconds = (now_us / 1'000'000) + kNtpJan1970;
80 uint32_t fractions = static_cast<uint32_t>(
81 (now_us % 1'000'000) * kMagicNtpFractionalUnit / 1'000'000);
danilchap21dc1892017-03-07 02:51:09 -080082 return NtpTime(seconds, fractions);
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000083}
84
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000085void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) {
Danil Chapovalov0c626af2020-02-10 11:16:00 +010086 AdvanceTime(TimeDelta::Millis(milliseconds));
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000087}
88
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +000089void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) {
Danil Chapovalov0c626af2020-02-10 11:16:00 +010090 AdvanceTime(TimeDelta::Micros(microseconds));
Sebastian Jansson4de31152019-06-11 08:52:11 +020091}
92
Niels Möller9308b7a2020-11-03 13:55:44 +010093// TODO(bugs.webrtc.org(12102): It's desirable to let a single thread own
94// advancement of the clock. We could then replace this read-modify-write
95// operation with just a thread checker. But currently, that breaks a couple of
96// tests, in particular, RepeatingTaskTest.ClockIntegration and
97// CallStatsTest.LastProcessedRtt.
Sebastian Jansson4de31152019-06-11 08:52:11 +020098void SimulatedClock::AdvanceTime(TimeDelta delta) {
Niels Möller9308b7a2020-11-03 13:55:44 +010099 time_us_.fetch_add(delta.us(), std::memory_order_relaxed);
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000100}
101
Nico Weber22f99252019-02-20 10:13:16 -0500102} // namespace webrtc