/* * 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 "inter_frame_delay.h" #include "tick_time.h" namespace webrtc { VCMInterFrameDelay::VCMInterFrameDelay() { Reset(); } // Resets the delay estimate void VCMInterFrameDelay::Reset() { _zeroWallClock = VCMTickTime::MillisecondTimestamp(); _wrapArounds = 0; _prevWallClock = 0; _prevTimestamp = 0; _dTS = 0; } // Calculates the delay of a frame with the given timestamp. // This method is called when the frame is complete. bool VCMInterFrameDelay::CalculateDelay(WebRtc_UWord32 timestamp, WebRtc_Word64 *delay, WebRtc_Word64 currentWallClock /* = -1 */) { if (currentWallClock <= -1) { currentWallClock = VCMTickTime::MillisecondTimestamp(); } if (_prevWallClock == 0) { // First set of data, initialization, wait for next frame _prevWallClock = currentWallClock; _prevTimestamp = timestamp; *delay = 0; return true; } WebRtc_Word32 prevWrapArounds = _wrapArounds; CheckForWrapArounds(timestamp); // This will be -1 for backward wrap arounds and +1 for forward wrap arounds WebRtc_Word32 wrapAroundsSincePrev = _wrapArounds - prevWrapArounds; // Account for reordering in jitter variance estimate in the future? // Note that this also captures incomplete frames which are grabbed // for decoding after a later frame has been complete, i.e. real // packet losses. if ((wrapAroundsSincePrev == 0 && timestamp < _prevTimestamp) || wrapAroundsSincePrev < 0) { *delay = 0; return false; } // Compute the compensated timestamp difference and convert it to ms and // round it to closest integer. _dTS = static_cast((timestamp + wrapAroundsSincePrev * (static_cast(1)<<32) - _prevTimestamp) / 90.0 + 0.5); // frameDelay is the difference of dT and dTS -- i.e. the difference of // the wall clock time difference and the timestamp difference between // two following frames. *delay = static_cast(currentWallClock - _prevWallClock - _dTS); _prevTimestamp = timestamp; _prevWallClock = currentWallClock; return true; } // Returns the current difference between incoming timestamps WebRtc_UWord32 VCMInterFrameDelay::CurrentTimeStampDiffMs() const { if (_dTS < 0) { return 0; } return static_cast(_dTS); } // Investigates if the timestamp clock has overflowed since the last timestamp and // keeps track of the number of wrap arounds since reset. void VCMInterFrameDelay::CheckForWrapArounds(WebRtc_UWord32 timestamp) { if (timestamp < _prevTimestamp) { // 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 cast to a Word32, // it should be positive. if (static_cast(timestamp - _prevTimestamp) > 0) { // Forward wrap around _wrapArounds++; } } // This difference will probably be less than -2^31 if we have had a backward wrap around. // Since it is cast to a Word32, it should be positive. else if (static_cast(_prevTimestamp - timestamp) > 0) { // Backward wrap around _wrapArounds--; } } }