diff --git a/webrtc/modules/video_coding/main/source/receiver.cc b/webrtc/modules/video_coding/main/source/receiver.cc index c3da7aaebb..41ccf5f9a9 100644 --- a/webrtc/modules/video_coding/main/source/receiver.cc +++ b/webrtc/modules/video_coding/main/source/receiver.cc @@ -200,7 +200,7 @@ VCMEncodedFrame* VCMReceiver::FrameForDecoding( if (timing_error) { // Timing error => reset timing and flush the jitter buffer. jitter_buffer_.Flush(); - timing_->Reset(clock_->TimeInMilliseconds()); + timing_->Reset(); return NULL; } diff --git a/webrtc/modules/video_coding/main/source/timestamp_extrapolator.cc b/webrtc/modules/video_coding/main/source/timestamp_extrapolator.cc index dee48ff2be..6e4b266ae7 100644 --- a/webrtc/modules/video_coding/main/source/timestamp_extrapolator.cc +++ b/webrtc/modules/video_coding/main/source/timestamp_extrapolator.cc @@ -26,7 +26,8 @@ _clock(clock), _startMs(0), _firstTimestamp(0), _wrapArounds(0), -_prevTs90khz(0), +_prevUnwrappedTimestamp(-1), +_prevWrapTimestamp(-1), _lambda(1), _firstAfterReset(true), _packetCount(0), @@ -38,7 +39,7 @@ _accDrift(6600), // in timestamp ticks, i.e. 15 ms _accMaxError(7000), _P11(1e10) { - Reset(_clock->TimeInMilliseconds()); + Reset(); } VCMTimestampExtrapolator::~VCMTimestampExtrapolator() @@ -47,17 +48,10 @@ VCMTimestampExtrapolator::~VCMTimestampExtrapolator() } void -VCMTimestampExtrapolator::Reset(const int64_t nowMs /* = -1 */) +VCMTimestampExtrapolator::Reset() { WriteLockScoped wl(*_rwLock); - if (nowMs > -1) - { - _startMs = nowMs; - } - else - { - _startMs = _clock->TimeInMilliseconds(); - } + _startMs = _clock->TimeInMilliseconds(); _prevMs = _startMs; _firstTimestamp = 0; _w[0] = 90.0; @@ -66,7 +60,8 @@ VCMTimestampExtrapolator::Reset(const int64_t nowMs /* = -1 */) _P[1][1] = _P11; _P[0][1] = _P[1][0] = 0; _firstAfterReset = true; - _prevTs90khz = 0; + _prevUnwrappedTimestamp = -1; + _prevWrapTimestamp = -1; _wrapArounds = 0; _packetCount = 0; _detectorAccumulatorPos = 0; @@ -94,12 +89,15 @@ VCMTimestampExtrapolator::Update(int64_t tMs, uint32_t ts90khz, bool trace) // Remove offset to prevent badly scaled matrices tMs -= _startMs; - int32_t prevWrapArounds = _wrapArounds; CheckForWrapArounds(ts90khz); - int32_t wrapAroundsSincePrev = _wrapArounds - prevWrapArounds; - if (wrapAroundsSincePrev == 0 && ts90khz < _prevTs90khz) + int64_t unwrapped_ts90khz = static_cast(ts90khz) + + _wrapArounds * ((static_cast(1) << 32) - 1); + + if (_prevUnwrappedTimestamp >= 0 && + unwrapped_ts90khz < _prevUnwrappedTimestamp) { + // Drop reordered frames. _rwLock->ReleaseLockExclusive(); return; } @@ -110,14 +108,13 @@ VCMTimestampExtrapolator::Update(int64_t tMs, uint32_t ts90khz, bool trace) // should be almost correct since tMs - _startMs // should about zero at this time. _w[1] = -_w[0] * tMs; - _firstTimestamp = ts90khz; + _firstTimestamp = unwrapped_ts90khz; _firstAfterReset = false; } - // Compensate for wraparounds by changing the line offset - _w[1] = _w[1] - wrapAroundsSincePrev * ((static_cast(1)<<32) - 1); - - double residual = (static_cast(ts90khz) - _firstTimestamp) - static_cast(tMs) * _w[0] - _w[1]; + double residual = + (static_cast(unwrapped_ts90khz) - _firstTimestamp) - + static_cast(tMs) * _w[0] - _w[1]; if (DelayChangeDetection(residual, trace) && _packetCount >= _startUpFilterDelayInPackets) { @@ -145,6 +142,7 @@ VCMTimestampExtrapolator::Update(int64_t tMs, uint32_t ts90khz, bool trace) _P[1][1] = 1 / _lambda * (_P[1][1] - (K[1] * tMs * _P[0][1] + K[1] * _P[1][1])); _P[0][0] = p00; _P[0][1] = p01; + _prevUnwrappedTimestamp = unwrapped_ts90khz; if (_packetCount < _startUpFilterDelayInPackets) { _packetCount++; @@ -156,38 +154,23 @@ VCMTimestampExtrapolator::Update(int64_t tMs, uint32_t ts90khz, bool trace) _rwLock->ReleaseLockExclusive(); } -uint32_t -VCMTimestampExtrapolator::ExtrapolateTimestamp(int64_t tMs) const -{ - ReadLockScoped rl(*_rwLock); - uint32_t timestamp = 0; - if (_packetCount == 0) - { - timestamp = 0; - } - else if (_packetCount < _startUpFilterDelayInPackets) - { - timestamp = static_cast(90.0 * (tMs - _prevMs) + _prevTs90khz + 0.5); - } - else - { - timestamp = static_cast(_w[0] * (tMs - _startMs) + _w[1] + _firstTimestamp + 0.5); - } - return timestamp; -} - int64_t -VCMTimestampExtrapolator::ExtrapolateLocalTime(uint32_t timestamp90khz) const +VCMTimestampExtrapolator::ExtrapolateLocalTime(uint32_t timestamp90khz) { ReadLockScoped rl(*_rwLock); int64_t localTimeMs = 0; + CheckForWrapArounds(timestamp90khz); + double unwrapped_ts90khz = static_cast(timestamp90khz) + + _wrapArounds * ((static_cast(1) << 32) - 1); if (_packetCount == 0) { localTimeMs = -1; } else if (_packetCount < _startUpFilterDelayInPackets) { - localTimeMs = _prevMs + static_cast(static_cast(timestamp90khz - _prevTs90khz) / 90.0 + 0.5); + localTimeMs = _prevMs + static_cast( + static_cast(unwrapped_ts90khz - _prevUnwrappedTimestamp) / + 90.0 + 0.5); } else { @@ -197,8 +180,11 @@ VCMTimestampExtrapolator::ExtrapolateLocalTime(uint32_t timestamp90khz) const } else { - double timestampDiff = static_cast(timestamp90khz) - static_cast(_firstTimestamp); - localTimeMs = static_cast(static_cast(_startMs) + (timestampDiff - _w[1]) / _w[0] + 0.5); + double timestampDiff = unwrapped_ts90khz - + static_cast(_firstTimestamp); + localTimeMs = static_cast( + static_cast(_startMs) + (timestampDiff - _w[1]) / + _w[0] + 0.5); } } return localTimeMs; @@ -209,17 +195,17 @@ VCMTimestampExtrapolator::ExtrapolateLocalTime(uint32_t timestamp90khz) const void VCMTimestampExtrapolator::CheckForWrapArounds(uint32_t ts90khz) { - if (_prevTs90khz == 0) + if (_prevWrapTimestamp == -1) { - _prevTs90khz = ts90khz; + _prevWrapTimestamp = ts90khz; return; } - if (ts90khz < _prevTs90khz) + if (ts90khz < _prevWrapTimestamp) { // This difference will probably be less than -2^31 if we have had a wrap around // (e.g. timestamp = 1, _previousTimestamp = 2^32 - 1). Since it is casted to a Word32, // it should be positive. - if (static_cast(ts90khz - _prevTs90khz) > 0) + if (static_cast(ts90khz - _prevWrapTimestamp) > 0) { // Forward wrap around _wrapArounds++; @@ -227,12 +213,12 @@ VCMTimestampExtrapolator::CheckForWrapArounds(uint32_t ts90khz) } // This difference will probably be less than -2^31 if we have had a backward wrap around. // Since it is casted to a Word32, it should be positive. - else if (static_cast(_prevTs90khz - ts90khz) > 0) + else if (static_cast(_prevWrapTimestamp - ts90khz) > 0) { // Backward wrap around _wrapArounds--; } - _prevTs90khz = ts90khz; + _prevWrapTimestamp = ts90khz; } bool diff --git a/webrtc/modules/video_coding/main/source/timestamp_extrapolator.h b/webrtc/modules/video_coding/main/source/timestamp_extrapolator.h index 233fa1be3b..59915162f0 100644 --- a/webrtc/modules/video_coding/main/source/timestamp_extrapolator.h +++ b/webrtc/modules/video_coding/main/source/timestamp_extrapolator.h @@ -27,9 +27,8 @@ public: int32_t receiverId = 0); ~VCMTimestampExtrapolator(); void Update(int64_t tMs, uint32_t ts90khz, bool trace = true); - uint32_t ExtrapolateTimestamp(int64_t tMs) const; - int64_t ExtrapolateLocalTime(uint32_t timestamp90khz) const; - void Reset(int64_t nowMs = -1); + int64_t ExtrapolateLocalTime(uint32_t timestamp90khz); + void Reset(); private: void CheckForWrapArounds(uint32_t ts90khz); @@ -44,7 +43,8 @@ private: int64_t _prevMs; uint32_t _firstTimestamp; int32_t _wrapArounds; - uint32_t _prevTs90khz; + int64_t _prevUnwrappedTimestamp; + int64_t _prevWrapTimestamp; const double _lambda; bool _firstAfterReset; uint32_t _packetCount; diff --git a/webrtc/modules/video_coding/main/source/timing.cc b/webrtc/modules/video_coding/main/source/timing.cc index 5b2cd0cbe2..91aed1470e 100644 --- a/webrtc/modules/video_coding/main/source/timing.cc +++ b/webrtc/modules/video_coding/main/source/timing.cc @@ -57,17 +57,11 @@ VCMTiming::~VCMTiming() } void -VCMTiming::Reset(int64_t nowMs /* = -1 */) +VCMTiming::Reset() { CriticalSectionScoped cs(_critSect); - if (nowMs > -1) - { - _tsExtrapolator->Reset(nowMs); - } - else - { - _tsExtrapolator->Reset(); - } + + _tsExtrapolator->Reset(); _codecTimer.Reset(); _renderDelayMs = kDefaultRenderDelayMs; _minTotalDelayMs = 0; diff --git a/webrtc/modules/video_coding/main/source/timing.h b/webrtc/modules/video_coding/main/source/timing.h index e100f7a2cf..4b7f6472a6 100644 --- a/webrtc/modules/video_coding/main/source/timing.h +++ b/webrtc/modules/video_coding/main/source/timing.h @@ -33,7 +33,7 @@ public: ~VCMTiming(); // Resets the timing to the initial state. - void Reset(int64_t nowMs = -1); + void Reset(); void ResetDecodeTime(); // The amount of time needed to render an image. Defaults to 10 ms. diff --git a/webrtc/modules/video_coding/main/source/timing_unittest.cc b/webrtc/modules/video_coding/main/source/timing_unittest.cc new file mode 100644 index 0000000000..d6716908f0 --- /dev/null +++ b/webrtc/modules/video_coding/main/source/timing_unittest.cc @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2011 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 +#include +#include +#include + +#include "webrtc/modules/video_coding/main/interface/video_coding.h" +#include "webrtc/modules/video_coding/main/source/internal_defines.h" +#include "webrtc/modules/video_coding/main/source/timing.h" +#include "webrtc/modules/video_coding/main/test/receiver_tests.h" +#include "webrtc/modules/video_coding/main/test/test_util.h" +#include "webrtc/system_wrappers/interface/trace.h" +#include "webrtc/test/testsupport/fileutils.h" + +namespace webrtc { + +TEST(ReceiverTiming, Tests) { + SimulatedClock clock(0); + VCMTiming timing(&clock); + uint32_t waitTime = 0; + uint32_t jitterDelayMs = 0; + uint32_t maxDecodeTimeMs = 0; + uint32_t timeStamp = 0; + + timing.Reset(); + + timing.UpdateCurrentDelay(timeStamp); + + timing.Reset(); + + timing.IncomingTimestamp(timeStamp, clock.TimeInMilliseconds()); + jitterDelayMs = 20; + timing.SetRequiredDelay(jitterDelayMs); + timing.UpdateCurrentDelay(timeStamp); + timing.SetRenderDelay(0); + waitTime = timing.MaxWaitingTime( + timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), + clock.TimeInMilliseconds()); + // First update initializes the render time. Since we have no decode delay + // we get waitTime = renderTime - now - renderDelay = jitter. + EXPECT_EQ(jitterDelayMs, waitTime); + + jitterDelayMs += VCMTiming::kDelayMaxChangeMsPerS + 10; + timeStamp += 90000; + clock.AdvanceTimeMilliseconds(1000); + timing.SetRequiredDelay(jitterDelayMs); + timing.UpdateCurrentDelay(timeStamp); + waitTime = timing.MaxWaitingTime(timing.RenderTimeMs( + timeStamp, clock.TimeInMilliseconds()), clock.TimeInMilliseconds()); + // Since we gradually increase the delay we only get 100 ms every second. + EXPECT_EQ(jitterDelayMs - 10, waitTime); + + timeStamp += 90000; + clock.AdvanceTimeMilliseconds(1000); + timing.UpdateCurrentDelay(timeStamp); + waitTime = timing.MaxWaitingTime( + timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), + clock.TimeInMilliseconds()); + EXPECT_EQ(waitTime, jitterDelayMs); + + // 300 incoming frames without jitter, verify that this gives the exact wait + // time. + for (int i = 0; i < 300; i++) { + clock.AdvanceTimeMilliseconds(1000 / 25); + timeStamp += 90000 / 25; + timing.IncomingTimestamp(timeStamp, clock.TimeInMilliseconds()); + } + timing.UpdateCurrentDelay(timeStamp); + waitTime = timing.MaxWaitingTime( + timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), + clock.TimeInMilliseconds()); + EXPECT_EQ(waitTime, jitterDelayMs); + + // Add decode time estimates. + for (int i = 0; i < 10; i++) { + int64_t startTimeMs = clock.TimeInMilliseconds(); + clock.AdvanceTimeMilliseconds(10); + timing.StopDecodeTimer(timeStamp, startTimeMs, + clock.TimeInMilliseconds()); + timeStamp += 90000 / 25; + clock.AdvanceTimeMilliseconds(1000 / 25 - 10); + timing.IncomingTimestamp(timeStamp, clock.TimeInMilliseconds()); + } + maxDecodeTimeMs = 10; + timing.SetRequiredDelay(jitterDelayMs); + clock.AdvanceTimeMilliseconds(1000); + timeStamp += 90000; + timing.UpdateCurrentDelay(timeStamp); + waitTime = timing.MaxWaitingTime( + timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), + clock.TimeInMilliseconds()); + EXPECT_EQ(waitTime, jitterDelayMs); + + uint32_t minTotalDelayMs = 200; + timing.SetMinimumTotalDelay(minTotalDelayMs); + clock.AdvanceTimeMilliseconds(5000); + timeStamp += 5*90000; + timing.UpdateCurrentDelay(timeStamp); + const int kRenderDelayMs = 10; + timing.SetRenderDelay(kRenderDelayMs); + waitTime = timing.MaxWaitingTime( + timing.RenderTimeMs(timeStamp, clock.TimeInMilliseconds()), + clock.TimeInMilliseconds()); + // We should at least have minTotalDelayMs - decodeTime (10) - renderTime + // (10) to wait. + EXPECT_EQ(waitTime, minTotalDelayMs - maxDecodeTimeMs - kRenderDelayMs); + // The total video delay should be equal to the min total delay. + EXPECT_EQ(minTotalDelayMs, timing.TargetVideoDelay()); + + // Reset min total delay. + timing.SetMinimumTotalDelay(0); + clock.AdvanceTimeMilliseconds(5000); + timeStamp += 5*90000; + timing.UpdateCurrentDelay(timeStamp); +} + +TEST(ReceiverTiming, WrapAround) { + const int kFramerate = 25; + SimulatedClock clock(0); + VCMTiming timing(&clock); + // Provoke a wrap-around. The forth frame will have wrapped at 25 fps. + uint32_t timestamp = 0xFFFFFFFFu - 3 * 90000 / kFramerate; + for (int i = 0; i < 4; ++i) { + timing.IncomingTimestamp(timestamp, clock.TimeInMilliseconds()); + clock.AdvanceTimeMilliseconds(1000 / kFramerate); + timestamp += 90000 / kFramerate; + int64_t render_time = timing.RenderTimeMs(0xFFFFFFFFu, + clock.TimeInMilliseconds()); + EXPECT_EQ(3 * 1000 / kFramerate, render_time); + render_time = timing.RenderTimeMs(89u, // One second later in 90 kHz. + clock.TimeInMilliseconds()); + EXPECT_EQ(3 * 1000 / kFramerate + 1, render_time); + } +} + +} // namespace webrtc diff --git a/webrtc/modules/video_coding/main/source/video_coding_test.gypi b/webrtc/modules/video_coding/main/source/video_coding_test.gypi index 3a66987f21..9ce3d5c5d1 100644 --- a/webrtc/modules/video_coding/main/source/video_coding_test.gypi +++ b/webrtc/modules/video_coding/main/source/video_coding_test.gypi @@ -1,5 +1,4 @@ # Copyright (c) 2011 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 @@ -58,7 +57,6 @@ '../test/normal_test.cc', '../test/pcap_file_reader.cc', '../test/quality_modes_test.cc', - '../test/receiver_timing_tests.cc', '../test/rtp_file_reader.cc', '../test/rtp_player.cc', '../test/test_callbacks.cc', @@ -108,6 +106,7 @@ 'session_info_unittest.cc', 'stream_generator.cc', 'stream_generator.h', + 'timing_unittest.cc', 'video_coding_robustness_unittest.cc', 'video_coding_impl_unittest.cc', 'qm_select_unittest.cc', diff --git a/webrtc/modules/video_coding/main/test/receiver_timing_tests.cc b/webrtc/modules/video_coding/main/test/receiver_timing_tests.cc deleted file mode 100644 index 5e59ebd509..0000000000 --- a/webrtc/modules/video_coding/main/test/receiver_timing_tests.cc +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (c) 2011 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 -#include -#include - -#include "webrtc/modules/video_coding/main/interface/video_coding.h" -#include "webrtc/modules/video_coding/main/source/internal_defines.h" -#include "webrtc/modules/video_coding/main/source/timing.h" -#include "webrtc/modules/video_coding/main/test/receiver_tests.h" -#include "webrtc/modules/video_coding/main/test/test_macros.h" -#include "webrtc/modules/video_coding/main/test/test_util.h" -#include "webrtc/system_wrappers/interface/trace.h" -#include "webrtc/test/testsupport/fileutils.h" - -using namespace webrtc; - -float vcmFloatMax(float a, float b) -{ - return a > b ? a : b; -} - -float vcmFloatMin(float a, float b) -{ - return a < b ? a : b; -} - -double const pi = 4*std::atan(1.0); - -class GaussDist -{ -public: - static float RandValue(float m, float stdDev) // returns a single normally distributed number - { - float r1 = static_cast((std::rand() + 1.0)/(RAND_MAX + 1.0)); // gives equal distribution in (0, 1] - float r2 = static_cast((std::rand() + 1.0)/(RAND_MAX + 1.0)); - return m + stdDev * static_cast(std::sqrt(-2*std::log(r1))*std::cos(2*pi*r2)); - } -}; - -int ReceiverTimingTests(CmdArgs& args) -{ - // Set up trace - Trace::CreateTrace(); - Trace::SetTraceFile((test::OutputPath() + "receiverTestTrace.txt").c_str()); - Trace::SetLevelFilter(webrtc::kTraceAll); - - // A static random seed - srand(0); - - Clock* clock = Clock::GetRealTimeClock(); - VCMTiming timing(clock); - float clockInMs = 0.0; - uint32_t waitTime = 0; - uint32_t jitterDelayMs = 0; - uint32_t maxDecodeTimeMs = 0; - uint32_t timeStamp = 0; - - timing.Reset(static_cast(clockInMs + 0.5)); - - timing.UpdateCurrentDelay(timeStamp); - - timing.Reset(static_cast(clockInMs + 0.5)); - - timing.IncomingTimestamp(timeStamp, static_cast(clockInMs + 0.5)); - jitterDelayMs = 20; - timing.SetRequiredDelay(jitterDelayMs); - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - // First update initializes the render time. Since we have no decode delay - // we get waitTime = renderTime - now - renderDelay = jitter - TEST(waitTime == jitterDelayMs); - - jitterDelayMs += VCMTiming::kDelayMaxChangeMsPerS + 10; - timeStamp += 90000; - clockInMs += 1000.0f; - timing.SetRequiredDelay(jitterDelayMs); - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - // Since we gradually increase the delay we only get - // 100 ms every second. - TEST(waitTime == jitterDelayMs - 10); - - timeStamp += 90000; - clockInMs += 1000.0; - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - TEST(waitTime == jitterDelayMs); - - // 300 incoming frames without jitter, verify that this gives the exact wait time - for (int i=0; i < 300; i++) - { - clockInMs += 1000.0f/30.0f; - timeStamp += 3000; - timing.IncomingTimestamp(timeStamp, static_cast(clockInMs + 0.5)); - } - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - TEST(waitTime == jitterDelayMs); - - // Add decode time estimates - for (int i=0; i < 10; i++) - { - int64_t startTimeMs = static_cast(clockInMs + 0.5); - clockInMs += 10.0f; - timing.StopDecodeTimer(timeStamp, startTimeMs, static_cast(clockInMs + 0.5)); - timeStamp += 3000; - clockInMs += 1000.0f/30.0f - 10.0f; - timing.IncomingTimestamp(timeStamp, static_cast(clockInMs + 0.5)); - } - maxDecodeTimeMs = 10; - timing.SetRequiredDelay(jitterDelayMs); - clockInMs += 1000.0f; - timeStamp += 90000; - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - TEST(waitTime == jitterDelayMs); - - uint32_t totalDelay1 = timing.TargetVideoDelay(); - uint32_t minTotalDelayMs = 200; - timing.SetMinimumTotalDelay(minTotalDelayMs); - clockInMs += 5000.0f; - timeStamp += 5*90000; - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - uint32_t totalDelay2 = timing.TargetVideoDelay(); - // We should at least have minTotalDelayMs - decodeTime (10) - renderTime (10) to wait - TEST(waitTime == minTotalDelayMs - maxDecodeTimeMs - 10); - // The total video delay should not increase with the extra delay, - // the extra delay should be independent. - TEST(totalDelay1 == totalDelay2); - - // Reset min total delay - timing.SetMinimumTotalDelay(0); - clockInMs += 5000.0f; - timeStamp += 5*90000; - timing.UpdateCurrentDelay(timeStamp); - - // A sudden increase in timestamp of 2.1 seconds - clockInMs += 1000.0f/30.0f; - timeStamp += static_cast(2.1*90000 + 0.5); - int64_t ret = timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)); - TEST(ret == -1); - timing.Reset(); - - // This test produces a trace which can be parsed with plotTimingTest.m. The plot - // can be used to see that the timing is reasonable under noise, and that the - // gradual transition between delays works as expected. - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, -1, "Stochastic test 1"); - - jitterDelayMs = 60; - maxDecodeTimeMs = 10; - - timeStamp = static_cast(-10000); // To produce a wrap - clockInMs = 10000.0f; - timing.Reset(static_cast(clockInMs + 0.5)); - - float noise = 0.0f; - for (int i=0; i < 1400; i++) - { - if (i == 400) - { - jitterDelayMs = 30; - } - else if (i == 700) - { - jitterDelayMs = 100; - } - else if (i == 1000) - { - minTotalDelayMs = 200; - timing.SetMinimumTotalDelay(minTotalDelayMs); - } - else if (i == 1200) - { - minTotalDelayMs = 0; - timing.SetMinimumTotalDelay(minTotalDelayMs); - } - int64_t startTimeMs = static_cast(clockInMs + 0.5); - noise = vcmFloatMin(vcmFloatMax(GaussDist::RandValue(0, 2), -10.0f), 30.0f); - clockInMs += 10.0f; - timing.StopDecodeTimer(timeStamp, startTimeMs, static_cast(clockInMs + noise + 0.5)); - timeStamp += 3000; - clockInMs += 1000.0f/30.0f - 10.0f; - noise = vcmFloatMin(vcmFloatMax(GaussDist::RandValue(0, 8), -15.0f), 15.0f); - timing.IncomingTimestamp(timeStamp, static_cast(clockInMs + noise + 0.5)); - timing.SetRequiredDelay(jitterDelayMs); - timing.UpdateCurrentDelay(timeStamp); - waitTime = timing.MaxWaitingTime(timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)), - static_cast(clockInMs + 0.5)); - - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, -1, "timeStamp=%u clock=%u maxWaitTime=%u", timeStamp, - static_cast(clockInMs + 0.5), waitTime); - - int64_t renderTimeMs = timing.RenderTimeMs(timeStamp, static_cast(clockInMs + 0.5)); - - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, -1, - "timeStamp=%u renderTime=%u", - timeStamp, - MaskWord64ToUWord32(renderTimeMs)); - } - WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVideoCoding, -1, "End Stochastic test 1"); - - printf("\nVCM Timing Test: \n\n%i tests completed\n", vcmMacrosTests); - if (vcmMacrosErrors > 0) - { - printf("%i FAILED\n\n", vcmMacrosErrors); - } - else - { - printf("ALL PASSED\n\n"); - } - - Trace::ReturnTrace(); - return 0; -} diff --git a/webrtc/modules/video_coding/main/test/tester_main.cc b/webrtc/modules/video_coding/main/test/tester_main.cc index 3a5c4a9a4d..8d4a4e16e6 100644 --- a/webrtc/modules/video_coding/main/test/tester_main.cc +++ b/webrtc/modules/video_coding/main/test/tester_main.cc @@ -97,7 +97,6 @@ int main(int argc, char **argv) { case 0: ret = NormalTest::RunTest(args); ret |= CodecDataBaseTest::RunTest(args); - ret |= ReceiverTimingTests(args); break; case 1: ret = NormalTest::RunTest(args); @@ -115,9 +114,6 @@ int main(int argc, char **argv) { // 0- normal, 1-Release test(50 runs) 2- from file ret = MediaOptTest::RunTest(0, args); break; - case 6: - ret = ReceiverTimingTests(args); - break; case 7: ret = RtpPlay(args); break;