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