* Implement WindowsRealTimeClock::CurrentTimeVal with GetSystemTimeAsFileTime as it supposes to return a POSIX gettimeofday, so that later it can be converted to NTP timee correctly.
* Updated to ClockTest.NtpTime to verify the returned NTP is at least larger than kNtpJan1970. Current implementation uses timeGetTime, which returns the time since windows is started, which can't be converted to NTP time. BUG=3325 R=pwestin@webrtc.org Review URL: https://webrtc-codereview.appspot.com/16509004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@6178 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
bf58a75dd9
commit
75718cf80a
@ -32,99 +32,6 @@ int64_t Clock::NtpToMs(uint32_t ntp_secs, uint32_t ntp_frac) {
|
||||
static_cast<int64_t>(ntp_frac_ms + 0.5);
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
struct reference_point {
|
||||
FILETIME file_time;
|
||||
LARGE_INTEGER counterMS;
|
||||
};
|
||||
|
||||
struct WindowsHelpTimer {
|
||||
volatile LONG _timeInMs;
|
||||
volatile LONG _numWrapTimeInMs;
|
||||
reference_point _ref_point;
|
||||
|
||||
volatile LONG _sync_flag;
|
||||
};
|
||||
|
||||
void Synchronize(WindowsHelpTimer* help_timer) {
|
||||
const LONG start_value = 0;
|
||||
const LONG new_value = 1;
|
||||
const LONG synchronized_value = 2;
|
||||
|
||||
LONG compare_flag = new_value;
|
||||
while (help_timer->_sync_flag == start_value) {
|
||||
const LONG new_value = 1;
|
||||
compare_flag = InterlockedCompareExchange(
|
||||
&help_timer->_sync_flag, new_value, start_value);
|
||||
}
|
||||
if (compare_flag != start_value) {
|
||||
// This thread was not the one that incremented the sync flag.
|
||||
// Block until synchronization finishes.
|
||||
while (compare_flag != synchronized_value) {
|
||||
::Sleep(0);
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Only the synchronizing thread gets here so this part can be
|
||||
// considered single threaded.
|
||||
|
||||
// set timer accuracy to 1 ms
|
||||
timeBeginPeriod(1);
|
||||
FILETIME ft0 = { 0, 0 },
|
||||
ft1 = { 0, 0 };
|
||||
//
|
||||
// Spin waiting for a change in system time. Get the matching
|
||||
// performance counter value for that time.
|
||||
//
|
||||
::GetSystemTimeAsFileTime(&ft0);
|
||||
do {
|
||||
::GetSystemTimeAsFileTime(&ft1);
|
||||
|
||||
help_timer->_ref_point.counterMS.QuadPart = ::timeGetTime();
|
||||
::Sleep(0);
|
||||
} while ((ft0.dwHighDateTime == ft1.dwHighDateTime) &&
|
||||
(ft0.dwLowDateTime == ft1.dwLowDateTime));
|
||||
help_timer->_ref_point.file_time = ft1;
|
||||
timeEndPeriod(1);
|
||||
}
|
||||
|
||||
void get_time(WindowsHelpTimer* help_timer, FILETIME& current_time) {
|
||||
// we can't use query performance counter due to speed stepping
|
||||
DWORD t = timeGetTime();
|
||||
// NOTE: we have a missmatch in sign between _timeInMs(LONG) and
|
||||
// (DWORD) however we only use it here without +- etc
|
||||
volatile LONG* timeInMsPtr = &help_timer->_timeInMs;
|
||||
// Make sure that we only inc wrapper once.
|
||||
DWORD old = InterlockedExchange(timeInMsPtr, t);
|
||||
if(old > t) {
|
||||
// wrap
|
||||
help_timer->_numWrapTimeInMs++;
|
||||
}
|
||||
LARGE_INTEGER elapsedMS;
|
||||
elapsedMS.HighPart = help_timer->_numWrapTimeInMs;
|
||||
elapsedMS.LowPart = t;
|
||||
|
||||
elapsedMS.QuadPart = elapsedMS.QuadPart -
|
||||
help_timer->_ref_point.counterMS.QuadPart;
|
||||
|
||||
// Translate to 100-nanoseconds intervals (FILETIME resolution)
|
||||
// and add to reference FILETIME to get current FILETIME.
|
||||
ULARGE_INTEGER filetime_ref_as_ul;
|
||||
|
||||
filetime_ref_as_ul.HighPart =
|
||||
help_timer->_ref_point.file_time.dwHighDateTime;
|
||||
filetime_ref_as_ul.LowPart =
|
||||
help_timer->_ref_point.file_time.dwLowDateTime;
|
||||
filetime_ref_as_ul.QuadPart +=
|
||||
(ULONGLONG)((elapsedMS.QuadPart)*1000*10);
|
||||
|
||||
// Copy to result
|
||||
current_time.dwHighDateTime = filetime_ref_as_ul.HighPart;
|
||||
current_time.dwLowDateTime = filetime_ref_as_ul.LowPart;
|
||||
}
|
||||
#endif
|
||||
|
||||
class RealTimeClock : public Clock {
|
||||
// Return a timestamp in milliseconds relative to some arbitrary source; the
|
||||
// source is fixed for this clock.
|
||||
@ -178,8 +85,7 @@ class RealTimeClock : public Clock {
|
||||
#if defined(_WIN32)
|
||||
class WindowsRealTimeClock : public RealTimeClock {
|
||||
public:
|
||||
WindowsRealTimeClock(WindowsHelpTimer* helpTimer)
|
||||
: _helpTimer(helpTimer) {}
|
||||
WindowsRealTimeClock() {}
|
||||
|
||||
virtual ~WindowsRealTimeClock() {}
|
||||
|
||||
@ -191,9 +97,7 @@ class WindowsRealTimeClock : public RealTimeClock {
|
||||
uint64_t Time;
|
||||
struct timeval tv;
|
||||
|
||||
// We can't use query performance counter since they can change depending on
|
||||
// speed stepping.
|
||||
get_time(_helpTimer, StartTime);
|
||||
GetSystemTimeAsFileTime(&StartTime);
|
||||
|
||||
Time = (((uint64_t) StartTime.dwHighDateTime) << 32) +
|
||||
(uint64_t) StartTime.dwLowDateTime;
|
||||
@ -205,8 +109,6 @@ class WindowsRealTimeClock : public RealTimeClock {
|
||||
tv.tv_usec = (uint32_t)((Time % (uint64_t)10000000) / 10);
|
||||
return tv;
|
||||
}
|
||||
|
||||
WindowsHelpTimer* _helpTimer;
|
||||
};
|
||||
|
||||
#elif ((defined WEBRTC_LINUX) || (defined WEBRTC_MAC))
|
||||
@ -228,17 +130,9 @@ class UnixRealTimeClock : public RealTimeClock {
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
// Keeps the global state for the Windows implementation of RtpRtcpClock.
|
||||
// Note that this is a POD. Only PODs are allowed to have static storage
|
||||
// duration according to the Google Style guide.
|
||||
static WindowsHelpTimer global_help_timer = {0, 0, {{ 0, 0}, 0}, 0};
|
||||
#endif
|
||||
|
||||
Clock* Clock::GetRealTimeClock() {
|
||||
#if defined(_WIN32)
|
||||
static WindowsRealTimeClock clock(&global_help_timer);
|
||||
static WindowsRealTimeClock clock;
|
||||
return &clock;
|
||||
#elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC)
|
||||
static UnixRealTimeClock clock;
|
||||
|
@ -20,6 +20,7 @@ TEST(ClockTest, NtpTime) {
|
||||
uint32_t fractions;
|
||||
clock->CurrentNtp(seconds, fractions);
|
||||
int64_t milliseconds = clock->CurrentNtpInMilliseconds();
|
||||
EXPECT_GT(milliseconds / 1000, kNtpJan1970);
|
||||
EXPECT_GE(milliseconds, Clock::NtpToMs(seconds, fractions));
|
||||
EXPECT_NEAR(milliseconds, Clock::NtpToMs(seconds, fractions), 5);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user