Update ReceiveStatistics to use Timestamp/TimeDelta to represent time

Bug: webrtc:13757
Change-Id: I1606a14ecf8ccb520428b84eed2f9a8ba746162f
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/307181
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40188}
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index 48a1fe8..d52de41 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -27,8 +27,16 @@
 
 namespace webrtc {
 namespace {
-constexpr int64_t kStatisticsTimeoutMs = 8000;
-constexpr int64_t kStatisticsProcessIntervalMs = 1000;
+constexpr TimeDelta kStatisticsTimeout = TimeDelta::Seconds(8);
+constexpr TimeDelta kStatisticsProcessInterval = TimeDelta::Seconds(1);
+
+TimeDelta UnixEpochDelta(Clock& clock) {
+  Timestamp now = clock.CurrentTime();
+  NtpTime ntp_now = clock.ConvertTimestampToNtpTime(now);
+  return TimeDelta::Millis(ntp_now.ToMs() - now.ms() -
+                           rtc::kNtpJan1970Millisecs);
+}
+
 }  // namespace
 
 StreamStatistician::~StreamStatistician() {}
@@ -38,10 +46,8 @@
                                                int max_reordering_threshold)
     : ssrc_(ssrc),
       clock_(clock),
-      delta_internal_unix_epoch_ms_(clock_->CurrentNtpInMilliseconds() -
-                                    clock_->TimeInMilliseconds() -
-                                    rtc::kNtpJan1970Millisecs),
-      incoming_bitrate_(kStatisticsProcessIntervalMs,
+      delta_internal_unix_epoch_(UnixEpochDelta(*clock_)),
+      incoming_bitrate_(kStatisticsProcessInterval.ms(),
                         RateStatistics::kBpsScale),
       max_reordering_threshold_(max_reordering_threshold),
       enable_retransmit_detection_(false),
@@ -49,7 +55,6 @@
       jitter_q4_(0),
       cumulative_loss_(0),
       cumulative_loss_rtcp_offset_(0),
-      last_receive_time_ms_(0),
       last_received_timestamp_(0),
       received_seq_first_(-1),
       received_seq_max_(-1),
@@ -61,7 +66,7 @@
 
 bool StreamStatisticianImpl::UpdateOutOfOrder(const RtpPacketReceived& packet,
                                               int64_t sequence_number,
-                                              int64_t now_ms) {
+                                              Timestamp now) {
   // Check if `packet` is second packet of a stream restart.
   if (received_seq_out_of_order_) {
     // Count the previous packet as a received; it was postponed below.
@@ -103,7 +108,7 @@
     return false;
 
   // Old out of order packet, may be retransmit.
-  if (enable_retransmit_detection_ && IsRetransmitOfOldPacket(packet, now_ms))
+  if (enable_retransmit_detection_ && IsRetransmitOfOldPacket(packet, now))
     receive_counters_.retransmitted.AddPacket(packet);
   return true;
 }
@@ -111,9 +116,8 @@
 void StreamStatisticianImpl::UpdateCounters(const RtpPacketReceived& packet) {
   RTC_DCHECK_EQ(ssrc_, packet.Ssrc());
   Timestamp now = clock_->CurrentTime();
-  int64_t now_ms = now.ms();
 
-  incoming_bitrate_.Update(packet.size(), now_ms);
+  incoming_bitrate_.Update(packet.size(), now.ms());
   receive_counters_.transmitted.AddPacket(packet);
   --cumulative_loss_;
 
@@ -126,7 +130,7 @@
     last_report_seq_max_ = sequence_number - 1;
     received_seq_max_ = sequence_number - 1;
     receive_counters_.first_packet_time = now;
-  } else if (UpdateOutOfOrder(packet, sequence_number, now_ms)) {
+  } else if (UpdateOutOfOrder(packet, sequence_number, now)) {
     return;
   }
   // In order packet.
@@ -140,18 +144,19 @@
   if (packet.Timestamp() != last_received_timestamp_ &&
       (receive_counters_.transmitted.packets -
        receive_counters_.retransmitted.packets) > 1) {
-    UpdateJitter(packet, now_ms);
+    UpdateJitter(packet, now);
   }
   last_received_timestamp_ = packet.Timestamp();
-  last_receive_time_ms_ = now_ms;
+  last_receive_time_ = now;
 }
 
 void StreamStatisticianImpl::UpdateJitter(const RtpPacketReceived& packet,
-                                          int64_t receive_time_ms) {
-  int64_t receive_diff_ms = receive_time_ms - last_receive_time_ms_;
-  RTC_DCHECK_GE(receive_diff_ms, 0);
-  uint32_t receive_diff_rtp = static_cast<uint32_t>(
-      (receive_diff_ms * packet.payload_type_frequency()) / 1000);
+                                          Timestamp receive_time) {
+  RTC_DCHECK(last_receive_time_.has_value());
+  TimeDelta receive_diff = receive_time - *last_receive_time_;
+  RTC_DCHECK_GE(receive_diff, TimeDelta::Zero());
+  uint32_t receive_diff_rtp =
+      (receive_diff * packet.payload_type_frequency()).seconds<uint32_t>();
   int32_t time_diff_samples =
       receive_diff_rtp - (packet.Timestamp() - last_received_timestamp_);
 
@@ -178,13 +183,13 @@
   if (payload_type_frequency != 0) {
     if (last_payload_type_frequency_ != 0) {
       // Value in "jitter_q4_" variable is a number of samples.
-      // I.e. jitter = timestamp (ms) * frequency (kHz).
+      // I.e. jitter = timestamp (s) * frequency (Hz).
       // Since the frequency has changed we have to update the number of samples
       // accordingly. The new value should rely on a new frequency.
 
       // If we don't do such procedure we end up with the number of samples that
-      // cannot be converted into milliseconds correctly
-      // (i.e. jitter_ms = jitter_q4_ >> 4 / (payload_type_frequency / 1000)).
+      // cannot be converted into TimeDelta correctly
+      // (i.e. jitter = jitter_q4_ >> 4 / payload_type_frequency).
       // In such case, the number of samples has a "mix".
 
       // Doing so we pretend that everything prior and including the current
@@ -219,11 +224,11 @@
     // Divide value in fractional seconds by frequency to get jitter in
     // fractional seconds.
     stats.interarrival_jitter =
-        webrtc::TimeDelta::Seconds(stats.jitter) / last_payload_type_frequency_;
+        TimeDelta::Seconds(stats.jitter) / last_payload_type_frequency_;
   }
-  if (last_receive_time_ms_ > 0) {
+  if (last_receive_time_.has_value()) {
     stats.last_packet_received_timestamp_ms =
-        last_receive_time_ms_ + delta_internal_unix_epoch_ms_;
+        (*last_receive_time_ + delta_internal_unix_epoch_).ms();
   }
   stats.packet_counter = receive_counters_.transmitted;
   return stats;
@@ -231,12 +236,12 @@
 
 void StreamStatisticianImpl::MaybeAppendReportBlockAndReset(
     std::vector<rtcp::ReportBlock>& report_blocks) {
-  int64_t now_ms = clock_->TimeInMilliseconds();
-  if (now_ms - last_receive_time_ms_ >= kStatisticsTimeoutMs) {
-    // Not active.
+  if (!ReceivedRtpPacket()) {
     return;
   }
-  if (!ReceivedRtpPacket()) {
+  Timestamp now = clock_->CurrentTime();
+  if (now - *last_receive_time_ >= kStatisticsTimeout) {
+    // Not active.
     return;
   }
 
@@ -278,9 +283,9 @@
   // Only for report blocks in RTCP SR and RR.
   last_report_cumulative_loss_ = cumulative_loss_;
   last_report_seq_max_ = received_seq_max_;
-  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "cumulative_loss_pkts", now_ms,
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "cumulative_loss_pkts", now.ms(),
                                   cumulative_loss_, ssrc_);
-  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "received_seq_max_pkts", now_ms,
+  BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "received_seq_max_pkts", now.ms(),
                                   (received_seq_max_ - received_seq_first_),
                                   ssrc_);
 }
@@ -310,30 +315,26 @@
 
 bool StreamStatisticianImpl::IsRetransmitOfOldPacket(
     const RtpPacketReceived& packet,
-    int64_t now_ms) const {
-  uint32_t frequency_khz = packet.payload_type_frequency() / 1000;
-  RTC_DCHECK_GT(frequency_khz, 0);
-
-  int64_t time_diff_ms = now_ms - last_receive_time_ms_;
+    Timestamp now) const {
+  int frequency_hz = packet.payload_type_frequency();
+  RTC_DCHECK(last_receive_time_.has_value());
+  RTC_DCHECK_GT(frequency_hz, 0);
+  TimeDelta time_diff = now - *last_receive_time_;
 
   // Diff in time stamp since last received in order.
   uint32_t timestamp_diff = packet.Timestamp() - last_received_timestamp_;
-  uint32_t rtp_time_stamp_diff_ms = timestamp_diff / frequency_khz;
-
-  int64_t max_delay_ms = 0;
+  TimeDelta rtp_time_stamp_diff =
+      TimeDelta::Seconds(timestamp_diff) / frequency_hz;
 
   // Jitter standard deviation in samples.
   float jitter_std = std::sqrt(static_cast<float>(jitter_q4_ >> 4));
 
   // 2 times the standard deviation => 95% confidence.
-  // And transform to milliseconds by dividing by the frequency in kHz.
-  max_delay_ms = static_cast<int64_t>((2 * jitter_std) / frequency_khz);
+  // Min max_delay is 1ms.
+  TimeDelta max_delay = std::max(
+      TimeDelta::Seconds(2 * jitter_std / frequency_hz), TimeDelta::Millis(1));
 
-  // Min max_delay_ms is 1.
-  if (max_delay_ms == 0) {
-    max_delay_ms = 1;
-  }
-  return time_diff_ms > rtp_time_stamp_diff_ms + max_delay_ms;
+  return time_diff > rtp_time_stamp_diff + max_delay;
 }
 
 std::unique_ptr<ReceiveStatistics> ReceiveStatistics::Create(Clock* clock) {
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.h b/modules/rtp_rtcp/source/receive_statistics_impl.h
index 11853b3..8ec7c96 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.h
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.h
@@ -18,6 +18,8 @@
 #include <vector>
 
 #include "absl/types/optional.h"
+#include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
 #include "modules/rtp_rtcp/include/receive_statistics.h"
 #include "modules/rtp_rtcp/source/rtcp_packet/report_block.h"
 #include "rtc_base/containers/flat_map.h"
@@ -63,21 +65,21 @@
 
  private:
   bool IsRetransmitOfOldPacket(const RtpPacketReceived& packet,
-                               int64_t now_ms) const;
-  void UpdateJitter(const RtpPacketReceived& packet, int64_t receive_time_ms);
+                               Timestamp now) const;
+  void UpdateJitter(const RtpPacketReceived& packet, Timestamp receive_time);
   void ReviseFrequencyAndJitter(int payload_type_frequency);
   // Updates StreamStatistician for out of order packets.
   // Returns true if packet considered to be out of order.
   bool UpdateOutOfOrder(const RtpPacketReceived& packet,
                         int64_t sequence_number,
-                        int64_t now_ms);
+                        Timestamp now);
   // Checks if this StreamStatistician received any rtp packets.
-  bool ReceivedRtpPacket() const { return received_seq_first_ >= 0; }
+  bool ReceivedRtpPacket() const { return last_receive_time_.has_value(); }
 
   const uint32_t ssrc_;
   Clock* const clock_;
   // Delta used to map internal timestamps to Unix epoch ones.
-  const int64_t delta_internal_unix_epoch_ms_;
+  const TimeDelta delta_internal_unix_epoch_;
   RateStatistics incoming_bitrate_;
   // In number of packets or sequence numbers.
   int max_reordering_threshold_;
@@ -94,7 +96,7 @@
   // senders, in particular, our own loss-based bandwidth estimator.
   int32_t cumulative_loss_rtcp_offset_;
 
-  int64_t last_receive_time_ms_;
+  absl::optional<Timestamp> last_receive_time_;
   uint32_t last_received_timestamp_;
   RtpSequenceNumberUnwrapper seq_unwrapper_;
   int64_t received_seq_first_;