summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/system_wrappers/source/clock.cc
blob: f7460b831c40f7aa5ce138fe52ffb6de0b84903b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
/*
 *  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 "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);
}

}  // namespace

class RealTimeClock : public Clock {
 public:
  RealTimeClock() = default;

  Timestamp CurrentTime() override {
    return Timestamp::Micros(rtc::TimeMicros());
  }

  NtpTime ConvertTimestampToNtpTime(Timestamp timestamp) override {
    return TimeMicrosToNtp(timestamp.us());
  }
};

Clock* Clock::GetRealTimeClockRaw() {
  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