blob: b101e0581617adb229c0dfe6f94a08513fefde46 [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
11#include "webrtc/system_wrappers/interface/clock.h"
12
13#if defined(_WIN32)
pbos@webrtc.orgacaf3a12013-05-27 15:07:45 +000014// Windows needs to be included before mmsystem.h
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000015#include <Windows.h>
16#include <WinSock.h>
17#include <MMSystem.h>
18#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
19#include <sys/time.h>
20#include <time.h>
21#endif
22
23#include "webrtc/system_wrappers/interface/tick_util.h"
24
25namespace webrtc {
26
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +000027const double kNtpFracPerMs = 4.294967296E6;
28
29int64_t Clock::NtpToMs(uint32_t ntp_secs, uint32_t ntp_frac) {
30 const double ntp_frac_ms = static_cast<double>(ntp_frac) / kNtpFracPerMs;
31 return 1000 * static_cast<int64_t>(ntp_secs) +
32 static_cast<int64_t>(ntp_frac_ms + 0.5);
33}
34
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000035class RealTimeClock : public Clock {
36 // Return a timestamp in milliseconds relative to some arbitrary source; the
37 // source is fixed for this clock.
pbos@webrtc.orga2a27182013-08-01 17:26:15 +000038 virtual int64_t TimeInMilliseconds() OVERRIDE {
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000039 return TickTime::MillisecondTimestamp();
40 }
41
42 // Return a timestamp in microseconds relative to some arbitrary source; the
43 // source is fixed for this clock.
pbos@webrtc.orga2a27182013-08-01 17:26:15 +000044 virtual int64_t TimeInMicroseconds() OVERRIDE {
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000045 return TickTime::MicrosecondTimestamp();
46 }
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +000047
48 // Retrieve an NTP absolute timestamp in seconds and fractions of a second.
pbos@webrtc.orga2a27182013-08-01 17:26:15 +000049 virtual void CurrentNtp(uint32_t& seconds, uint32_t& fractions) OVERRIDE {
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +000050 timeval tv = CurrentTimeVal();
51 double microseconds_in_seconds;
52 Adjust(tv, &seconds, &microseconds_in_seconds);
53 fractions = static_cast<uint32_t>(
54 microseconds_in_seconds * kMagicNtpFractionalUnit + 0.5);
55 }
56
57 // Retrieve an NTP absolute timestamp in milliseconds.
pbos@webrtc.orga2a27182013-08-01 17:26:15 +000058 virtual int64_t CurrentNtpInMilliseconds() OVERRIDE {
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +000059 timeval tv = CurrentTimeVal();
60 uint32_t seconds;
61 double microseconds_in_seconds;
62 Adjust(tv, &seconds, &microseconds_in_seconds);
63 return 1000 * static_cast<int64_t>(seconds) +
64 static_cast<int64_t>(1000.0 * microseconds_in_seconds + 0.5);
65 }
66
67 protected:
68 virtual timeval CurrentTimeVal() const = 0;
69
70 static void Adjust(const timeval& tv, uint32_t* adjusted_s,
71 double* adjusted_us_in_s) {
72 *adjusted_s = tv.tv_sec + kNtpJan1970;
73 *adjusted_us_in_s = tv.tv_usec / 1e6;
74
75 if (*adjusted_us_in_s >= 1) {
76 *adjusted_us_in_s -= 1;
77 ++*adjusted_s;
78 } else if (*adjusted_us_in_s < -1) {
79 *adjusted_us_in_s += 1;
80 --*adjusted_s;
81 }
82 }
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000083};
84
85#if defined(_WIN32)
86class WindowsRealTimeClock : public RealTimeClock {
87 public:
wu@webrtc.org75718cf2014-05-15 23:54:14 +000088 WindowsRealTimeClock() {}
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000089
90 virtual ~WindowsRealTimeClock() {}
91
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +000092 protected:
pbos@webrtc.orga2a27182013-08-01 17:26:15 +000093 virtual timeval CurrentTimeVal() const OVERRIDE {
pbos@webrtc.org046deb92013-04-09 09:06:11 +000094 const uint64_t FILETIME_1970 = 0x019db1ded53e8000;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000095
96 FILETIME StartTime;
pbos@webrtc.org046deb92013-04-09 09:06:11 +000097 uint64_t Time;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +000098 struct timeval tv;
99
wu@webrtc.org75718cf2014-05-15 23:54:14 +0000100 GetSystemTimeAsFileTime(&StartTime);
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000101
pbos@webrtc.org046deb92013-04-09 09:06:11 +0000102 Time = (((uint64_t) StartTime.dwHighDateTime) << 32) +
103 (uint64_t) StartTime.dwLowDateTime;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000104
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000105 // Convert the hecto-nano second time to tv format.
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000106 Time -= FILETIME_1970;
107
pbos@webrtc.org046deb92013-04-09 09:06:11 +0000108 tv.tv_sec = (uint32_t)(Time / (uint64_t)10000000);
109 tv.tv_usec = (uint32_t)((Time % (uint64_t)10000000) / 10);
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000110 return tv;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000111 }
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000112};
113
114#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
115class UnixRealTimeClock : public RealTimeClock {
116 public:
117 UnixRealTimeClock() {}
118
119 virtual ~UnixRealTimeClock() {}
120
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000121 protected:
pbos@webrtc.orga2a27182013-08-01 17:26:15 +0000122 virtual timeval CurrentTimeVal() const OVERRIDE {
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000123 struct timeval tv;
124 struct timezone tz;
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000125 tz.tz_minuteswest = 0;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000126 tz.tz_dsttime = 0;
127 gettimeofday(&tv, &tz);
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000128 return tv;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000129 }
130};
131#endif
132
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000133Clock* Clock::GetRealTimeClock() {
134#if defined(_WIN32)
wu@webrtc.org75718cf2014-05-15 23:54:14 +0000135 static WindowsRealTimeClock clock;
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000136 return &clock;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000137#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000138 static UnixRealTimeClock clock;
139 return &clock;
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000140#else
141 return NULL;
142#endif
143}
144
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000145SimulatedClock::SimulatedClock(int64_t initial_time_us)
146 : time_us_(initial_time_us) {}
147
148int64_t SimulatedClock::TimeInMilliseconds() {
149 return (time_us_ + 500) / 1000;
150}
151
152int64_t SimulatedClock::TimeInMicroseconds() {
153 return time_us_;
154}
155
156void SimulatedClock::CurrentNtp(uint32_t& seconds, uint32_t& fractions) {
157 seconds = (TimeInMilliseconds() / 1000) + kNtpJan1970;
158 fractions = (uint32_t)((TimeInMilliseconds() % 1000) *
159 kMagicNtpFractionalUnit / 1000);
160}
161
stefan@webrtc.orgb8e7f4c2013-04-12 11:56:23 +0000162int64_t SimulatedClock::CurrentNtpInMilliseconds() {
163 return TimeInMilliseconds() + 1000 * static_cast<int64_t>(kNtpJan1970);
164}
165
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000166void SimulatedClock::AdvanceTimeMilliseconds(int64_t milliseconds) {
167 AdvanceTimeMicroseconds(1000 * milliseconds);
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000168}
169
stefan@webrtc.orga678a3b2013-01-21 07:42:11 +0000170void SimulatedClock::AdvanceTimeMicroseconds(int64_t microseconds) {
stefan@webrtc.org20ed36d2013-01-17 14:01:20 +0000171 time_us_ += microseconds;
172}
173
174}; // namespace webrtc