Propagate time of the last received packet with Timestamp type

Bug: webrtc:13757
Change-Id: I446fc10ad6a90ab9ecaac337b9f2ad4ccad37cbd
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/307020
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40211}
diff --git a/audio/audio_receive_stream.cc b/audio/audio_receive_stream.cc
index bde48aa..978bbb2 100644
--- a/audio/audio_receive_stream.cc
+++ b/audio/audio_receive_stream.cc
@@ -266,8 +266,7 @@
   stats.packets_lost = call_stats.cumulativeLost;
   stats.nacks_sent = call_stats.nacks_sent;
   stats.capture_start_ntp_time_ms = call_stats.capture_start_ntp_time_ms_;
-  stats.last_packet_received_timestamp_ms =
-      call_stats.last_packet_received_timestamp_ms;
+  stats.last_packet_received = call_stats.last_packet_received;
   stats.codec_name = receive_codec->second.name;
   stats.codec_payload_type = receive_codec->first;
   int clockrate_khz = receive_codec->second.clockrate_hz / 1000;
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
index b056028..32c4676 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -828,13 +828,12 @@
         rtp_stats.packet_counter.header_bytes +
         rtp_stats.packet_counter.padding_bytes;
     stats.packetsReceived = rtp_stats.packet_counter.packets;
-    stats.last_packet_received_timestamp_ms =
-        rtp_stats.last_packet_received_timestamp_ms;
+    stats.last_packet_received = rtp_stats.last_packet_received;
   } else {
     stats.payload_bytes_received = 0;
     stats.header_and_padding_bytes_received = 0;
     stats.packetsReceived = 0;
-    stats.last_packet_received_timestamp_ms = absl::nullopt;
+    stats.last_packet_received = absl::nullopt;
   }
 
   {
diff --git a/audio/channel_receive.h b/audio/channel_receive.h
index 13edf04..ab69103 100644
--- a/audio/channel_receive.h
+++ b/audio/channel_receive.h
@@ -63,7 +63,7 @@
   // The timestamp at which the last packet was received, i.e. the time of the
   // local clock when it was received - not the RTP timestamp of that packet.
   // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-lastpacketreceivedtimestamp
-  absl::optional<int64_t> last_packet_received_timestamp_ms;
+  absl::optional<Timestamp> last_packet_received;
   // Remote outbound stats derived by the received RTCP sender reports.
   // Note that the timestamps below correspond to the time elapsed since the
   // Unix epoch.
diff --git a/call/audio_receive_stream.h b/call/audio_receive_stream.h
index b0e94fe..4879311 100644
--- a/call/audio_receive_stream.h
+++ b/call/audio_receive_stream.h
@@ -83,7 +83,7 @@
     // The timestamp at which the last packet was received, i.e. the time of the
     // local clock when it was received - not the RTP timestamp of that packet.
     // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-lastpacketreceivedtimestamp
-    absl::optional<int64_t> last_packet_received_timestamp_ms;
+    absl::optional<Timestamp> last_packet_received;
     uint64_t jitter_buffer_flushes = 0;
     double relative_packet_arrival_delay_seconds = 0.0;
     int32_t interruption_count = 0;
diff --git a/media/BUILD.gn b/media/BUILD.gn
index 795e2af..8508a7b 100644
--- a/media/BUILD.gn
+++ b/media/BUILD.gn
@@ -250,6 +250,7 @@
     "../api/transport:datagram_transport_interface",
     "../api/transport/rtp:rtp_source",
     "../api/units:time_delta",
+    "../api/units:timestamp",
     "../api/video:recordable_encoded_frame",
     "../api/video:video_frame",
     "../api/video:video_rtp_headers",
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index e982284..58e35f3 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -33,6 +33,7 @@
 #include "api/transport/data_channel_transport_interface.h"
 #include "api/transport/rtp/rtp_source.h"
 #include "api/units/time_delta.h"
+#include "api/units/timestamp.h"
 #include "api/video/video_content_type.h"
 #include "api/video/video_sink_interface.h"
 #include "api/video/video_source_interface.h"
@@ -458,7 +459,7 @@
   // The timestamp at which the last packet was received, i.e. the time of the
   // local clock when it was received - not the RTP timestamp of that packet.
   // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-lastpacketreceivedtimestamp
-  absl::optional<int64_t> last_packet_received_timestamp_ms;
+  absl::optional<webrtc::Timestamp> last_packet_received;
   // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-estimatedplayouttimestamp
   absl::optional<int64_t> estimated_playout_ntp_timestamp_ms;
   std::string codec_name;
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 8c7fad1..f07ff1a3 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -3572,8 +3572,7 @@
   info.total_assembly_time = stats.total_assembly_time;
   info.frames_assembled_from_multiple_packets =
       stats.frames_assembled_from_multiple_packets;
-  info.last_packet_received_timestamp_ms =
-      stats.rtp_stats.last_packet_received_timestamp_ms;
+  info.last_packet_received = stats.rtp_stats.last_packet_received;
   info.estimated_playout_ntp_timestamp_ms =
       stats.estimated_playout_ntp_timestamp_ms;
   info.first_frame_received_to_decoded_ms =
diff --git a/media/engine/webrtc_voice_engine.cc b/media/engine/webrtc_voice_engine.cc
index 86c56fc..4c7abed 100644
--- a/media/engine/webrtc_voice_engine.cc
+++ b/media/engine/webrtc_voice_engine.cc
@@ -2496,8 +2496,7 @@
     rinfo.decoding_plc_cng = stats.decoding_plc_cng;
     rinfo.decoding_muted_output = stats.decoding_muted_output;
     rinfo.capture_start_ntp_time_ms = stats.capture_start_ntp_time_ms;
-    rinfo.last_packet_received_timestamp_ms =
-        stats.last_packet_received_timestamp_ms;
+    rinfo.last_packet_received = stats.last_packet_received;
     rinfo.estimated_playout_ntp_timestamp_ms =
         stats.estimated_playout_ntp_timestamp_ms;
     rinfo.jitter_buffer_flushes = stats.jitter_buffer_flushes;
diff --git a/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
index 26126e3..594b333 100644
--- a/modules/rtp_rtcp/include/rtp_rtcp_defines.h
+++ b/modules/rtp_rtcp/include/rtp_rtcp_defines.h
@@ -387,9 +387,12 @@
   // Interarrival jitter in time.
   webrtc::TimeDelta interarrival_jitter = webrtc::TimeDelta::Zero();
 
-  // Timestamp and counters exposed in RTCInboundRtpStreamStats, see
+  // Time of the last packet received in unix epoch,
+  // i.e. Timestamp::Zero() represents 1st Jan 1970 00:00
+  absl::optional<Timestamp> last_packet_received;
+
+  // Counters exposed in RTCInboundRtpStreamStats, see
   // https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict*
-  absl::optional<int64_t> last_packet_received_timestamp_ms;
   RtpPacketCounter packet_counter;
 };
 
diff --git a/modules/rtp_rtcp/source/receive_statistics_impl.cc b/modules/rtp_rtcp/source/receive_statistics_impl.cc
index d52de41..6fe2000 100644
--- a/modules/rtp_rtcp/source/receive_statistics_impl.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_impl.cc
@@ -227,8 +227,8 @@
         TimeDelta::Seconds(stats.jitter) / last_payload_type_frequency_;
   }
   if (last_receive_time_.has_value()) {
-    stats.last_packet_received_timestamp_ms =
-        (*last_receive_time_ + delta_internal_unix_epoch_).ms();
+    stats.last_packet_received =
+        *last_receive_time_ + delta_internal_unix_epoch_;
   }
   stats.packet_counter = receive_counters_.transmitted;
   return stats;
diff --git a/modules/rtp_rtcp/source/receive_statistics_unittest.cc b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
index 66e3061..a255854 100644
--- a/modules/rtp_rtcp/source/receive_statistics_unittest.cc
+++ b/modules/rtp_rtcp/source/receive_statistics_unittest.cc
@@ -595,13 +595,13 @@
   RtpReceiveStats counters =
       receive_statistics_->GetStatistician(kSsrc1)->GetStats();
 
-  EXPECT_EQ(42, counters.last_packet_received_timestamp_ms);
+  EXPECT_EQ(counters.last_packet_received, Timestamp::Millis(42));
 
   clock_.AdvanceTimeMilliseconds(3);
   packet1_.SetSequenceNumber(101);
   receive_statistics_->OnRtpPacket(packet1_);
   counters = receive_statistics_->GetStatistician(kSsrc1)->GetStats();
-  EXPECT_EQ(45, counters.last_packet_received_timestamp_ms);
+  EXPECT_EQ(counters.last_packet_received, Timestamp::Millis(45));
 }
 
 TEST_P(ReceiveStatisticsTest, SimpleJitterComputation) {
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index eeee3b8..48e8542 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -474,9 +474,9 @@
       voice_receiver_info.total_output_duration;
   // `fir_count` and `pli_count` are only valid for video and are
   // purposefully left undefined for audio.
-  if (voice_receiver_info.last_packet_received_timestamp_ms.has_value()) {
-    inbound_audio->last_packet_received_timestamp = static_cast<double>(
-        *voice_receiver_info.last_packet_received_timestamp_ms);
+  if (voice_receiver_info.last_packet_received.has_value()) {
+    inbound_audio->last_packet_received_timestamp =
+        voice_receiver_info.last_packet_received->ms<double>();
   }
   if (voice_receiver_info.estimated_playout_ntp_timestamp_ms.has_value()) {
     // TODO(bugs.webrtc.org/10529): Fix time origin.
@@ -649,9 +649,9 @@
   inbound_video->min_playout_delay =
       static_cast<double>(video_receiver_info.min_playout_delay_ms) /
       rtc::kNumMillisecsPerSec;
-  if (video_receiver_info.last_packet_received_timestamp_ms.has_value()) {
-    inbound_video->last_packet_received_timestamp = static_cast<double>(
-        *video_receiver_info.last_packet_received_timestamp_ms);
+  if (video_receiver_info.last_packet_received.has_value()) {
+    inbound_video->last_packet_received_timestamp =
+        video_receiver_info.last_packet_received->ms<double>();
   }
   if (video_receiver_info.estimated_playout_ntp_timestamp_ms.has_value()) {
     // TODO(bugs.webrtc.org/10529): Fix time origin if needed.
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index 79d61ad..a8111bf 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -2183,9 +2183,7 @@
   voice_media_info.receivers[0].relative_packet_arrival_delay_seconds = 16;
   voice_media_info.receivers[0].interruption_count = 7788;
   voice_media_info.receivers[0].total_interruption_duration_ms = 778899;
-
-  voice_media_info.receivers[0].last_packet_received_timestamp_ms =
-      absl::nullopt;
+  voice_media_info.receivers[0].last_packet_received = absl::nullopt;
 
   RtpCodecParameters codec_parameters;
   codec_parameters.payload_type = 42;
@@ -2251,7 +2249,7 @@
       expected_audio);
 
   // Set previously undefined values and "GetStats" again.
-  voice_media_info.receivers[0].last_packet_received_timestamp_ms = 3000;
+  voice_media_info.receivers[0].last_packet_received = Timestamp::Seconds(3);
   expected_audio.last_packet_received_timestamp = 3000.0;
   voice_media_info.receivers[0].estimated_playout_ntp_timestamp_ms = 4567;
   expected_audio.estimated_playout_timestamp = 4567;
@@ -2344,8 +2342,7 @@
   video_media_info.receivers[0].jitter_buffer_target_delay_seconds = 1.1;
   video_media_info.receivers[0].jitter_buffer_minimum_delay_seconds = 0.999;
   video_media_info.receivers[0].jitter_buffer_emitted_count = 13;
-  video_media_info.receivers[0].last_packet_received_timestamp_ms =
-      absl::nullopt;
+  video_media_info.receivers[0].last_packet_received = absl::nullopt;
   video_media_info.receivers[0].content_type = VideoContentType::UNSPECIFIED;
   video_media_info.receivers[0].estimated_playout_ntp_timestamp_ms =
       absl::nullopt;
@@ -2427,7 +2424,7 @@
   // Set previously undefined values and "GetStats" again.
   video_media_info.receivers[0].qp_sum = 9;
   expected_video.qp_sum = 9;
-  video_media_info.receivers[0].last_packet_received_timestamp_ms = 1000;
+  video_media_info.receivers[0].last_packet_received = Timestamp::Seconds(1);
   expected_video.last_packet_received_timestamp = 1000.0;
   video_media_info.receivers[0].content_type = VideoContentType::SCREENSHARE;
   expected_video.content_type = "screenshare";