|  | /* | 
|  | *  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 "webrtc/modules/video_coding/inter_frame_delay.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | VCMInterFrameDelay::VCMInterFrameDelay(int64_t currentWallClock) { | 
|  | Reset(currentWallClock); | 
|  | } | 
|  |  | 
|  | // Resets the delay estimate | 
|  | void VCMInterFrameDelay::Reset(int64_t currentWallClock) { | 
|  | _zeroWallClock = currentWallClock; | 
|  | _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(uint32_t timestamp, | 
|  | int64_t* delay, | 
|  | int64_t currentWallClock) { | 
|  | if (_prevWallClock == 0) { | 
|  | // First set of data, initialization, wait for next frame | 
|  | _prevWallClock = currentWallClock; | 
|  | _prevTimestamp = timestamp; | 
|  | *delay = 0; | 
|  | return true; | 
|  | } | 
|  |  | 
|  | int32_t prevWrapArounds = _wrapArounds; | 
|  | CheckForWrapArounds(timestamp); | 
|  |  | 
|  | // This will be -1 for backward wrap arounds and +1 for forward wrap arounds | 
|  | int32_t 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<int64_t>( | 
|  | (timestamp + wrapAroundsSincePrev * (static_cast<int64_t>(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<int64_t>(currentWallClock - _prevWallClock - _dTS); | 
|  |  | 
|  | _prevTimestamp = timestamp; | 
|  | _prevWallClock = currentWallClock; | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | // Returns the current difference between incoming timestamps | 
|  | uint32_t VCMInterFrameDelay::CurrentTimeStampDiffMs() const { | 
|  | if (_dTS < 0) { | 
|  | return 0; | 
|  | } | 
|  | return static_cast<uint32_t>(_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(uint32_t 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<int32_t>(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<int32_t>(_prevTimestamp - timestamp) > 0) { | 
|  | // Backward wrap around | 
|  | _wrapArounds--; | 
|  | } | 
|  | } | 
|  | }  // namespace webrtc |