Change NtpTime representation to single uint64_t
Add explicit conversions to/from uint64_t

uint64_t is natural type for NtpTime, including wrap on overflow.

BUG=None

Review-Url: https://codereview.webrtc.org/2695683002
Cr-Commit-Position: refs/heads/master@{#16624}
diff --git a/webrtc/system_wrappers/include/ntp_time.h b/webrtc/system_wrappers/include/ntp_time.h
index ecb303a..5e53064 100644
--- a/webrtc/system_wrappers/include/ntp_time.h
+++ b/webrtc/system_wrappers/include/ntp_time.h
@@ -16,41 +16,39 @@
 
 class NtpTime {
  public:
-  NtpTime() : seconds_(0), fractions_(0) {}
+  static constexpr uint64_t kFractionsPerSecond = 0x100000000;
+  NtpTime() : value_(0) {}
+  explicit NtpTime(uint64_t value) : value_(value) {}
   NtpTime(uint32_t seconds, uint32_t fractions)
-      : seconds_(seconds), fractions_(fractions) {}
+      : value_(seconds * kFractionsPerSecond + fractions) {}
 
   NtpTime(const NtpTime&) = default;
   NtpTime& operator=(const NtpTime&) = default;
+  explicit operator uint64_t() const { return value_; }
 
   void Set(uint32_t seconds, uint32_t fractions) {
-    seconds_ = seconds;
-    fractions_ = fractions;
+    value_ = seconds * kFractionsPerSecond + fractions;
   }
-  void Reset() {
-    seconds_ = 0;
-    fractions_ = 0;
-  }
+  void Reset() { value_ = 0; }
 
   int64_t ToMs() const {
     static constexpr double kNtpFracPerMs = 4.294967296E6;  // 2^32 / 1000.
-    const double frac_ms = static_cast<double>(fractions_) / kNtpFracPerMs;
-    return 1000 * static_cast<int64_t>(seconds_) +
+    const double frac_ms = static_cast<double>(fractions()) / kNtpFracPerMs;
+    return 1000 * static_cast<int64_t>(seconds()) +
            static_cast<int64_t>(frac_ms + 0.5);
   }
-  // NTP standard (RFC1305, section 3.1) explicitly state value 0/0 is invalid.
-  bool Valid() const { return !(seconds_ == 0 && fractions_ == 0); }
+  // NTP standard (RFC1305, section 3.1) explicitly state value 0 is invalid.
+  bool Valid() const { return value_ != 0; }
 
-  uint32_t seconds() const { return seconds_; }
-  uint32_t fractions() const { return fractions_; }
+  uint32_t seconds() const { return value_ / kFractionsPerSecond; }
+  uint32_t fractions() const { return value_ % kFractionsPerSecond; }
 
  private:
-  uint32_t seconds_;
-  uint32_t fractions_;
+  uint64_t value_;
 };
 
 inline bool operator==(const NtpTime& n1, const NtpTime& n2) {
-  return n1.seconds() == n2.seconds() && n1.fractions() == n2.fractions();
+  return static_cast<uint64_t>(n1) == static_cast<uint64_t>(n2);
 }
 inline bool operator!=(const NtpTime& n1, const NtpTime& n2) {
   return !(n1 == n2);
diff --git a/webrtc/system_wrappers/source/ntp_time_unittest.cc b/webrtc/system_wrappers/source/ntp_time_unittest.cc
index fe04471..9a2a926 100644
--- a/webrtc/system_wrappers/source/ntp_time_unittest.cc
+++ b/webrtc/system_wrappers/source/ntp_time_unittest.cc
@@ -54,5 +54,12 @@
   EXPECT_EQ(ntp.ToMs(), clock.CurrentNtpInMilliseconds());
 }
 
+TEST(NtpTimeTest, CanExplicitlyConvertToAndFromUint64) {
+  uint64_t untyped_time = 0x123456789;
+  NtpTime time(untyped_time);
+  EXPECT_EQ(untyped_time, static_cast<uint64_t>(time));
+  EXPECT_EQ(NtpTime(0x12345678, 0x90abcdef), NtpTime(0x1234567890abcdef));
+}
+
 }  // namespace
 }  // namespace webrtc