diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp index edaa2f8aee..06a8822f39 100644 --- a/webrtc/modules/modules.gyp +++ b/webrtc/modules/modules.gyp @@ -328,6 +328,7 @@ 'rtp_rtcp/source/rtp_rtcp_impl_unittest.cc', 'rtp_rtcp/source/rtp_header_extension_unittest.cc', 'rtp_rtcp/source/rtp_sender_unittest.cc', + 'rtp_rtcp/source/time_util_unittest.cc', 'rtp_rtcp/source/vp8_partition_aggregator_unittest.cc', 'rtp_rtcp/test/testAPI/test_api.cc', 'rtp_rtcp/test/testAPI/test_api.h', diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc index 8ac7e0a383..f089d36afb 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.cc @@ -14,7 +14,7 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" -#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" +#include "webrtc/modules/rtp_rtcp/source/time_util.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" namespace webrtc { @@ -37,8 +37,6 @@ StreamStatisticianImpl::StreamStatisticianImpl( cumulative_loss_(0), jitter_q4_transmission_time_offset_(0), last_receive_time_ms_(0), - last_receive_time_secs_(0), - last_receive_time_frac_(0), last_received_timestamp_(0), last_received_transmission_time_offset_(0), received_seq_first_(0), @@ -79,9 +77,7 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, // are received, 4 will be ignored. if (in_order) { // Current time in samples. - uint32_t receive_time_secs; - uint32_t receive_time_frac; - clock_->CurrentNtp(receive_time_secs, receive_time_frac); + NtpTime receive_time(*clock_); // Wrong if we use RetransmitOfOldPacket. if (receive_counters_.transmitted.packets > 1 && @@ -97,11 +93,10 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, if (header.timestamp != last_received_timestamp_ && (receive_counters_.transmitted.packets - receive_counters_.retransmitted.packets) > 1) { - UpdateJitter(header, receive_time_secs, receive_time_frac); + UpdateJitter(header, receive_time); } last_received_timestamp_ = header.timestamp; - last_receive_time_secs_ = receive_time_secs; - last_receive_time_frac_ = receive_time_frac; + last_receive_time_ntp_ = receive_time; last_receive_time_ms_ = clock_->TimeInMilliseconds(); } @@ -113,14 +108,11 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header, } void StreamStatisticianImpl::UpdateJitter(const RTPHeader& header, - uint32_t receive_time_secs, - uint32_t receive_time_frac) { - uint32_t receive_time_rtp = RtpUtility::ConvertNTPTimeToRTP( - receive_time_secs, receive_time_frac, header.payload_type_frequency); + NtpTime receive_time) { + uint32_t receive_time_rtp = + NtpToRtp(receive_time, header.payload_type_frequency); uint32_t last_receive_time_rtp = - RtpUtility::ConvertNTPTimeToRTP(last_receive_time_secs_, - last_receive_time_frac_, - header.payload_type_frequency); + NtpToRtp(last_receive_time_ntp_, header.payload_type_frequency); int32_t time_diff_samples = (receive_time_rtp - last_receive_time_rtp) - (header.timestamp - last_received_timestamp_); @@ -319,8 +311,8 @@ void StreamStatisticianImpl::ProcessBitrate() { void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const { CriticalSectionScoped cs(stream_lock_.get()); - *secs = last_receive_time_secs_; - *frac = last_receive_time_frac_; + *secs = last_receive_time_ntp_.seconds(); + *frac = last_receive_time_ntp_.fractions(); } bool StreamStatisticianImpl::IsRetransmitOfOldPacket( diff --git a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h index b3ef287a1d..025dcd42c7 100644 --- a/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h +++ b/webrtc/modules/rtp_rtcp/source/receive_statistics_impl.h @@ -19,6 +19,7 @@ #include "webrtc/base/scoped_ptr.h" #include "webrtc/modules/rtp_rtcp/source/bitrate.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" +#include "webrtc/system_wrappers/include/ntp_time.h" namespace webrtc { @@ -52,9 +53,7 @@ class StreamStatisticianImpl : public StreamStatistician { private: bool InOrderPacketInternal(uint16_t sequence_number) const; RtcpStatistics CalculateRtcpStatistics(); - void UpdateJitter(const RTPHeader& header, - uint32_t receive_time_secs, - uint32_t receive_time_frac); + void UpdateJitter(const RTPHeader& header, NtpTime receive_time); void UpdateCounters(const RTPHeader& rtp_header, size_t packet_length, bool retransmitted); @@ -73,8 +72,7 @@ class StreamStatisticianImpl : public StreamStatistician { uint32_t jitter_q4_transmission_time_offset_; int64_t last_receive_time_ms_; - uint32_t last_receive_time_secs_; - uint32_t last_receive_time_frac_; + NtpTime last_receive_time_ntp_; uint32_t last_received_timestamp_; int32_t last_received_transmission_time_offset_; uint16_t received_seq_first_; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc index fb9b206cd1..93b115aa88 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_receiver_impl.cc @@ -22,7 +22,6 @@ namespace webrtc { -using RtpUtility::GetCurrentRTP; using RtpUtility::Payload; using RtpUtility::StringCompare; diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc index 17fbbac791..940d12b621 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc @@ -21,6 +21,7 @@ #include "webrtc/modules/rtp_rtcp/source/byte_io.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" +#include "webrtc/modules/rtp_rtcp/source/time_util.h" #include "webrtc/system_wrappers/include/critical_section_wrapper.h" #include "webrtc/system_wrappers/include/tick_util.h" @@ -1643,7 +1644,7 @@ uint16_t RTPSender::UpdateTransportSequenceNumber( void RTPSender::SetSendingStatus(bool enabled) { if (enabled) { uint32_t frequency_hz = SendPayloadFrequency(); - uint32_t RTPtime = RtpUtility::GetCurrentRTP(clock_, frequency_hz); + uint32_t RTPtime = CurrentRtp(*clock_, frequency_hz); // Will be ignored if it's already configured via API. SetStartTimestamp(RTPtime, false); diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc index fcd43ad197..bd7df42288 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc @@ -76,38 +76,6 @@ enum { kRtpMinParseLength = 12 }; -/* - * Time routines. - */ - -uint32_t GetCurrentRTP(Clock* clock, uint32_t freq) { - const bool use_global_clock = (clock == NULL); - Clock* local_clock = clock; - if (use_global_clock) { - local_clock = Clock::GetRealTimeClock(); - } - uint32_t secs = 0, frac = 0; - local_clock->CurrentNtp(secs, frac); - if (use_global_clock) { - delete local_clock; - } - return ConvertNTPTimeToRTP(secs, frac, freq); -} - -uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, uint32_t NTPfrac, uint32_t freq) { - float ftemp = (float)NTPfrac / (float)NTP_FRAC; - uint32_t tmp = (uint32_t)(ftemp * freq); - return NTPsec * freq + tmp; -} - -uint32_t ConvertNTPTimeToMS(uint32_t NTPsec, uint32_t NTPfrac) { - int freq = 1000; - float ftemp = (float)NTPfrac / (float)NTP_FRAC; - uint32_t tmp = (uint32_t)(ftemp * freq); - uint32_t MStime = NTPsec * freq + tmp; - return MStime; -} - /* * Misc utility routines */ diff --git a/webrtc/modules/rtp_rtcp/source/rtp_utility.h b/webrtc/modules/rtp_rtcp/source/rtp_utility.h index 7582f3a98a..bdcb11ccc2 100644 --- a/webrtc/modules/rtp_rtcp/source/rtp_utility.h +++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.h @@ -46,15 +46,6 @@ namespace RtpUtility { typedef std::map PayloadTypeMap; - // Return the current RTP timestamp from the NTP timestamp - // returned by the specified clock. - uint32_t GetCurrentRTP(Clock* clock, uint32_t freq); - - // Return the current RTP absolute timestamp. - uint32_t ConvertNTPTimeToRTP(uint32_t NTPsec, - uint32_t NTPfrac, - uint32_t freq); - uint32_t pow2(uint8_t exp); // Returns true if |newTimestamp| is older than |existingTimestamp|. diff --git a/webrtc/modules/rtp_rtcp/source/time_util.h b/webrtc/modules/rtp_rtcp/source/time_util.h new file mode 100644 index 0000000000..5b544ddf9a --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/time_util.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015 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_RTP_RTCP_SOURCE_TIME_UTIL_H_ +#define WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ + +#include "webrtc/base/basictypes.h" +#include "webrtc/system_wrappers/include/ntp_time.h" + +namespace webrtc { + +// Converts NTP timestamp to RTP timestamp. +inline uint32_t NtpToRtp(NtpTime ntp, uint32_t freq) { + uint32_t tmp = (static_cast(ntp.fractions()) * freq) >> 32; + return ntp.seconds() * freq + tmp; +} +// Return the current RTP timestamp from the NTP timestamp +// returned by the specified clock. +inline uint32_t CurrentRtp(const Clock& clock, uint32_t freq) { + return NtpToRtp(NtpTime(clock), freq); +} + +// Helper function for compact ntp representation: +// RFC 3550, Section 4. Time Format. +// Wallclock time is represented using the timestamp format of +// the Network Time Protocol (NTP). +// ... +// In some fields where a more compact representation is +// appropriate, only the middle 32 bits are used; that is, the low 16 +// bits of the integer part and the high 16 bits of the fractional part. +inline uint32_t CompactNtp(NtpTime ntp) { + return (ntp.seconds() << 16) | (ntp.fractions() >> 16); +} +// Converts interval between compact ntp timestamps to milliseconds. +// This interval can be upto ~18.2 hours (2^16 seconds). +inline uint32_t CompactNtpIntervalToMs(uint32_t compact_ntp_interval) { + return static_cast(compact_ntp_interval) * 1000 / (1 << 16); +} + +} // namespace webrtc +#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_TIME_UTIL_H_ diff --git a/webrtc/modules/rtp_rtcp/source/time_util_unittest.cc b/webrtc/modules/rtp_rtcp/source/time_util_unittest.cc new file mode 100644 index 0000000000..7efb83ccad --- /dev/null +++ b/webrtc/modules/rtp_rtcp/source/time_util_unittest.cc @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2015 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/rtp_rtcp/source/time_util.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace webrtc { + +TEST(TimeUtilTest, CompactNtp) { + const uint32_t kNtpSec = 0x12345678; + const uint32_t kNtpFrac = 0x23456789; + const NtpTime kNtp(kNtpSec, kNtpFrac); + const uint32_t kNtpMid = 0x56782345; + EXPECT_EQ(kNtpMid, CompactNtp(kNtp)); +} + +TEST(TimeUtilTest, CompactNtpToMs) { + const NtpTime ntp1(0x12345, 0x23456); + const NtpTime ntp2(0x12654, 0x64335); + uint32_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); + uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); + + uint32_t ntp_to_ms_diff = CompactNtpIntervalToMs(ntp_diff); + + EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); +} + +TEST(TimeUtilTest, CompactNtpToMsWithWrap) { + const NtpTime ntp1(0x1ffff, 0x23456); + const NtpTime ntp2(0x20000, 0x64335); + uint32_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); + + // While ntp2 > ntp1, there compact ntp presentation happen to be opposite. + // That shouldn't be a problem as long as unsigned arithmetic is used. + ASSERT_GT(ntp2.ToMs(), ntp1.ToMs()); + ASSERT_LT(CompactNtp(ntp2), CompactNtp(ntp1)); + + uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); + uint32_t ntp_to_ms_diff = CompactNtpIntervalToMs(ntp_diff); + + EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); +} + +TEST(TimeUtilTest, CompactNtpToMsLarge) { + const NtpTime ntp1(0x10000, 0x23456); + const NtpTime ntp2(0x1ffff, 0x64335); + uint32_t ms_diff = ntp2.ToMs() - ntp1.ToMs(); + // Ntp difference close to maximum of ~18 hours should convert correctly too. + ASSERT_GT(ms_diff, 18u * 3600 * 1000); + uint32_t ntp_diff = CompactNtp(ntp2) - CompactNtp(ntp1); + uint32_t ntp_to_ms_diff = CompactNtpIntervalToMs(ntp_diff); + + EXPECT_NEAR(ms_diff, ntp_to_ms_diff, 1); +} +} // namespace webrtc