Move TickTime::QueryOsForTicks out-of-line
This inline function is no longer expanded on arm Android, but on x86 Android it will still be expanded. Move it out-of-line to make things consistent. This change list will also fix a potential bug on webrtc for Android: Since the inline function won't be expanded on arm Android, TickTime::MillisecondTimestamp and Clock::GetRealTimeClock()->TimeInMilliseconds will be treated as function call, due to macro WEBRTC_CLOCK_TYPE_REALTIME's guard defined in system_wrappers module they will get current time using CLOCK_REALTIME. But on x86 Android, the inline function will be expanded to where it's been called, if the call happens in other compilation units which don't have WEBRTC_CLOCK_TYPE_REALTIME definition, it will get current time using CLOCK_MONOTONIC, while Clock::GetRealTimeClock()->TimeInMilliseconds will always use CLOCK_REALTIME, then there will be two types of time in x86 Android which will cause some weird issues like all received remote streams will be dropped due to future render timestamp. BUG=None TEST=WebRTCViEDemo application works well on both arm and x86 Android R=fischman@webrtc.org, niklas.enbom@webrtc.org Review URL: https://webrtc-codereview.appspot.com/1688004 Patch from Jeremy Mao <yujie.mao@intel.com>. git-svn-id: http://webrtc.googlecode.com/svn/trunk@4274 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
4cf1a8af69
commit
1d4a2d5daf
@ -163,74 +163,6 @@ inline TickTime TickTime::Now() {
|
||||
return TickTime(QueryOsForTicks());
|
||||
}
|
||||
|
||||
inline int64_t TickTime::QueryOsForTicks() {
|
||||
TickTime result;
|
||||
#if _WIN32
|
||||
// TODO(wu): Remove QueryPerformanceCounter implementation.
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
// QueryPerformanceCounter returns the value from the TSC which is
|
||||
// incremented at the CPU frequency. The algorithm used requires
|
||||
// the CPU frequency to be constant. Technology like speed stepping
|
||||
// which has variable CPU frequency will therefore yield unpredictable,
|
||||
// incorrect time estimations.
|
||||
LARGE_INTEGER qpcnt;
|
||||
QueryPerformanceCounter(&qpcnt);
|
||||
result.ticks_ = qpcnt.QuadPart;
|
||||
#else
|
||||
static volatile LONG last_time_get_time = 0;
|
||||
static volatile int64_t num_wrap_time_get_time = 0;
|
||||
volatile LONG* last_time_get_time_ptr = &last_time_get_time;
|
||||
DWORD now = timeGetTime();
|
||||
// Atomically update the last gotten time
|
||||
DWORD old = InterlockedExchange(last_time_get_time_ptr, now);
|
||||
if (now < old) {
|
||||
// If now is earlier than old, there may have been a race between
|
||||
// threads.
|
||||
// 0x0fffffff ~3.1 days, the code will not take that long to execute
|
||||
// so it must have been a wrap around.
|
||||
if (old > 0xf0000000 && now < 0x0fffffff) {
|
||||
num_wrap_time_get_time++;
|
||||
}
|
||||
}
|
||||
result.ticks_ = now + (num_wrap_time_get_time << 32);
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
struct timespec ts;
|
||||
// TODO(wu): Remove CLOCK_REALTIME implementation.
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
result.ticks_ = 1000000000LL * static_cast<int64_t>(ts.tv_sec) +
|
||||
static_cast<int64_t>(ts.tv_nsec);
|
||||
#elif defined(WEBRTC_MAC)
|
||||
static mach_timebase_info_data_t timebase;
|
||||
if (timebase.denom == 0) {
|
||||
// Get the timebase if this is the first time we run.
|
||||
// Recommended by Apple's QA1398.
|
||||
kern_return_t retval = mach_timebase_info(&timebase);
|
||||
if (retval != KERN_SUCCESS) {
|
||||
// TODO(wu): Implement CHECK similar to chrome for all the platforms.
|
||||
// Then replace this with a CHECK(retval == KERN_SUCCESS);
|
||||
#ifndef WEBRTC_IOS
|
||||
asm("int3");
|
||||
#else
|
||||
__builtin_trap();
|
||||
#endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_
|
||||
}
|
||||
}
|
||||
// Use timebase to convert absolute time tick units into nanoseconds.
|
||||
result.ticks_ = mach_absolute_time() * timebase.numer / timebase.denom;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
result.ticks_ = 1000000LL * static_cast<int64_t>(tv.tv_sec) +
|
||||
static_cast<int64_t>(tv.tv_usec);
|
||||
#endif
|
||||
return result.ticks_;
|
||||
}
|
||||
|
||||
inline int64_t TickTime::MillisecondTimestamp() {
|
||||
int64_t ticks = TickTime::Now().Ticks();
|
||||
#if _WIN32
|
||||
|
@ -27,4 +27,72 @@ void TickTime::AdvanceFakeClock(int64_t milliseconds) {
|
||||
fake_ticks_ += MillisecondsToTicks(milliseconds);
|
||||
}
|
||||
|
||||
int64_t TickTime::QueryOsForTicks() {
|
||||
TickTime result;
|
||||
#if _WIN32
|
||||
// TODO(wu): Remove QueryPerformanceCounter implementation.
|
||||
#ifdef USE_QUERY_PERFORMANCE_COUNTER
|
||||
// QueryPerformanceCounter returns the value from the TSC which is
|
||||
// incremented at the CPU frequency. The algorithm used requires
|
||||
// the CPU frequency to be constant. Technology like speed stepping
|
||||
// which has variable CPU frequency will therefore yield unpredictable,
|
||||
// incorrect time estimations.
|
||||
LARGE_INTEGER qpcnt;
|
||||
QueryPerformanceCounter(&qpcnt);
|
||||
result.ticks_ = qpcnt.QuadPart;
|
||||
#else
|
||||
static volatile LONG last_time_get_time = 0;
|
||||
static volatile int64_t num_wrap_time_get_time = 0;
|
||||
volatile LONG* last_time_get_time_ptr = &last_time_get_time;
|
||||
DWORD now = timeGetTime();
|
||||
// Atomically update the last gotten time
|
||||
DWORD old = InterlockedExchange(last_time_get_time_ptr, now);
|
||||
if (now < old) {
|
||||
// If now is earlier than old, there may have been a race between
|
||||
// threads.
|
||||
// 0x0fffffff ~3.1 days, the code will not take that long to execute
|
||||
// so it must have been a wrap around.
|
||||
if (old > 0xf0000000 && now < 0x0fffffff) {
|
||||
num_wrap_time_get_time++;
|
||||
}
|
||||
}
|
||||
result.ticks_ = now + (num_wrap_time_get_time << 32);
|
||||
#endif
|
||||
#elif defined(WEBRTC_LINUX)
|
||||
struct timespec ts;
|
||||
// TODO(wu): Remove CLOCK_REALTIME implementation.
|
||||
#ifdef WEBRTC_CLOCK_TYPE_REALTIME
|
||||
clock_gettime(CLOCK_REALTIME, &ts);
|
||||
#else
|
||||
clock_gettime(CLOCK_MONOTONIC, &ts);
|
||||
#endif
|
||||
result.ticks_ = 1000000000LL * static_cast<int64_t>(ts.tv_sec) +
|
||||
static_cast<int64_t>(ts.tv_nsec);
|
||||
#elif defined(WEBRTC_MAC)
|
||||
static mach_timebase_info_data_t timebase;
|
||||
if (timebase.denom == 0) {
|
||||
// Get the timebase if this is the first time we run.
|
||||
// Recommended by Apple's QA1398.
|
||||
kern_return_t retval = mach_timebase_info(&timebase);
|
||||
if (retval != KERN_SUCCESS) {
|
||||
// TODO(wu): Implement CHECK similar to chrome for all the platforms.
|
||||
// Then replace this with a CHECK(retval == KERN_SUCCESS);
|
||||
#ifndef WEBRTC_IOS
|
||||
asm("int3");
|
||||
#else
|
||||
__builtin_trap();
|
||||
#endif // WEBRTC_IOS
|
||||
}
|
||||
}
|
||||
// Use timebase to convert absolute time tick units into nanoseconds.
|
||||
result.ticks_ = mach_absolute_time() * timebase.numer / timebase.denom;
|
||||
#else
|
||||
struct timeval tv;
|
||||
gettimeofday(&tv, NULL);
|
||||
result.ticks_ = 1000000LL * static_cast<int64_t>(tv.tv_sec) +
|
||||
static_cast<int64_t>(tv.tv_usec);
|
||||
#endif
|
||||
return result.ticks_;
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
Loading…
x
Reference in New Issue
Block a user