OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2004 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
(...skipping 14 matching lines...) Expand all Loading... |
25 #include <mmsystem.h> | 25 #include <mmsystem.h> |
26 #endif | 26 #endif |
27 | 27 |
28 #include "webrtc/base/checks.h" | 28 #include "webrtc/base/checks.h" |
29 #include "webrtc/base/timeutils.h" | 29 #include "webrtc/base/timeutils.h" |
30 | 30 |
31 #define EFFICIENT_IMPLEMENTATION 1 | 31 #define EFFICIENT_IMPLEMENTATION 1 |
32 | 32 |
33 namespace rtc { | 33 namespace rtc { |
34 | 34 |
35 const uint32 HALF = 0x80000000; | 35 const uint32_t HALF = 0x80000000; |
36 | 36 |
37 uint64 TimeNanos() { | 37 uint64_t TimeNanos() { |
38 int64 ticks = 0; | 38 int64_t ticks = 0; |
39 #if defined(WEBRTC_MAC) | 39 #if defined(WEBRTC_MAC) |
40 static mach_timebase_info_data_t timebase; | 40 static mach_timebase_info_data_t timebase; |
41 if (timebase.denom == 0) { | 41 if (timebase.denom == 0) { |
42 // Get the timebase if this is the first time we run. | 42 // Get the timebase if this is the first time we run. |
43 // Recommended by Apple's QA1398. | 43 // Recommended by Apple's QA1398. |
44 if (mach_timebase_info(&timebase) != KERN_SUCCESS) { | 44 if (mach_timebase_info(&timebase) != KERN_SUCCESS) { |
45 RTC_DCHECK(false); | 45 RTC_DCHECK(false); |
46 } | 46 } |
47 } | 47 } |
48 // Use timebase to convert absolute time tick units into nanoseconds. | 48 // Use timebase to convert absolute time tick units into nanoseconds. |
49 ticks = mach_absolute_time() * timebase.numer / timebase.denom; | 49 ticks = mach_absolute_time() * timebase.numer / timebase.denom; |
50 #elif defined(WEBRTC_POSIX) | 50 #elif defined(WEBRTC_POSIX) |
51 struct timespec ts; | 51 struct timespec ts; |
52 // TODO: Do we need to handle the case when CLOCK_MONOTONIC | 52 // TODO: Do we need to handle the case when CLOCK_MONOTONIC |
53 // is not supported? | 53 // is not supported? |
54 clock_gettime(CLOCK_MONOTONIC, &ts); | 54 clock_gettime(CLOCK_MONOTONIC, &ts); |
55 ticks = kNumNanosecsPerSec * static_cast<int64>(ts.tv_sec) + | 55 ticks = kNumNanosecsPerSec * static_cast<int64_t>(ts.tv_sec) + |
56 static_cast<int64>(ts.tv_nsec); | 56 static_cast<int64_t>(ts.tv_nsec); |
57 #elif defined(WEBRTC_WIN) | 57 #elif defined(WEBRTC_WIN) |
58 static volatile LONG last_timegettime = 0; | 58 static volatile LONG last_timegettime = 0; |
59 static volatile int64 num_wrap_timegettime = 0; | 59 static volatile int64_t num_wrap_timegettime = 0; |
60 volatile LONG* last_timegettime_ptr = &last_timegettime; | 60 volatile LONG* last_timegettime_ptr = &last_timegettime; |
61 DWORD now = timeGetTime(); | 61 DWORD now = timeGetTime(); |
62 // Atomically update the last gotten time | 62 // Atomically update the last gotten time |
63 DWORD old = InterlockedExchange(last_timegettime_ptr, now); | 63 DWORD old = InterlockedExchange(last_timegettime_ptr, now); |
64 if (now < old) { | 64 if (now < old) { |
65 // If now is earlier than old, there may have been a race between | 65 // If now is earlier than old, there may have been a race between |
66 // threads. | 66 // threads. |
67 // 0x0fffffff ~3.1 days, the code will not take that long to execute | 67 // 0x0fffffff ~3.1 days, the code will not take that long to execute |
68 // so it must have been a wrap around. | 68 // so it must have been a wrap around. |
69 if (old > 0xf0000000 && now < 0x0fffffff) { | 69 if (old > 0xf0000000 && now < 0x0fffffff) { |
70 num_wrap_timegettime++; | 70 num_wrap_timegettime++; |
71 } | 71 } |
72 } | 72 } |
73 ticks = now + (num_wrap_timegettime << 32); | 73 ticks = now + (num_wrap_timegettime << 32); |
74 // TODO: Calculate with nanosecond precision. Otherwise, we're just | 74 // TODO: Calculate with nanosecond precision. Otherwise, we're just |
75 // wasting a multiply and divide when doing Time() on Windows. | 75 // wasting a multiply and divide when doing Time() on Windows. |
76 ticks = ticks * kNumNanosecsPerMillisec; | 76 ticks = ticks * kNumNanosecsPerMillisec; |
77 #endif | 77 #endif |
78 return ticks; | 78 return ticks; |
79 } | 79 } |
80 | 80 |
81 uint32 Time() { | 81 uint32_t Time() { |
82 return static_cast<uint32>(TimeNanos() / kNumNanosecsPerMillisec); | 82 return static_cast<uint32_t>(TimeNanos() / kNumNanosecsPerMillisec); |
83 } | 83 } |
84 | 84 |
85 uint64 TimeMicros() { | 85 uint64_t TimeMicros() { |
86 return static_cast<uint64>(TimeNanos() / kNumNanosecsPerMicrosec); | 86 return static_cast<uint64_t>(TimeNanos() / kNumNanosecsPerMicrosec); |
87 } | 87 } |
88 | 88 |
89 #if defined(WEBRTC_WIN) | 89 #if defined(WEBRTC_WIN) |
90 static const uint64 kFileTimeToUnixTimeEpochOffset = 116444736000000000ULL; | 90 static const uint64_t kFileTimeToUnixTimeEpochOffset = 116444736000000000ULL; |
91 | 91 |
92 struct timeval { | 92 struct timeval { |
93 long tv_sec, tv_usec; // NOLINT | 93 long tv_sec, tv_usec; // NOLINT |
94 }; | 94 }; |
95 | 95 |
96 // Emulate POSIX gettimeofday(). | 96 // Emulate POSIX gettimeofday(). |
97 // Based on breakpad/src/third_party/glog/src/utilities.cc | 97 // Based on breakpad/src/third_party/glog/src/utilities.cc |
98 static int gettimeofday(struct timeval *tv, void *tz) { | 98 static int gettimeofday(struct timeval *tv, void *tz) { |
99 // FILETIME is measured in tens of microseconds since 1601-01-01 UTC. | 99 // FILETIME is measured in tens of microseconds since 1601-01-01 UTC. |
100 FILETIME ft; | 100 FILETIME ft; |
101 GetSystemTimeAsFileTime(&ft); | 101 GetSystemTimeAsFileTime(&ft); |
102 | 102 |
103 LARGE_INTEGER li; | 103 LARGE_INTEGER li; |
104 li.LowPart = ft.dwLowDateTime; | 104 li.LowPart = ft.dwLowDateTime; |
105 li.HighPart = ft.dwHighDateTime; | 105 li.HighPart = ft.dwHighDateTime; |
106 | 106 |
107 // Convert to seconds and microseconds since Unix time Epoch. | 107 // Convert to seconds and microseconds since Unix time Epoch. |
108 int64 micros = (li.QuadPart - kFileTimeToUnixTimeEpochOffset) / 10; | 108 int64_t micros = (li.QuadPart - kFileTimeToUnixTimeEpochOffset) / 10; |
109 tv->tv_sec = static_cast<long>(micros / kNumMicrosecsPerSec); // NOLINT | 109 tv->tv_sec = static_cast<long>(micros / kNumMicrosecsPerSec); // NOLINT |
110 tv->tv_usec = static_cast<long>(micros % kNumMicrosecsPerSec); // NOLINT | 110 tv->tv_usec = static_cast<long>(micros % kNumMicrosecsPerSec); // NOLINT |
111 | 111 |
112 return 0; | 112 return 0; |
113 } | 113 } |
114 | 114 |
115 // Emulate POSIX gmtime_r(). | 115 // Emulate POSIX gmtime_r(). |
116 static struct tm *gmtime_r(const time_t *timep, struct tm *result) { | 116 static struct tm *gmtime_r(const time_t *timep, struct tm *result) { |
117 // On Windows, gmtime is thread safe. | 117 // On Windows, gmtime is thread safe. |
118 struct tm *tm = gmtime(timep); // NOLINT | 118 struct tm *tm = gmtime(timep); // NOLINT |
119 if (tm == NULL) { | 119 if (tm == NULL) { |
120 return NULL; | 120 return NULL; |
121 } | 121 } |
122 *result = *tm; | 122 *result = *tm; |
123 return result; | 123 return result; |
124 } | 124 } |
125 #endif // WEBRTC_WIN | 125 #endif // WEBRTC_WIN |
126 | 126 |
127 void CurrentTmTime(struct tm *tm, int *microseconds) { | 127 void CurrentTmTime(struct tm *tm, int *microseconds) { |
128 struct timeval timeval; | 128 struct timeval timeval; |
129 if (gettimeofday(&timeval, NULL) < 0) { | 129 if (gettimeofday(&timeval, NULL) < 0) { |
130 // Incredibly unlikely code path. | 130 // Incredibly unlikely code path. |
131 timeval.tv_sec = timeval.tv_usec = 0; | 131 timeval.tv_sec = timeval.tv_usec = 0; |
132 } | 132 } |
133 time_t secs = timeval.tv_sec; | 133 time_t secs = timeval.tv_sec; |
134 gmtime_r(&secs, tm); | 134 gmtime_r(&secs, tm); |
135 *microseconds = timeval.tv_usec; | 135 *microseconds = timeval.tv_usec; |
136 } | 136 } |
137 | 137 |
138 uint32 TimeAfter(int32 elapsed) { | 138 uint32_t TimeAfter(int32_t elapsed) { |
139 RTC_DCHECK_GE(elapsed, 0); | 139 RTC_DCHECK_GE(elapsed, 0); |
140 RTC_DCHECK_LT(static_cast<uint32>(elapsed), HALF); | 140 RTC_DCHECK_LT(static_cast<uint32_t>(elapsed), HALF); |
141 return Time() + elapsed; | 141 return Time() + elapsed; |
142 } | 142 } |
143 | 143 |
144 bool TimeIsBetween(uint32 earlier, uint32 middle, uint32 later) { | 144 bool TimeIsBetween(uint32_t earlier, uint32_t middle, uint32_t later) { |
145 if (earlier <= later) { | 145 if (earlier <= later) { |
146 return ((earlier <= middle) && (middle <= later)); | 146 return ((earlier <= middle) && (middle <= later)); |
147 } else { | 147 } else { |
148 return !((later < middle) && (middle < earlier)); | 148 return !((later < middle) && (middle < earlier)); |
149 } | 149 } |
150 } | 150 } |
151 | 151 |
152 bool TimeIsLaterOrEqual(uint32 earlier, uint32 later) { | 152 bool TimeIsLaterOrEqual(uint32_t earlier, uint32_t later) { |
153 #if EFFICIENT_IMPLEMENTATION | 153 #if EFFICIENT_IMPLEMENTATION |
154 int32 diff = later - earlier; | 154 int32_t diff = later - earlier; |
155 return (diff >= 0 && static_cast<uint32>(diff) < HALF); | 155 return (diff >= 0 && static_cast<uint32_t>(diff) < HALF); |
156 #else | 156 #else |
157 const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF); | 157 const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF); |
158 return later_or_equal; | 158 return later_or_equal; |
159 #endif | 159 #endif |
160 } | 160 } |
161 | 161 |
162 bool TimeIsLater(uint32 earlier, uint32 later) { | 162 bool TimeIsLater(uint32_t earlier, uint32_t later) { |
163 #if EFFICIENT_IMPLEMENTATION | 163 #if EFFICIENT_IMPLEMENTATION |
164 int32 diff = later - earlier; | 164 int32_t diff = later - earlier; |
165 return (diff > 0 && static_cast<uint32>(diff) < HALF); | 165 return (diff > 0 && static_cast<uint32_t>(diff) < HALF); |
166 #else | 166 #else |
167 const bool earlier_or_equal = TimeIsBetween(later, earlier, later + HALF); | 167 const bool earlier_or_equal = TimeIsBetween(later, earlier, later + HALF); |
168 return !earlier_or_equal; | 168 return !earlier_or_equal; |
169 #endif | 169 #endif |
170 } | 170 } |
171 | 171 |
172 int32 TimeDiff(uint32 later, uint32 earlier) { | 172 int32_t TimeDiff(uint32_t later, uint32_t earlier) { |
173 #if EFFICIENT_IMPLEMENTATION | 173 #if EFFICIENT_IMPLEMENTATION |
174 return later - earlier; | 174 return later - earlier; |
175 #else | 175 #else |
176 const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF); | 176 const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF); |
177 if (later_or_equal) { | 177 if (later_or_equal) { |
178 if (earlier <= later) { | 178 if (earlier <= later) { |
179 return static_cast<long>(later - earlier); | 179 return static_cast<long>(later - earlier); |
180 } else { | 180 } else { |
181 return static_cast<long>(later + (UINT32_MAX - earlier) + 1); | 181 return static_cast<long>(later + (UINT32_MAX - earlier) + 1); |
182 } | 182 } |
183 } else { | 183 } else { |
184 if (later <= earlier) { | 184 if (later <= earlier) { |
185 return -static_cast<long>(earlier - later); | 185 return -static_cast<long>(earlier - later); |
186 } else { | 186 } else { |
187 return -static_cast<long>(earlier + (UINT32_MAX - later) + 1); | 187 return -static_cast<long>(earlier + (UINT32_MAX - later) + 1); |
188 } | 188 } |
189 } | 189 } |
190 #endif | 190 #endif |
191 } | 191 } |
192 | 192 |
193 TimestampWrapAroundHandler::TimestampWrapAroundHandler() | 193 TimestampWrapAroundHandler::TimestampWrapAroundHandler() |
194 : last_ts_(0), num_wrap_(0) {} | 194 : last_ts_(0), num_wrap_(0) {} |
195 | 195 |
196 int64 TimestampWrapAroundHandler::Unwrap(uint32 ts) { | 196 int64_t TimestampWrapAroundHandler::Unwrap(uint32_t ts) { |
197 if (ts < last_ts_) { | 197 if (ts < last_ts_) { |
198 if (last_ts_ > 0xf0000000 && ts < 0x0fffffff) { | 198 if (last_ts_ > 0xf0000000 && ts < 0x0fffffff) { |
199 ++num_wrap_; | 199 ++num_wrap_; |
200 } | 200 } |
201 } | 201 } |
202 last_ts_ = ts; | 202 last_ts_ = ts; |
203 int64_t unwrapped_ts = ts + (num_wrap_ << 32); | 203 int64_t unwrapped_ts = ts + (num_wrap_ << 32); |
204 return unwrapped_ts; | 204 return unwrapped_ts; |
205 } | 205 } |
206 | 206 |
207 } // namespace rtc | 207 } // namespace rtc |
OLD | NEW |