1 /* 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 11 #include "system_wrappers/include/clock.h" 12 13 #include "rtc_base/time_utils.h" 14 15 namespace webrtc { 16 namespace { 17 NtpOffsetUsCalledOnce()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 TimeMicrosToNtp(int64_t time_us)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 45 } // namespace 46 47 class RealTimeClock : public Clock { 48 public: 49 RealTimeClock() = default; 50 CurrentTime()51 Timestamp CurrentTime() override { 52 return Timestamp::Micros(rtc::TimeMicros()); 53 } 54 ConvertTimestampToNtpTime(Timestamp timestamp)55 NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override { 56 return TimeMicrosToNtp(timestamp.us()); 57 } 58 }; 59 GetRealTimeClock()60Clock* Clock::GetRealTimeClock() { 61 static Clock* const clock = new RealTimeClock(); 62 return clock; 63 } 64 SimulatedClock(int64_t initial_time_us)65SimulatedClock::SimulatedClock(int64_t initial_time_us) 66 : time_us_(initial_time_us) {} 67 SimulatedClock(Timestamp initial_time)68SimulatedClock::SimulatedClock(Timestamp initial_time) 69 : SimulatedClock(initial_time.us()) {} 70 ~SimulatedClock()71SimulatedClock::~SimulatedClock() {} 72 CurrentTime()73Timestamp SimulatedClock::CurrentTime() { 74 return Timestamp::Micros(time_us_.load(std::memory_order_relaxed)); 75 } 76 ConvertTimestampToNtpTime(Timestamp timestamp)77NtpTime 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); 82 return NtpTime(seconds, fractions); 83 } 84 AdvanceTimeMilliseconds(int64_t milliseconds)85void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) { 86 AdvanceTime(TimeDelta::Millis(milliseconds)); 87 } 88 AdvanceTimeMicroseconds(int64_t microseconds)89void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) { 90 AdvanceTime(TimeDelta::Micros(microseconds)); 91 } 92 93 // 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. AdvanceTime(TimeDelta delta)98void SimulatedClock::AdvanceTime(TimeDelta delta) { 99 time_us_.fetch_add(delta.us(), std::memory_order_relaxed); 100 } 101 102 } // namespace webrtc 103