| /* |
| * 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--; |
| } |
| } |
| |
| } |