147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org/* 247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Copyright 2004 The WebRTC Project Authors. All rights reserved. 347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * 447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * Use of this source code is governed by a BSD-style license 547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * that can be found in the LICENSE file in the root of the source 647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * tree. An additional intellectual property rights grant can be found 747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * in the file PATENTS. All contributing project authors may 847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org * be found in the AUTHORS file in the root of the source tree. 947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org */ 1047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <stdint.h> 1247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 1347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_POSIX) 1447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <sys/time.h> 1547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC) 1647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <mach/mach_time.h> 1747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 1847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 1947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 2047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN) 214dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org#ifndef WIN32_LEAN_AND_MEAN 2247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define WIN32_LEAN_AND_MEAN 234dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org#endif 2447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <windows.h> 2547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include <mmsystem.h> 2647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 2747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 284dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org#include "webrtc/base/checks.h" 2947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#include "webrtc/base/timeutils.h" 3047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#define EFFICIENT_IMPLEMENTATION 1 3247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgnamespace rtc { 3447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgconst uint32 HALF = 0x80000000; 3647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 3747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint64 TimeNanos() { 3847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int64 ticks = 0; 3947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_MAC) 4047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static mach_timebase_info_data_t timebase; 4147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (timebase.denom == 0) { 4247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Get the timebase if this is the first time we run. 4347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Recommended by Apple's QA1398. 444dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org if (mach_timebase_info(&timebase) != KERN_SUCCESS) { 454dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org DCHECK(false); 464dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org } 4747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 4847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Use timebase to convert absolute time tick units into nanoseconds. 4947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ticks = mach_absolute_time() * timebase.numer / timebase.denom; 5047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_POSIX) 5147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org struct timespec ts; 5247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: Do we need to handle the case when CLOCK_MONOTONIC 5347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // is not supported? 5447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org clock_gettime(CLOCK_MONOTONIC, &ts); 5547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ticks = kNumNanosecsPerSec * static_cast<int64>(ts.tv_sec) + 5647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static_cast<int64>(ts.tv_nsec); 5747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#elif defined(WEBRTC_WIN) 5847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static volatile LONG last_timegettime = 0; 5947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org static volatile int64 num_wrap_timegettime = 0; 6047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org volatile LONG* last_timegettime_ptr = &last_timegettime; 6147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DWORD now = timeGetTime(); 6247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Atomically update the last gotten time 6347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org DWORD old = InterlockedExchange(last_timegettime_ptr, now); 6447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (now < old) { 6547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // If now is earlier than old, there may have been a race between 6647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // threads. 6747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // 0x0fffffff ~3.1 days, the code will not take that long to execute 6847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // so it must have been a wrap around. 6947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (old > 0xf0000000 && now < 0x0fffffff) { 7047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org num_wrap_timegettime++; 7147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 7247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 7347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ticks = now + (num_wrap_timegettime << 32); 7447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // TODO: Calculate with nanosecond precision. Otherwise, we're just 7547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // wasting a multiply and divide when doing Time() on Windows. 7647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org ticks = ticks * kNumNanosecsPerMillisec; 7747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 7847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ticks; 7947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint32 Time() { 8247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<uint32>(TimeNanos() / kNumNanosecsPerMillisec); 8347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint64 TimeMicros() { 8647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<uint64>(TimeNanos() / kNumNanosecsPerMicrosec); 8747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 8847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 8947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if defined(WEBRTC_WIN) 9047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic const uint64 kFileTimeToUnixTimeEpochOffset = 116444736000000000ULL; 9147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstruct timeval { 9347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org long tv_sec, tv_usec; // NOLINT 9447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org}; 9547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 9647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Emulate POSIX gettimeofday(). 9747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Based on breakpad/src/third_party/glog/src/utilities.cc 9847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic int gettimeofday(struct timeval *tv, void *tz) { 9947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // FILETIME is measured in tens of microseconds since 1601-01-01 UTC. 10047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org FILETIME ft; 10147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org GetSystemTimeAsFileTime(&ft); 10247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org LARGE_INTEGER li; 10447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org li.LowPart = ft.dwLowDateTime; 10547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org li.HighPart = ft.dwHighDateTime; 10647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 10747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Convert to seconds and microseconds since Unix time Epoch. 10847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int64 micros = (li.QuadPart - kFileTimeToUnixTimeEpochOffset) / 10; 10947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org tv->tv_sec = static_cast<long>(micros / kNumMicrosecsPerSec); // NOLINT 11047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org tv->tv_usec = static_cast<long>(micros % kNumMicrosecsPerSec); // NOLINT 11147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return 0; 11347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 11447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 11547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org// Emulate POSIX gmtime_r(). 11647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgstatic struct tm *gmtime_r(const time_t *timep, struct tm *result) { 11747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // On Windows, gmtime is thread safe. 11847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org struct tm *tm = gmtime(timep); // NOLINT 11947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (tm == NULL) { 12047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return NULL; 12147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 12247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *result = *tm; 12347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return result; 12447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 1254dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org#endif // WEBRTC_WIN 12647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 12747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgvoid CurrentTmTime(struct tm *tm, int *microseconds) { 12847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org struct timeval timeval; 12947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (gettimeofday(&timeval, NULL) < 0) { 13047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org // Incredibly unlikely code path. 13147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org timeval.tv_sec = timeval.tv_usec = 0; 13247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 13347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org time_t secs = timeval.tv_sec; 13447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org gmtime_r(&secs, tm); 13547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org *microseconds = timeval.tv_usec; 13647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 13747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 13847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orguint32 TimeAfter(int32 elapsed) { 1394dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org DCHECK_GE(elapsed, 0); 1404dc8e4e9752f6512961a49a2b6af3b7143adfac2andrew@webrtc.org DCHECK_LT(static_cast<uint32>(elapsed), HALF); 14147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return Time() + elapsed; 14247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 14347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 14447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool TimeIsBetween(uint32 earlier, uint32 middle, uint32 later) { 14547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (earlier <= later) { 14647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return ((earlier <= middle) && (middle <= later)); 14747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 14847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return !((later < middle) && (middle < earlier)); 14947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 15047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 15147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 15247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool TimeIsLaterOrEqual(uint32 earlier, uint32 later) { 15347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if EFFICIENT_IMPLEMENTATION 15447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int32 diff = later - earlier; 15547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return (diff >= 0 && static_cast<uint32>(diff) < HALF); 15647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 15747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF); 15847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return later_or_equal; 15947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 16047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 16147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 16247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgbool TimeIsLater(uint32 earlier, uint32 later) { 16347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if EFFICIENT_IMPLEMENTATION 16447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org int32 diff = later - earlier; 16547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return (diff > 0 && static_cast<uint32>(diff) < HALF); 16647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 16747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const bool earlier_or_equal = TimeIsBetween(later, earlier, later + HALF); 16847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return !earlier_or_equal; 16947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 17047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 17147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 17247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.orgint32 TimeDiff(uint32 later, uint32 earlier) { 17347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#if EFFICIENT_IMPLEMENTATION 17447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return later - earlier; 17547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#else 17647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org const bool later_or_equal = TimeIsBetween(earlier, later, earlier + HALF); 17747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (later_or_equal) { 17847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (earlier <= later) { 17947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<long>(later - earlier); 18047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 18147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return static_cast<long>(later + (UINT32_MAX - earlier) + 1); 18247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18347be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 18447be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org if (later <= earlier) { 18547be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -static_cast<long>(earlier - later); 18647be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } else { 18747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org return -static_cast<long>(earlier + (UINT32_MAX - later) + 1); 18847be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 18947be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org } 19047be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org#endif 19147be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} 19247be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org 19311e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.orgTimestampWrapAroundHandler::TimestampWrapAroundHandler() 19411e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org : last_ts_(0), num_wrap_(0) {} 19511e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org 19611e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.orgint64 TimestampWrapAroundHandler::Unwrap(uint32 ts) { 19711e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org if (ts < last_ts_) { 19811e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org if (last_ts_ > 0xf0000000 && ts < 0x0fffffff) { 19911e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org ++num_wrap_; 20011e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org } 20111e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org } 20211e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org last_ts_ = ts; 20311e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org int64_t unwrapped_ts = ts + (num_wrap_ << 32); 20411e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org return unwrapped_ts; 20511e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org} 20611e96c736207147b6c79963073f89112a8dbefb4henrike@webrtc.org 20747be73b8629244d6bb63a28198f97f040ce53d21henrike@webrtc.org} // namespace rtc 208