From 4cebe6cded9e3c8a1177f69cb71f48f993df3e5a Mon Sep 17 00:00:00 2001 From: "phoglund@webrtc.org" Date: Wed, 7 Nov 2012 13:37:19 +0000 Subject: [PATCH] Made TickTime immutable, rewrote tick utils to be fakeable. BUG= Review URL: https://webrtc-codereview.appspot.com/798004 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3053 4adac7df-926f-26a2-2b94-8c16560cd09d --- .../main/test/unit_test/deflickering_test.cc | 2 +- .../main/test/unit_test/denoising_test.cc | 2 +- .../main/test/unit_test/unit_test.cc | 4 +- webrtc/system_wrappers/interface/tick_util.h | 81 ++++++++++++++----- webrtc/system_wrappers/source/Android.mk | 1 + .../source/system_wrappers.gyp | 3 +- webrtc/system_wrappers/source/tick_util.cc | 30 +++++++ .../auto_test/source/vie_autotest_capture.cc | 8 +- webrtc/video_engine/vie_receiver.cc | 7 +- 9 files changed, 103 insertions(+), 35 deletions(-) create mode 100644 webrtc/system_wrappers/source/tick_util.cc diff --git a/webrtc/modules/video_processing/main/test/unit_test/deflickering_test.cc b/webrtc/modules/video_processing/main/test/unit_test/deflickering_test.cc index bf284fcb61..d7833f9200 100644 --- a/webrtc/modules/video_processing/main/test/unit_test/deflickering_test.cc +++ b/webrtc/modules/video_processing/main/test/unit_test/deflickering_test.cc @@ -69,7 +69,7 @@ TEST_F(VideoProcessingModuleTest, Deflickering) ASSERT_EQ(0, _vpm->GetFrameStats(&stats, _videoFrame)); ASSERT_EQ(0, _vpm->Deflickering(&_videoFrame, &stats)); t1 = TickTime::Now(); - accTicks += t1 - t0; + accTicks += (t1 - t0); if (runIdx == 0) { diff --git a/webrtc/modules/video_processing/main/test/unit_test/denoising_test.cc b/webrtc/modules/video_processing/main/test/unit_test/denoising_test.cc index 1d0f9a28db..b3d1259d60 100644 --- a/webrtc/modules/video_processing/main/test/unit_test/denoising_test.cc +++ b/webrtc/modules/video_processing/main/test/unit_test/denoising_test.cc @@ -107,7 +107,7 @@ TEST_F(VideoProcessingModuleTest, Denoising) t0 = TickTime::Now(); ASSERT_GE(modifiedPixels = _vpm->Denoising(&_videoFrame), 0); t1 = TickTime::Now(); - accTicks += t1 - t0; + accTicks += (t1 - t0); if (runIdx == 0) { diff --git a/webrtc/modules/video_processing/main/test/unit_test/unit_test.cc b/webrtc/modules/video_processing/main/test/unit_test/unit_test.cc index 0a0fa1f507..b340b6f8ff 100644 --- a/webrtc/modules/video_processing/main/test/unit_test/unit_test.cc +++ b/webrtc/modules/video_processing/main/test/unit_test/unit_test.cc @@ -14,7 +14,7 @@ #include "common_video/libyuv/include/webrtc_libyuv.h" #include "system_wrappers/interface/tick_util.h" -#include "testsupport/fileutils.h" +#include "test/testsupport/fileutils.h" namespace webrtc { @@ -283,7 +283,7 @@ TEST_F(VideoProcessingModuleTest, Resampler) // stop timer t1 = TickTime::Now(); - accTicks += t1 - t0; + accTicks += (t1 - t0); if (accTicks.Microseconds() < minRuntime || runIdx == 0) { minRuntime = accTicks.Microseconds(); diff --git a/webrtc/system_wrappers/interface/tick_util.h b/webrtc/system_wrappers/interface/tick_util.h index c3432154ea..019c80036b 100644 --- a/webrtc/system_wrappers/interface/tick_util.h +++ b/webrtc/system_wrappers/interface/tick_util.h @@ -32,9 +32,13 @@ namespace webrtc { class TickInterval; +// Class representing the current time. This class is immutable. class TickTime { public: + TickTime(); + explicit TickTime(WebRtc_Word64 ticks); + // Current time in the tick domain. static TickTime Now(); @@ -44,6 +48,7 @@ public: // Now in the time domain in us. static WebRtc_Word64 MicrosecondTimestamp(); + // Returns the number of ticks in the tick domain. WebRtc_Word64 Ticks() const; static WebRtc_Word64 MillisecondsToTicks(const WebRtc_Word64 ms); @@ -52,15 +57,28 @@ public: // Returns a TickTime that is ticks later than the passed TickTime friend TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks); - TickTime& operator+=(const WebRtc_Word64& rhs); - + TickTime& operator+=(const WebRtc_Word64& ticks); // Returns a TickInterval that is the difference in ticks beween rhs and lhs friend TickInterval operator-(const TickTime& lhs, const TickTime& rhs); + + // Call to engage the fake clock. This is useful for tests since relying on + // a real clock often makes the test flaky. + static void UseFakeClock(WebRtc_Word64 start_millisecond); + + // Advance the fake clock. Must be called after UseFakeClock. + static void AdvanceFakeClock(WebRtc_Word64 milliseconds); + private: + static WebRtc_Word64 QueryOsForTicks(); + + static bool _use_fake_clock; + static WebRtc_Word64 _fake_ticks; + WebRtc_Word64 _ticks; }; +// Reperesents a time delta in ticks. This class is immutable. class TickInterval { public: @@ -72,12 +90,12 @@ public: // Returns the sum of two TickIntervals as a TickInterval friend TickInterval operator+(const TickInterval& lhs, const TickInterval& rhs); - TickInterval& operator-=(const TickInterval& rhs); + TickInterval& operator+=(const TickInterval& rhs); // Returns a TickInterval corresponding to rhs - lhs friend TickInterval operator-(const TickInterval& lhs, const TickInterval& rhs); - TickInterval& operator+=(const TickInterval& rhs); + TickInterval& operator-=(const TickInterval& rhs); friend bool operator>(const TickInterval& lhs, const TickInterval& rhs); friend bool operator<=(const TickInterval& lhs, const TickInterval& rhs); @@ -115,25 +133,44 @@ inline TickTime operator+(const TickTime lhs, const WebRtc_Word64 ticks) time._ticks += ticks; return time; } + inline bool operator>(const TickInterval& lhs, const TickInterval& rhs) { return lhs._interval > rhs._interval; } + inline bool operator<=(const TickInterval& lhs, const TickInterval& rhs) { return lhs._interval <= rhs._interval; } + inline bool operator<(const TickInterval& lhs, const TickInterval& rhs) { return lhs._interval <= rhs._interval; } + inline bool operator>=(const TickInterval& lhs, const TickInterval& rhs) { return lhs._interval >= rhs._interval; } +inline TickTime::TickTime() + : _ticks(0) { +} + +inline TickTime::TickTime(WebRtc_Word64 ticks) + : _ticks(ticks) { +} + inline TickTime TickTime::Now() { + if (_use_fake_clock) + return TickTime(_fake_ticks); + else + return TickTime(QueryOsForTicks()); +} + +inline WebRtc_Word64 TickTime::QueryOsForTicks() { TickTime result; #if _WIN32 // TODO(wu): Remove QueryPerformanceCounter implementation. @@ -159,7 +196,7 @@ inline TickTime TickTime::Now() // 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) + if(old > 0xf0000000 && now < 0x0fffffff) { numWrapTimeGetTime++; } @@ -198,43 +235,42 @@ inline TickTime TickTime::Now() gettimeofday(&tv, NULL); result._ticks = 1000000LL * static_cast(tv.tv_sec) + static_cast(tv.tv_usec); #endif - return result; + return result._ticks; } inline WebRtc_Word64 TickTime::MillisecondTimestamp() { - TickTime now = TickTime::Now(); + WebRtc_Word64 ticks = TickTime::Now().Ticks(); #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); - return (now._ticks * 1000) / qpfreq.QuadPart; + return (ticks * 1000) / qpfreq.QuadPart; #else - return now._ticks; + return ticks; #endif #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) - return now._ticks / 1000000LL; + return ticks / 1000000LL; #else - return now._ticks / 1000LL; + return ticks / 1000LL; #endif } inline WebRtc_Word64 TickTime::MicrosecondTimestamp() { - TickTime now = TickTime::Now(); - + WebRtc_Word64 ticks = TickTime::Now().Ticks(); #if _WIN32 #ifdef USE_QUERY_PERFORMANCE_COUNTER LARGE_INTEGER qpfreq; QueryPerformanceFrequency(&qpfreq); - return (now._ticks * 1000) / (qpfreq.QuadPart/1000); + return (ticks * 1000) / (qpfreq.QuadPart/1000); #else - return now._ticks *1000LL; + return ticks *1000LL; #endif #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) - return now._ticks / 1000LL; + return ticks / 1000LL; #else - return now._ticks; + return ticks; #endif } @@ -300,7 +336,7 @@ inline WebRtc_Word64 TickInterval::Milliseconds() const QueryPerformanceFrequency(&qpfreq); return (_interval * 1000) / qpfreq.QuadPart; #else - // _interval is in ms + // _interval is in ms return _interval; #endif #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) @@ -320,7 +356,7 @@ inline WebRtc_Word64 TickInterval::Microseconds() const QueryPerformanceFrequency(&qpfreq); return (_interval * 1000000) / qpfreq.QuadPart; #else - // _interval is in ms + // _interval is in ms return _interval *1000LL; #endif #elif defined(WEBRTC_LINUX) || defined(WEBRTC_MAC) @@ -334,15 +370,16 @@ inline WebRtc_Word64 TickInterval::Microseconds() const inline TickInterval& TickInterval::operator+=(const TickInterval& rhs) { - _interval += rhs._interval; - return *this; + _interval += rhs._interval; + return *this; } inline TickInterval& TickInterval::operator-=(const TickInterval& rhs) { _interval -= rhs._interval; - return *this; + return *this; } + } // namespace webrtc #endif // WEBRTC_SYSTEM_WRAPPERS_INTERFACE_TICK_UTIL_H_ diff --git a/webrtc/system_wrappers/source/Android.mk b/webrtc/system_wrappers/source/Android.mk index dee84ca294..a23dbde311 100644 --- a/webrtc/system_wrappers/source/Android.mk +++ b/webrtc/system_wrappers/source/Android.mk @@ -40,6 +40,7 @@ LOCAL_SRC_FILES := \ event_posix.cc \ sleep.cc \ thread_posix.cc \ + tick_util.cc \ trace_posix.cc \ rw_lock_posix.cc diff --git a/webrtc/system_wrappers/source/system_wrappers.gyp b/webrtc/system_wrappers/source/system_wrappers.gyp index 7a3cd20905..02e301969f 100644 --- a/webrtc/system_wrappers/source/system_wrappers.gyp +++ b/webrtc/system_wrappers/source/system_wrappers.gyp @@ -91,14 +91,15 @@ 'rw_lock_posix.h', 'rw_lock_win.cc', 'rw_lock_win.h', + 'set_thread_name_win.h', 'sleep.cc', 'sort.cc', + 'tick_util.cc', 'thread.cc', 'thread_posix.cc', 'thread_posix.h', 'thread_win.cc', 'thread_win.h', - 'set_thread_name_win.h', 'trace_impl.cc', 'trace_impl.h', 'trace_impl_no_op.cc', diff --git a/webrtc/system_wrappers/source/tick_util.cc b/webrtc/system_wrappers/source/tick_util.cc new file mode 100644 index 0000000000..b6ebc11a84 --- /dev/null +++ b/webrtc/system_wrappers/source/tick_util.cc @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "system_wrappers/interface/tick_util.h" + +#include + +namespace webrtc { + +bool TickTime::_use_fake_clock = false; +WebRtc_Word64 TickTime::_fake_ticks = 0; + +void TickTime::UseFakeClock(WebRtc_Word64 start_millisecond) { + _use_fake_clock = true; + _fake_ticks = MillisecondsToTicks(start_millisecond); +} + +void TickTime::AdvanceFakeClock(WebRtc_Word64 milliseconds) { + assert(_use_fake_clock); + _fake_ticks += MillisecondsToTicks(milliseconds); +} + +} // namespace webrtc diff --git a/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc b/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc index 816f9b7e08..bec6657676 100644 --- a/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc +++ b/webrtc/video_engine/test/auto_test/source/vie_autotest_capture.cc @@ -454,7 +454,7 @@ void ViEAutoTest::ViECaptureExternalCaptureTest() { while (frame_count < 120) { external_capture->IncomingFrame( video_frame, video_frame_length, capability, - webrtc::TickTime::Now().MillisecondTimestamp()); + webrtc::TickTime::MillisecondTimestamp()); AutoTestSleep(33); if (effect_filter.number_of_captured_frames_ > 2) { @@ -478,7 +478,7 @@ void ViEAutoTest::ViECaptureExternalCaptureTest() { for (int frame = 0; frame < 30; ++frame) { external_capture->IncomingFrame( video_frame, video_frame_length, capability, - webrtc::TickTime::Now().MillisecondTimestamp()); + webrtc::TickTime::MillisecondTimestamp()); AutoTestSleep(33); } EXPECT_EQ(webrtc::Bright, observer.brightness_) << @@ -491,7 +491,7 @@ void ViEAutoTest::ViECaptureExternalCaptureTest() { for (int frame = 0; frame < 30; ++frame) { external_capture->IncomingFrame( video_frame, video_frame_length, capability, - webrtc::TickTime::Now().MillisecondTimestamp()); + webrtc::TickTime::MillisecondTimestamp()); AutoTestSleep(33); } EXPECT_EQ(webrtc::Dark, observer.brightness_) << @@ -513,7 +513,7 @@ void ViEAutoTest::ViECaptureExternalCaptureTest() { for (int frame = 0; frame < 10; ++frame) { external_capture->IncomingFrame( video_frame, video_frame_length, capability, - webrtc::TickTime::Now().MillisecondTimestamp()); + webrtc::TickTime::MillisecondTimestamp()); AutoTestSleep(33); } EXPECT_EQ(webrtc::AlarmCleared, observer.alarm_) << diff --git a/webrtc/video_engine/vie_receiver.cc b/webrtc/video_engine/vie_receiver.cc index 9ab7d7410b..490731cf70 100644 --- a/webrtc/video_engine/vie_receiver.cc +++ b/webrtc/video_engine/vie_receiver.cc @@ -128,10 +128,9 @@ WebRtc_Word32 ViEReceiver::OnReceivedPayloadData( const int packet_size = payload_size + rtp_header->header.paddingLength; uint32_t compensated_timestamp = rtp_header->header.timestamp + rtp_header->extension.transmissionTimeOffset; - remote_bitrate_estimator_->IncomingPacket(rtp_header->header.ssrc, - packet_size, - TickTime::MillisecondTimestamp(), - compensated_timestamp); + remote_bitrate_estimator_->IncomingPacket( + rtp_header->header.ssrc, packet_size, + TickTime::MillisecondTimestamp(), compensated_timestamp); if (vcm_->IncomingPacket(payload_data, payload_size, *rtp_header) != 0) { // Check this... return -1;