| 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 |