| /* | 
 |  *  Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 
 |  * | 
 |  *  Use of this source code is governed by a BSD-style license | 
 |  *  that can be found in the LICENSE file in the root of the source | 
 |  *  tree. An additional intellectual property rights grant can be found | 
 |  *  in the file PATENTS.  All contributing project authors may | 
 |  *  be found in the AUTHORS file in the root of the source tree. | 
 |  */ | 
 |  | 
 | #include "system_wrappers/include/clock.h" | 
 |  | 
 | #include <atomic> | 
 | #include <cstdint> | 
 |  | 
 | #include "api/units/time_delta.h" | 
 | #include "api/units/timestamp.h" | 
 | #include "rtc_base/checks.h" | 
 | #include "rtc_base/time_utils.h" | 
 | #include "system_wrappers/include/ntp_time.h" | 
 |  | 
 | namespace webrtc { | 
 | namespace { | 
 |  | 
 | int64_t NtpOffsetUsCalledOnce() { | 
 |   constexpr int64_t kNtpJan1970Sec = 2208988800; | 
 |   int64_t clock_time = TimeMicros(); | 
 |   int64_t utc_time = TimeUTCMicros(); | 
 |   return utc_time - clock_time + kNtpJan1970Sec * 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 / kNumMicrosecsPerSec); | 
 |  | 
 |   // Scale fractions of the second to NTP resolution. | 
 |   constexpr int64_t kNtpFractionsInSecond = 1LL << 32; | 
 |   int64_t us_fractions = time_ntp_us % kNumMicrosecsPerSec; | 
 |   uint32_t ntp_fractions = | 
 |       us_fractions * kNtpFractionsInSecond / kNumMicrosecsPerSec; | 
 |  | 
 |   return NtpTime(ntp_seconds, ntp_fractions); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | class RealTimeClock : public Clock { | 
 |  public: | 
 |   RealTimeClock() = default; | 
 |  | 
 |   Timestamp CurrentTime() override { return Timestamp::Micros(TimeMicros()); } | 
 |  | 
 |   NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override { | 
 |     return TimeMicrosToNtp(timestamp.us()); | 
 |   } | 
 | }; | 
 |  | 
 | Clock* Clock::GetRealTimeClock() { | 
 |   static Clock* const clock = new RealTimeClock(); | 
 |   return clock; | 
 | } | 
 |  | 
 | SimulatedClock::SimulatedClock(int64_t initial_time_us) | 
 |     : time_us_(initial_time_us) {} | 
 |  | 
 | SimulatedClock::SimulatedClock(Timestamp initial_time) | 
 |     : SimulatedClock(initial_time.us()) {} | 
 |  | 
 | SimulatedClock::~SimulatedClock() {} | 
 |  | 
 | Timestamp SimulatedClock::CurrentTime() { | 
 |   return Timestamp::Micros(time_us_.load(std::memory_order_relaxed)); | 
 | } | 
 |  | 
 | 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<uint32_t>( | 
 |       (now_us % 1'000'000) * kMagicNtpFractionalUnit / 1'000'000); | 
 |   return NtpTime(seconds, fractions); | 
 | } | 
 |  | 
 | void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) { | 
 |   AdvanceTime(TimeDelta::Millis(milliseconds)); | 
 | } | 
 |  | 
 | void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) { | 
 |   AdvanceTime(TimeDelta::Micros(microseconds)); | 
 | } | 
 |  | 
 | // TODO(bugs.webrtc.org(12102): It's desirable to let a single thread own | 
 | // advancement of the clock. We could then replace this read-modify-write | 
 | // operation with just a thread checker. But currently, that breaks a couple of | 
 | // tests, in particular, RepeatingTaskTest.ClockIntegration and | 
 | // CallStatsTest.LastProcessedRtt. | 
 | void SimulatedClock::AdvanceTime(TimeDelta delta) { | 
 |   time_us_.fetch_add(delta.us(), std::memory_order_relaxed); | 
 | } | 
 |  | 
 | }  // namespace webrtc |