[rtp_rtcp] time helper functions
  RTP timestams helper functions moved from rtp_utility
  added functions to deal with CompactNtp timestamps

R=åsapersson
BUG=webrtc:5260

Review URL: https://codereview.webrtc.org/1535113002

Cr-Commit-Position: refs/heads/master@{#11106}
diff --git a/webrtc/modules/modules.gyp b/webrtc/modules/modules.gyp
index edaa2f8..06a8822 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 8ac7e0a..f089d36 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 @@
       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 @@
   // 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 @@
     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::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::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 b3ef287..025dcd4 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 @@
  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 @@
   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 fb9b206..93b115a 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 17fbbac..940d12b 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 @@
 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 fcd43ad..bd7df42 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.cc
@@ -77,38 +77,6 @@
 };
 
 /*
- * 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 7582f3a..bdcb11c 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_utility.h
+++ b/webrtc/modules/rtp_rtcp/source/rtp_utility.h
@@ -46,15 +46,6 @@
 
     typedef std::map<int8_t, Payload*> 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 0000000..5b544dd
--- /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<uint64_t>(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<uint64_t>(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 0000000..7efb83c
--- /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