Function that Converts NtpTime to a Timestamp with UTC epoch in Clock.

danilchap@webrtc.org suggested to add a converter for NtpTime <-> UTC Timestamp for in https://webrtc-review.googlesource.com/c/src/+/365641.

This CL add a NtpTime -> UTC Timestamp in Clock, and change code to start to use the new function.

Bug: None
Change-Id: If4af6cb8e31c1731692edfb8358e67b7a43226a0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/366001
Commit-Queue: Olov Brändström <brandstrom@google.com>
Reviewed-by: Henrik Boström <hbos@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Henrik Andreassson <henrika@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#43293}
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
index 9fc2882..ea4c912 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -874,11 +874,9 @@
   if (rtcp_sr_stats.has_value()) {
     stats.last_sender_report_timestamp = rtcp_sr_stats->last_arrival_timestamp;
     stats.last_sender_report_utc_timestamp =
-        Timestamp::Millis(rtcp_sr_stats->last_arrival_ntp_timestamp.ToMs() -
-                          rtc::kNtpJan1970Millisecs);
+        Clock::NtpToUtc(rtcp_sr_stats->last_arrival_ntp_timestamp);
     stats.last_sender_report_remote_utc_timestamp =
-        Timestamp::Millis(rtcp_sr_stats->last_remote_ntp_timestamp.ToMs() -
-                          rtc::kNtpJan1970Millisecs);
+        Clock::NtpToUtc(rtcp_sr_stats->last_remote_ntp_timestamp);
     stats.sender_reports_packets_sent = rtcp_sr_stats->packets_sent;
     stats.sender_reports_bytes_sent = rtcp_sr_stats->bytes_sent;
     stats.sender_reports_reports_count = rtcp_sr_stats->reports_count;
diff --git a/modules/rtp_rtcp/source/rtcp_receiver.cc b/modules/rtp_rtcp/source/rtcp_receiver.cc
index 10f9d87..672ee98 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver.cc
@@ -621,9 +621,8 @@
   NtpTime now_ntp = env_.clock().ConvertTimestampToNtpTime(now);
   // Number of seconds since 1900 January 1 00:00 GMT (see
   // https://tools.ietf.org/html/rfc868).
-  report_block_data->SetReportBlock(
-      remote_ssrc, report_block,
-      Timestamp::Millis(now_ntp.ToMs() - rtc::kNtpJan1970Millisecs), now);
+  report_block_data->SetReportBlock(remote_ssrc, report_block,
+                                    Clock::NtpToUtc(now_ntp), now);
 
   uint32_t send_time_ntp = report_block.last_sr();
   // RFC3550, section 6.4.1, LSR field discription states:
diff --git a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
index b01c23c..f8789edc 100644
--- a/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
+++ b/modules/rtp_rtcp/source/rtcp_receiver_unittest.cc
@@ -1544,8 +1544,7 @@
   const uint32_t kCumulativeLoss = 7;
   const uint32_t kJitter = 9;
   const uint16_t kSequenceNumber = 1234;
-  const int64_t kNtpNowMs =
-      mocks.clock.CurrentNtpInMilliseconds() - rtc::kNtpJan1970Millisecs;
+  const Timestamp kUtcNow = Clock::NtpToUtc(mocks.clock.CurrentNtpTime());
 
   rtcp::ReportBlock rtcp_block;
   rtcp_block.SetMediaSsrc(kReceiverMainSsrc);
@@ -1566,8 +1565,7 @@
         EXPECT_EQ(rtcp_block.extended_high_seq_num(),
                   report_block.extended_highest_sequence_number());
         EXPECT_EQ(rtcp_block.jitter(), report_block.jitter());
-        EXPECT_EQ(report_block.report_block_timestamp_utc(),
-                  Timestamp::Millis(kNtpNowMs));
+        EXPECT_EQ(report_block.report_block_timestamp_utc(), kUtcNow);
         // No RTT is calculated in this test.
         EXPECT_EQ(0u, report_block.num_rtts());
       });
diff --git a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
index 858b580..e1d316d 100644
--- a/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
+++ b/modules/rtp_rtcp/source/rtcp_transceiver_impl.cc
@@ -362,8 +362,7 @@
   }
   NtpTime now_ntp = config_.clock->ConvertTimestampToNtpTime(now);
   uint32_t receive_time_ntp = CompactNtp(now_ntp);
-  Timestamp now_utc =
-      Timestamp::Millis(now_ntp.ToMs() - rtc::kNtpJan1970Millisecs);
+  Timestamp now_utc = Clock::NtpToUtc(now_ntp);
 
   for (const rtcp::ReportBlock& block : rtcp_report_blocks) {
     std::optional<TimeDelta> rtt;
diff --git a/system_wrappers/BUILD.gn b/system_wrappers/BUILD.gn
index 5e66d4b..1afd20a 100644
--- a/system_wrappers/BUILD.gn
+++ b/system_wrappers/BUILD.gn
@@ -142,6 +142,7 @@
       ":field_trial",
       ":metrics",
       ":system_wrappers",
+      "../api/units:time_delta",
       "../rtc_base:checks",
       "../rtc_base:random",
       "../rtc_base:stringutils",
diff --git a/system_wrappers/include/clock.h b/system_wrappers/include/clock.h
index 6029607..ec4bae0 100644
--- a/system_wrappers/include/clock.h
+++ b/system_wrappers/include/clock.h
@@ -48,6 +48,23 @@
     return ConvertTimestampToNtpTime(Timestamp::Millis(timestamp_ms)).ToMs();
   }
 
+  // Converts NtpTime to a Timestamp with UTC epoch.
+  // A `Minus Infinity` Timestamp is returned if the NtpTime is invalid.
+  static Timestamp NtpToUtc(NtpTime ntp_time) {
+    if (!ntp_time.Valid()) {
+      return Timestamp::MinusInfinity();
+    }
+    // Seconds since UTC epoch.
+    int64_t time = ntp_time.seconds() - kNtpJan1970;
+    // Microseconds since UTC epoch (not including NTP fraction)
+    time = time * 1'000'000;
+    // Fractions part of the NTP time, in microseconds.
+    int64_t time_fraction =
+        DivideRoundToNearest(int64_t{ntp_time.fractions()} * 1'000'000,
+                             NtpTime::kFractionsPerSecond);
+    return Timestamp::Micros(time + time_fraction);
+  }
+
   // Returns an instance of the real-time system clock implementation.
   static Clock* GetRealTimeClock();
 };
diff --git a/system_wrappers/source/clock_unittest.cc b/system_wrappers/source/clock_unittest.cc
index f7b0ed7..e50b789 100644
--- a/system_wrappers/source/clock_unittest.cc
+++ b/system_wrappers/source/clock_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "system_wrappers/include/clock.h"
 
+#include "api/units/time_delta.h"
 #include "test/gtest.h"
 
 namespace webrtc {
@@ -31,4 +32,13 @@
   EXPECT_GE(milliseconds_upper_bound + 1, ntp_time.ToMs());
 }
 
+TEST(ClockTest, NtpToUtc) {
+  Clock* clock = Clock::GetRealTimeClock();
+  NtpTime ntp = clock->CurrentNtpTime();
+  Timestamp a = Clock::NtpToUtc(ntp);
+  Timestamp b = Timestamp::Millis(ntp.ToMs() - int64_t{kNtpJan1970} * 1000);
+  TimeDelta d = a - b;
+  EXPECT_LT(d.Abs(), TimeDelta::Millis(1));
+}
+
 }  // namespace webrtc
diff --git a/video/video_receive_stream2.cc b/video/video_receive_stream2.cc
index aa3ff4a..610ef14 100644
--- a/video/video_receive_stream2.cc
+++ b/video/video_receive_stream2.cc
@@ -573,11 +573,9 @@
       rtp_video_stream_receiver_.GetSenderReportStats();
   if (rtcp_sr_stats) {
     stats.last_sender_report_utc_timestamp =
-        Timestamp::Millis(rtcp_sr_stats->last_arrival_ntp_timestamp.ToMs() -
-                          rtc::kNtpJan1970Millisecs);
+        Clock::NtpToUtc(rtcp_sr_stats->last_arrival_ntp_timestamp);
     stats.last_sender_report_remote_utc_timestamp =
-        Timestamp::Millis(rtcp_sr_stats->last_remote_ntp_timestamp.ToMs() -
-                          rtc::kNtpJan1970Millisecs);
+        Clock::NtpToUtc(rtcp_sr_stats->last_remote_ntp_timestamp);
     stats.sender_reports_packets_sent = rtcp_sr_stats->packets_sent;
     stats.sender_reports_bytes_sent = rtcp_sr_stats->bytes_sent;
     stats.sender_reports_reports_count = rtcp_sr_stats->reports_count;