diff --git a/src/modules/remote_bitrate_estimator/include/rtp_to_ntp.h b/src/modules/remote_bitrate_estimator/include/rtp_to_ntp.h new file mode 100644 index 0000000000..b46534fcb7 --- /dev/null +++ b/src/modules/remote_bitrate_estimator/include/rtp_to_ntp.h @@ -0,0 +1,43 @@ +/* + * 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. + */ + +#ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_RTP_TO_NTP_H_ +#define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_RTP_TO_NTP_H_ + +#include + +#include "typedefs.h" + +namespace webrtc { + +namespace synchronization { + +struct RtcpMeasurement { + RtcpMeasurement(); + RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp); + uint32_t ntp_secs; + uint32_t ntp_frac; + uint32_t rtp_timestamp; +}; + +typedef std::list RtcpList; + +// Converts an RTP timestamp to the NTP domain in milliseconds using two +// (RTP timestamp, NTP timestamp) pairs. +bool RtpToNtpMs(int64_t rtp_timestamp, const RtcpList& rtcp, + int64_t* timestamp_in_ms); + +// Returns 1 there has been a forward wrap around, 0 if there has been no wrap +// around and -1 if there has been a backwards wrap around (i.e. reordering). +int CheckForWrapArounds(uint32_t rtp_timestamp, uint32_t rtcp_rtp_timestamp); +} // namespace synchronization +} // namespace webrtc + +#endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_INCLUDE_RTP_TO_NTP_H_ diff --git a/src/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi b/src/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi index cb5107b632..d3f180fcc5 100644 --- a/src/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi +++ b/src/modules/remote_bitrate_estimator/remote_bitrate_estimator.gypi @@ -29,6 +29,7 @@ # interface 'include/bwe_defines.h', 'include/remote_bitrate_estimator.h', + 'include/rtp_to_ntp.h', # source 'bitrate_estimator.cc', @@ -41,6 +42,7 @@ 'remote_bitrate_estimator_single_stream.cc', 'remote_rate_control.cc', 'remote_rate_control.h', + 'rtp_to_ntp.cc', '../../video_engine/stream_synchronization.cc', '../../video_engine/stream_synchronization.h', ], # source @@ -62,6 +64,7 @@ 'include/mock/mock_remote_bitrate_observer.h', 'bitrate_estimator_unittest.cc', 'remote_bitrate_estimator_unittest.cc', + 'rtp_to_ntp_unittest.cc', ], }, ], # targets diff --git a/src/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc b/src/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc index fc0d2a8792..ebf767ce54 100644 --- a/src/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc +++ b/src/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.cc @@ -10,9 +10,9 @@ #include "modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.h" +#include "modules/remote_bitrate_estimator/include/rtp_to_ntp.h" #include "modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h" #include "system_wrappers/interface/tick_util.h" -#include "video_engine/stream_synchronization.h" namespace webrtc { diff --git a/src/modules/remote_bitrate_estimator/rtp_to_ntp.cc b/src/modules/remote_bitrate_estimator/rtp_to_ntp.cc new file mode 100644 index 0000000000..642c02d918 --- /dev/null +++ b/src/modules/remote_bitrate_estimator/rtp_to_ntp.cc @@ -0,0 +1,125 @@ +/* + * 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 "modules/remote_bitrate_estimator/include/rtp_to_ntp.h" + +#include + +namespace webrtc { + +namespace synchronization { + +const double kNtpFracPerMs = 4.294967296E6; + +RtcpMeasurement::RtcpMeasurement() + : ntp_secs(0), ntp_frac(0), rtp_timestamp(0) {} + +RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, + uint32_t timestamp) + : ntp_secs(ntp_secs), ntp_frac(ntp_frac), rtp_timestamp(timestamp) {} + +// Calculates the RTP timestamp frequency from two pairs of NTP and RTP +// timestamps. +bool CalculateFrequency( + int64_t rtcp_ntp_ms1, + uint32_t rtp_timestamp1, + int64_t rtcp_ntp_ms2, + uint32_t rtp_timestamp2, + double* frequency_khz) { + if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) { + return false; + } + *frequency_khz = static_cast(rtp_timestamp1 - rtp_timestamp2) / + static_cast(rtcp_ntp_ms1 - rtcp_ntp_ms2); + return true; +} + +// Detects if there has been a wraparound between |old_timestamp| and +// |new_timestamp|, and compensates by adding 2^32 if that is the case. +bool CompensateForWrapAround(uint32_t new_timestamp, + uint32_t old_timestamp, + int64_t* compensated_timestamp) { + assert(compensated_timestamp); + int64_t wraps = synchronization::CheckForWrapArounds(new_timestamp, + old_timestamp); + if (wraps < 0) { + // Reordering, don't use this packet. + return false; + } + *compensated_timestamp = new_timestamp + (wraps << 32); + return true; +} + +// Converts an NTP timestamp to a millisecond timestamp. +int64_t NtpToMs(uint32_t ntp_secs, uint32_t ntp_frac) { + const double ntp_frac_ms = static_cast(ntp_frac) / kNtpFracPerMs; + return ntp_secs * 1000 + ntp_frac_ms + 0.5; +} + +// Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp +// pairs in |rtcp|. The converted timestamp is returned in +// |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP +// timestamps and returns false if it can't do the conversion due to reordering. +bool RtpToNtpMs(int64_t rtp_timestamp, + const synchronization::RtcpList& rtcp, + int64_t* rtp_timestamp_in_ms) { + assert(rtcp.size() == 2); + int64_t rtcp_ntp_ms_new = synchronization::NtpToMs(rtcp.front().ntp_secs, + rtcp.front().ntp_frac); + int64_t rtcp_ntp_ms_old = synchronization::NtpToMs(rtcp.back().ntp_secs, + rtcp.back().ntp_frac); + int64_t rtcp_timestamp_new = rtcp.front().rtp_timestamp; + int64_t rtcp_timestamp_old = rtcp.back().rtp_timestamp; + if (!CompensateForWrapAround(rtcp_timestamp_new, + rtcp_timestamp_old, + &rtcp_timestamp_new)) { + return false; + } + double freq_khz; + if (!CalculateFrequency(rtcp_ntp_ms_new, + rtcp_timestamp_new, + rtcp_ntp_ms_old, + rtcp_timestamp_old, + &freq_khz)) { + return false; + } + double offset = rtcp_timestamp_new - freq_khz * rtcp_ntp_ms_new; + int64_t rtp_timestamp_unwrapped; + if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old, + &rtp_timestamp_unwrapped)) { + return false; + } + double rtp_timestamp_ntp_ms = (static_cast(rtp_timestamp_unwrapped) - + offset) / freq_khz + 0.5f; + if (rtp_timestamp_ntp_ms < 0) { + return false; + } + *rtp_timestamp_in_ms = rtp_timestamp_ntp_ms; + return true; +} + +int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) { + if (new_timestamp < old_timestamp) { + // This difference should be less than -2^31 if we have had a wrap around + // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is + // cast to a int32_t, it should be positive. + if (static_cast(new_timestamp - old_timestamp) > 0) { + // Forward wrap around. + return 1; + } + } else if (static_cast(old_timestamp - new_timestamp) > 0) { + // This difference should be less than -2^31 if we have had a backward wrap + // around. Since it is cast to a int32_t, it should be positive. + return -1; + } + return 0; +} +} // namespace synchronization +} // namespace webrtc diff --git a/src/modules/remote_bitrate_estimator/rtp_to_ntp_unittest.cc b/src/modules/remote_bitrate_estimator/rtp_to_ntp_unittest.cc new file mode 100644 index 0000000000..5f2142a239 --- /dev/null +++ b/src/modules/remote_bitrate_estimator/rtp_to_ntp_unittest.cc @@ -0,0 +1,163 @@ +/* + * 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 "gtest/gtest.h" +#include "modules/remote_bitrate_estimator/include/rtp_to_ntp.h" + +namespace webrtc { + +TEST(WrapAroundTests, NoWrap) { + EXPECT_EQ(0, synchronization::CheckForWrapArounds(0xFFFFFFFF, 0xFFFFFFFE)); + EXPECT_EQ(0, synchronization::CheckForWrapArounds(1, 0)); + EXPECT_EQ(0, synchronization::CheckForWrapArounds(0x00010000, 0x0000FFFF)); +} + +TEST(WrapAroundTests, ForwardWrap) { + EXPECT_EQ(1, synchronization::CheckForWrapArounds(0, 0xFFFFFFFF)); + EXPECT_EQ(1, synchronization::CheckForWrapArounds(0, 0xFFFF0000)); + EXPECT_EQ(1, synchronization::CheckForWrapArounds(0x0000FFFF, 0xFFFFFFFF)); + EXPECT_EQ(1, synchronization::CheckForWrapArounds(0x0000FFFF, 0xFFFF0000)); +} + +TEST(WrapAroundTests, BackwardWrap) { + EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFFFFFF, 0)); + EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFF0000, 0)); + EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFFFFFF, 0x0000FFFF)); + EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFF0000, 0x0000FFFF)); +} + +TEST(WrapAroundTests, OldRtcpWrapped) { + synchronization::RtcpList rtcp; + uint32_t ntp_sec = 0; + uint32_t ntp_frac = 0; + uint32_t timestamp = 0; + const uint32_t kOneMsInNtpFrac = 4294967; + const uint32_t kTimestampTicksPerMs = 90; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp -= kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp -= kTimestampTicksPerMs; + int64_t timestamp_in_ms = -1; + // This expected to fail since it's highly unlikely that the older RTCP + // has a much smaller RTP timestamp than the newer. + EXPECT_FALSE(synchronization::RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms)); +} + +TEST(WrapAroundTests, NewRtcpWrapped) { + synchronization::RtcpList rtcp; + uint32_t ntp_sec = 0; + uint32_t ntp_frac = 0; + uint32_t timestamp = 0xFFFFFFFF; + const uint32_t kOneMsInNtpFrac = 4294967; + const uint32_t kTimestampTicksPerMs = 90; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp += kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + int64_t timestamp_in_ms = -1; + EXPECT_TRUE(synchronization::RtpToNtpMs(rtcp.back().rtp_timestamp, rtcp, + ×tamp_in_ms)); + // Since this RTP packet has the same timestamp as the RTCP packet constructed + // at time 0 it should be mapped to 0 as well. + EXPECT_EQ(0, timestamp_in_ms); +} + +TEST(WrapAroundTests, RtpWrapped) { + const uint32_t kOneMsInNtpFrac = 4294967; + const uint32_t kTimestampTicksPerMs = 90; + synchronization::RtcpList rtcp; + uint32_t ntp_sec = 0; + uint32_t ntp_frac = 0; + uint32_t timestamp = 0xFFFFFFFF - 2 * kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp += kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp += kTimestampTicksPerMs; + int64_t timestamp_in_ms = -1; + EXPECT_TRUE(synchronization::RtpToNtpMs(timestamp, rtcp, + ×tamp_in_ms)); + // Since this RTP packet has the same timestamp as the RTCP packet constructed + // at time 0 it should be mapped to 0 as well. + EXPECT_EQ(2, timestamp_in_ms); +} + +TEST(WrapAroundTests, OldRtp_RtcpsWrapped) { + const uint32_t kOneMsInNtpFrac = 4294967; + const uint32_t kTimestampTicksPerMs = 90; + synchronization::RtcpList rtcp; + uint32_t ntp_sec = 0; + uint32_t ntp_frac = 0; + uint32_t timestamp = 0; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp += kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp -= 2*kTimestampTicksPerMs; + int64_t timestamp_in_ms = -1; + EXPECT_FALSE(synchronization::RtpToNtpMs(timestamp, rtcp, + ×tamp_in_ms)); +} + +TEST(WrapAroundTests, OldRtp_NewRtcpWrapped) { + const uint32_t kOneMsInNtpFrac = 4294967; + const uint32_t kTimestampTicksPerMs = 90; + synchronization::RtcpList rtcp; + uint32_t ntp_sec = 0; + uint32_t ntp_frac = 0; + uint32_t timestamp = 0xFFFFFFFF; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp += kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp -= kTimestampTicksPerMs; + int64_t timestamp_in_ms = -1; + EXPECT_TRUE(synchronization::RtpToNtpMs(timestamp, rtcp, + ×tamp_in_ms)); + // Constructed at the same time as the first RTCP and should therefore be + // mapped to zero. + EXPECT_EQ(0, timestamp_in_ms); +} + +TEST(WrapAroundTests, OldRtp_OldRtcpWrapped) { + const uint32_t kOneMsInNtpFrac = 4294967; + const uint32_t kTimestampTicksPerMs = 90; + synchronization::RtcpList rtcp; + uint32_t ntp_sec = 0; + uint32_t ntp_frac = 0; + uint32_t timestamp = 0; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp -= kTimestampTicksPerMs; + rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, + timestamp)); + ntp_frac += kOneMsInNtpFrac; + timestamp += 2*kTimestampTicksPerMs; + int64_t timestamp_in_ms = -1; + EXPECT_FALSE(synchronization::RtpToNtpMs(timestamp, rtcp, + ×tamp_in_ms)); +} +}; // namespace webrtc diff --git a/src/video_engine/stream_synchronization.cc b/src/video_engine/stream_synchronization.cc index a905c4c50d..11caf3d299 100644 --- a/src/video_engine/stream_synchronization.cc +++ b/src/video_engine/stream_synchronization.cc @@ -22,115 +22,6 @@ const int kMaxVideoDiffMs = 80; const int kMaxAudioDiffMs = 80; const int kMaxDelay = 1500; -const double kNtpFracPerMs = 4.294967296E6; - -namespace synchronization { - -RtcpMeasurement::RtcpMeasurement() - : ntp_secs(0), ntp_frac(0), rtp_timestamp(0) {} - -RtcpMeasurement::RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, - uint32_t timestamp) - : ntp_secs(ntp_secs), ntp_frac(ntp_frac), rtp_timestamp(timestamp) {} - -// Calculates the RTP timestamp frequency from two pairs of NTP and RTP -// timestamps. -bool CalculateFrequency( - int64_t rtcp_ntp_ms1, - uint32_t rtp_timestamp1, - int64_t rtcp_ntp_ms2, - uint32_t rtp_timestamp2, - double* frequency_khz) { - if (rtcp_ntp_ms1 <= rtcp_ntp_ms2) { - return false; - } - *frequency_khz = static_cast(rtp_timestamp1 - rtp_timestamp2) / - static_cast(rtcp_ntp_ms1 - rtcp_ntp_ms2); - return true; -} - -// Detects if there has been a wraparound between |old_timestamp| and -// |new_timestamp|, and compensates by adding 2^32 if that is the case. -bool CompensateForWrapAround(uint32_t new_timestamp, - uint32_t old_timestamp, - int64_t* compensated_timestamp) { - assert(compensated_timestamp); - int64_t wraps = synchronization::CheckForWrapArounds(new_timestamp, - old_timestamp); - if (wraps < 0) { - // Reordering, don't use this packet. - return false; - } - *compensated_timestamp = new_timestamp + (wraps << 32); - return true; -} - -// Converts an NTP timestamp to a millisecond timestamp. -int64_t NtpToMs(uint32_t ntp_secs, uint32_t ntp_frac) { - const double ntp_frac_ms = static_cast(ntp_frac) / kNtpFracPerMs; - return ntp_secs * 1000 + ntp_frac_ms + 0.5; -} - -// Converts |rtp_timestamp| to the NTP time base using the NTP and RTP timestamp -// pairs in |rtcp|. The converted timestamp is returned in -// |rtp_timestamp_in_ms|. This function compensates for wrap arounds in RTP -// timestamps and returns false if it can't do the conversion due to reordering. -bool RtpToNtpMs(int64_t rtp_timestamp, - const synchronization::RtcpList& rtcp, - int64_t* rtp_timestamp_in_ms) { - assert(rtcp.size() == 2); - int64_t rtcp_ntp_ms_new = synchronization::NtpToMs(rtcp.front().ntp_secs, - rtcp.front().ntp_frac); - int64_t rtcp_ntp_ms_old = synchronization::NtpToMs(rtcp.back().ntp_secs, - rtcp.back().ntp_frac); - int64_t rtcp_timestamp_new = rtcp.front().rtp_timestamp; - int64_t rtcp_timestamp_old = rtcp.back().rtp_timestamp; - if (!CompensateForWrapAround(rtcp_timestamp_new, - rtcp_timestamp_old, - &rtcp_timestamp_new)) { - return false; - } - double freq_khz; - if (!CalculateFrequency(rtcp_ntp_ms_new, - rtcp_timestamp_new, - rtcp_ntp_ms_old, - rtcp_timestamp_old, - &freq_khz)) { - return false; - } - double offset = rtcp_timestamp_new - freq_khz * rtcp_ntp_ms_new; - int64_t rtp_timestamp_unwrapped; - if (!CompensateForWrapAround(rtp_timestamp, rtcp_timestamp_old, - &rtp_timestamp_unwrapped)) { - return false; - } - double rtp_timestamp_ntp_ms = (static_cast(rtp_timestamp_unwrapped) - - offset) / freq_khz + 0.5f; - if (rtp_timestamp_ntp_ms < 0) { - return false; - } - *rtp_timestamp_in_ms = rtp_timestamp_ntp_ms; - return true; -} - -int CheckForWrapArounds(uint32_t new_timestamp, uint32_t old_timestamp) { - if (new_timestamp < old_timestamp) { - // This difference should be less than -2^31 if we have had a wrap around - // (e.g. |new_timestamp| = 1, |rtcp_rtp_timestamp| = 2^32 - 1). Since it is - // cast to a int32_t, it should be positive. - if (static_cast(new_timestamp - old_timestamp) > 0) { - // Forward wrap around. - return 1; - } - } else if (static_cast(old_timestamp - new_timestamp) > 0) { - // This difference should be less than -2^31 if we have had a backward wrap - // around. Since it is cast to a int32_t, it should be positive. - return -1; - } - return 0; -} -} // namespace synchronization - struct ViESyncDelay { ViESyncDelay() { extra_video_delay_ms = 0; diff --git a/src/video_engine/stream_synchronization.h b/src/video_engine/stream_synchronization.h index 66aa31d0e1..25a370cf2d 100644 --- a/src/video_engine/stream_synchronization.h +++ b/src/video_engine/stream_synchronization.h @@ -13,31 +13,11 @@ #include +#include "modules/remote_bitrate_estimator/include/rtp_to_ntp.h" #include "typedefs.h" // NOLINT namespace webrtc { -namespace synchronization { -struct RtcpMeasurement { - RtcpMeasurement(); - RtcpMeasurement(uint32_t ntp_secs, uint32_t ntp_frac, uint32_t timestamp); - uint32_t ntp_secs; - uint32_t ntp_frac; - uint32_t rtp_timestamp; -}; - -typedef std::list RtcpList; - -// Converts an RTP timestamp to the NTP domain in milliseconds using two -// (RTP timestamp, NTP timestamp) pairs. -bool RtpToNtpMs(int64_t rtp_timestamp, const RtcpList& rtcp, - int64_t* timestamp_in_ms); - -// Returns 1 there has been a forward wrap around, 0 if there has been no wrap -// around and -1 if there has been a backwards wrap around (i.e. reordering). -int CheckForWrapArounds(uint32_t rtp_timestamp, uint32_t rtcp_rtp_timestamp); -} // namespace synchronization - struct ViESyncDelay; class StreamSynchronization { diff --git a/src/video_engine/stream_synchronization_unittest.cc b/src/video_engine/stream_synchronization_unittest.cc index bc249b5ed6..f693b753f5 100644 --- a/src/video_engine/stream_synchronization_unittest.cc +++ b/src/video_engine/stream_synchronization_unittest.cc @@ -459,152 +459,4 @@ TEST_F(StreamSynchronizationTest, BothDelayedVideoClockDrift) { video_clock_drift_ = 1.05; BothDelayedAudioLaterTest(); } - -TEST(WrapAroundTests, NoWrap) { - EXPECT_EQ(0, synchronization::CheckForWrapArounds(0xFFFFFFFF, 0xFFFFFFFE)); - EXPECT_EQ(0, synchronization::CheckForWrapArounds(1, 0)); - EXPECT_EQ(0, synchronization::CheckForWrapArounds(0x00010000, 0x0000FFFF)); -} - -TEST(WrapAroundTests, ForwardWrap) { - EXPECT_EQ(1, synchronization::CheckForWrapArounds(0, 0xFFFFFFFF)); - EXPECT_EQ(1, synchronization::CheckForWrapArounds(0, 0xFFFF0000)); - EXPECT_EQ(1, synchronization::CheckForWrapArounds(0x0000FFFF, 0xFFFFFFFF)); - EXPECT_EQ(1, synchronization::CheckForWrapArounds(0x0000FFFF, 0xFFFF0000)); -} - -TEST(WrapAroundTests, BackwardWrap) { - EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFFFFFF, 0)); - EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFF0000, 0)); - EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFFFFFF, 0x0000FFFF)); - EXPECT_EQ(-1, synchronization::CheckForWrapArounds(0xFFFF0000, 0x0000FFFF)); -} - -TEST(WrapAroundTests, OldRtcpWrapped) { - synchronization::RtcpList rtcp; - uint32_t ntp_sec = 0; - uint32_t ntp_frac = 0; - uint32_t timestamp = 0; - const uint32_t kOneMsInNtpFrac = 4294967; - const uint32_t kTimestampTicksPerMs = 90; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp -= kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp -= kTimestampTicksPerMs; - int64_t timestamp_in_ms = -1; - // This expected to fail since it's highly unlikely that the older RTCP - // has a much smaller RTP timestamp than the newer. - EXPECT_FALSE(synchronization::RtpToNtpMs(timestamp, rtcp, ×tamp_in_ms)); -} - -TEST(WrapAroundTests, NewRtcpWrapped) { - synchronization::RtcpList rtcp; - uint32_t ntp_sec = 0; - uint32_t ntp_frac = 0; - uint32_t timestamp = 0xFFFFFFFF; - const uint32_t kOneMsInNtpFrac = 4294967; - const uint32_t kTimestampTicksPerMs = 90; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp += kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - int64_t timestamp_in_ms = -1; - EXPECT_TRUE(synchronization::RtpToNtpMs(rtcp.back().rtp_timestamp, rtcp, - ×tamp_in_ms)); - // Since this RTP packet has the same timestamp as the RTCP packet constructed - // at time 0 it should be mapped to 0 as well. - EXPECT_EQ(0, timestamp_in_ms); -} - -TEST(WrapAroundTests, RtpWrapped) { - const uint32_t kOneMsInNtpFrac = 4294967; - const uint32_t kTimestampTicksPerMs = 90; - synchronization::RtcpList rtcp; - uint32_t ntp_sec = 0; - uint32_t ntp_frac = 0; - uint32_t timestamp = 0xFFFFFFFF - 2 * kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp += kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp += kTimestampTicksPerMs; - int64_t timestamp_in_ms = -1; - EXPECT_TRUE(synchronization::RtpToNtpMs(timestamp, rtcp, - ×tamp_in_ms)); - // Since this RTP packet has the same timestamp as the RTCP packet constructed - // at time 0 it should be mapped to 0 as well. - EXPECT_EQ(2, timestamp_in_ms); -} - -TEST(WrapAroundTests, OldRtp_RtcpsWrapped) { - const uint32_t kOneMsInNtpFrac = 4294967; - const uint32_t kTimestampTicksPerMs = 90; - synchronization::RtcpList rtcp; - uint32_t ntp_sec = 0; - uint32_t ntp_frac = 0; - uint32_t timestamp = 0; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp += kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp -= 2*kTimestampTicksPerMs; - int64_t timestamp_in_ms = -1; - EXPECT_FALSE(synchronization::RtpToNtpMs(timestamp, rtcp, - ×tamp_in_ms)); -} - -TEST(WrapAroundTests, OldRtp_NewRtcpWrapped) { - const uint32_t kOneMsInNtpFrac = 4294967; - const uint32_t kTimestampTicksPerMs = 90; - synchronization::RtcpList rtcp; - uint32_t ntp_sec = 0; - uint32_t ntp_frac = 0; - uint32_t timestamp = 0xFFFFFFFF; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp += kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp -= kTimestampTicksPerMs; - int64_t timestamp_in_ms = -1; - EXPECT_TRUE(synchronization::RtpToNtpMs(timestamp, rtcp, - ×tamp_in_ms)); - // Constructed at the same time as the first RTCP and should therefore be - // mapped to zero. - EXPECT_EQ(0, timestamp_in_ms); -} - -TEST(WrapAroundTests, OldRtp_OldRtcpWrapped) { - const uint32_t kOneMsInNtpFrac = 4294967; - const uint32_t kTimestampTicksPerMs = 90; - synchronization::RtcpList rtcp; - uint32_t ntp_sec = 0; - uint32_t ntp_frac = 0; - uint32_t timestamp = 0; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp -= kTimestampTicksPerMs; - rtcp.push_front(synchronization::RtcpMeasurement(ntp_sec, ntp_frac, - timestamp)); - ntp_frac += kOneMsInNtpFrac; - timestamp += 2*kTimestampTicksPerMs; - int64_t timestamp_in_ms = -1; - EXPECT_FALSE(synchronization::RtpToNtpMs(timestamp, rtcp, - ×tamp_in_ms)); -} } // namespace webrtc