Propagate arrival time inside NetEq

Bug: webrtc:341266986
Change-Id: I0fdd14e3fc5b09cbc9369497501f399464964211
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/352920
Commit-Queue: Lionel Koenig <lionelk@webrtc.org>
Reviewed-by: Jakob Ivarsson‎ <jakobi@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#42414}
diff --git a/api/neteq/BUILD.gn b/api/neteq/BUILD.gn
index f73085a..c29660d 100644
--- a/api/neteq/BUILD.gn
+++ b/api/neteq/BUILD.gn
@@ -23,6 +23,7 @@
     "../../rtc_base:stringutils",
     "../../system_wrappers:system_wrappers",
     "../audio_codecs:audio_codecs_api",
+    "../units:timestamp",
     "//third_party/abseil-cpp/absl/types:optional",
   ]
 }
diff --git a/api/neteq/neteq.h b/api/neteq/neteq.h
index 927bd62..d16f7ba 100644
--- a/api/neteq/neteq.h
+++ b/api/neteq/neteq.h
@@ -23,6 +23,7 @@
 #include "api/audio_codecs/audio_format.h"
 #include "api/rtp_headers.h"
 #include "api/scoped_refptr.h"
+#include "api/units/timestamp.h"
 
 namespace webrtc {
 
@@ -183,10 +184,20 @@
 
   virtual ~NetEq() {}
 
+  virtual int InsertPacket(const RTPHeader& rtp_header,
+                           rtc::ArrayView<const uint8_t> payload) {
+    // TODO: webrtc:343501093 - removed unused method.
+    return InsertPacket(rtp_header, payload,
+                        /*receive_time=*/Timestamp::MinusInfinity());
+  }
   // Inserts a new packet into NetEq.
   // Returns 0 on success, -1 on failure.
   virtual int InsertPacket(const RTPHeader& rtp_header,
-                           rtc::ArrayView<const uint8_t> payload) = 0;
+                           rtc::ArrayView<const uint8_t> payload,
+                           Timestamp receive_time) {
+    // TODO: webrtc:343501093 - Make this method pure virtual.
+    return InsertPacket(rtp_header, payload);
+  }
 
   // Lets NetEq know that a packet arrived with an empty payload. This typically
   // happens when empty packets are used for probing the network channel, and
diff --git a/audio/channel_receive.cc b/audio/channel_receive.cc
index 1fa396e..b2fa0bf 100644
--- a/audio/channel_receive.cc
+++ b/audio/channel_receive.cc
@@ -196,8 +196,8 @@
  private:
   void ReceivePacket(const uint8_t* packet,
                      size_t packet_length,
-                     const RTPHeader& header)
-      RTC_RUN_ON(worker_thread_checker_);
+                     const RTPHeader& header,
+                     Timestamp receive_time) RTC_RUN_ON(worker_thread_checker_);
   int ResendPackets(const uint16_t* sequence_numbers, int length);
   void UpdatePlayoutTimestamp(bool rtcp, int64_t now_ms)
       RTC_RUN_ON(worker_thread_checker_);
@@ -205,7 +205,8 @@
   int GetRtpTimestampRateHz() const;
 
   void OnReceivedPayloadData(rtc::ArrayView<const uint8_t> payload,
-                             const RTPHeader& rtpHeader)
+                             const RTPHeader& rtpHeader,
+                             Timestamp receive_time)
       RTC_RUN_ON(worker_thread_checker_);
 
   void InitFrameTransformerDelegate(
@@ -254,7 +255,6 @@
   AudioSinkInterface* audio_sink_ = nullptr;
   AudioLevel _outputAudioLevel;
 
-  Clock* const clock_;
   RemoteNtpTimeEstimator ntp_estimator_ RTC_GUARDED_BY(ts_stats_lock_);
 
   // Timestamp of the audio pulled from NetEq.
@@ -320,7 +320,8 @@
 
 void ChannelReceive::OnReceivedPayloadData(
     rtc::ArrayView<const uint8_t> payload,
-    const RTPHeader& rtpHeader) {
+    const RTPHeader& rtpHeader,
+    Timestamp receive_time) {
   if (!playing_) {
     // Avoid inserting into NetEQ when we are not playing. Count the
     // packet as discarded.
@@ -335,7 +336,7 @@
     // the SourceTracker from updating RtpSource information.
     if (source_tracker_) {
       RtpPacketInfos::vector_type packet_vector = {
-          RtpPacketInfo(rtpHeader, clock_->CurrentTime())};
+          RtpPacketInfo(rtpHeader, receive_time)};
       source_tracker_->OnFrameDelivered(RtpPacketInfos(packet_vector));
     }
 
@@ -343,7 +344,7 @@
   }
 
   // Push the incoming payload (parsed and ready for decoding) into the ACM
-  if (acm_receiver_.InsertPacket(rtpHeader, payload) != 0) {
+  if (acm_receiver_.InsertPacket(rtpHeader, payload, receive_time) != 0) {
     RTC_DLOG(LS_ERROR) << "ChannelReceive::OnReceivedPayloadData() unable to "
                           "push data to the ACM";
     return;
@@ -372,7 +373,9 @@
       receive_audio_callback = [this](rtc::ArrayView<const uint8_t> packet,
                                       const RTPHeader& header) {
         RTC_DCHECK_RUN_ON(&worker_thread_checker_);
-        OnReceivedPayloadData(packet, header);
+        // TODO(lionelk): Get the receive time.
+        OnReceivedPayloadData(packet, header,
+                              /*receive_time=*/Timestamp::MinusInfinity());
       };
   frame_transformer_delegate_ =
       rtc::make_ref_counted<ChannelReceiveFrameTransformerDelegate>(
@@ -545,7 +548,6 @@
                               jitter_buffer_fast_playout,
                               jitter_buffer_min_delay_ms)),
       _outputAudioLevel(),
-      clock_(clock),
       ntp_estimator_(clock),
       playout_timestamp_rtp_(0),
       playout_delay_ms_(0),
@@ -663,12 +665,14 @@
           rtc::saturated_cast<uint32_t>(packet_copy.payload_type_frequency()),
           header.extension.absolute_capture_time);
 
-  ReceivePacket(packet_copy.data(), packet_copy.size(), header);
+  ReceivePacket(packet_copy.data(), packet_copy.size(), header,
+                packet.arrival_time());
 }
 
 void ChannelReceive::ReceivePacket(const uint8_t* packet,
                                    size_t packet_length,
-                                   const RTPHeader& header) {
+                                   const RTPHeader& header,
+                                   Timestamp receive_time) {
   const uint8_t* payload = packet + header.headerLength;
   RTC_DCHECK_GE(packet_length, header.headerLength);
   size_t payload_length = packet_length - header.headerLength;
@@ -688,7 +692,8 @@
     const FrameDecryptorInterface::Result decrypt_result =
         frame_decryptor_->Decrypt(
             cricket::MEDIA_TYPE_AUDIO, csrcs,
-            /*additional_data=*/nullptr,
+            /*additional_data=*/
+            nullptr,
             rtc::ArrayView<const uint8_t>(payload, payload_data_length),
             decrypted_audio_payload);
 
@@ -720,7 +725,7 @@
     frame_transformer_delegate_->Transform(payload_data, header, remote_ssrc_,
                                            mime_type.str());
   } else {
-    OnReceivedPayloadData(payload_data, header);
+    OnReceivedPayloadData(payload_data, header, receive_time);
   }
 }
 
diff --git a/audio/voip/audio_ingress.cc b/audio/voip/audio_ingress.cc
index 80f2115..29363c1 100644
--- a/audio/voip/audio_ingress.cc
+++ b/audio/voip/audio_ingress.cc
@@ -11,6 +11,7 @@
 #include "audio/voip/audio_ingress.h"
 
 #include <algorithm>
+#include <ctime>
 #include <utility>
 #include <vector>
 
@@ -50,7 +51,8 @@
       rtp_receive_statistics_(receive_statistics),
       rtp_rtcp_(rtp_rtcp),
       acm_receiver_(CreateAcmConfig(decoder_factory)),
-      ntp_estimator_(clock) {}
+      ntp_estimator_(clock),
+      clock_(clock) {}
 
 AudioIngress::~AudioIngress() = default;
 
@@ -184,7 +186,8 @@
   auto data_view = rtc::ArrayView<const uint8_t>(payload, payload_data_length);
 
   // Push the incoming payload (parsed and ready for decoding) into the ACM.
-  if (acm_receiver_.InsertPacket(header, data_view) != 0) {
+  if (acm_receiver_.InsertPacket(header, data_view, clock_->CurrentTime()) !=
+      0) {
     RTC_DLOG(LS_ERROR) << "AudioIngress::ReceivedRTPPacket() unable to "
                           "push data to the ACM";
   }
diff --git a/audio/voip/audio_ingress.h b/audio/voip/audio_ingress.h
index 11bde7c..36876de 100644
--- a/audio/voip/audio_ingress.h
+++ b/audio/voip/audio_ingress.h
@@ -133,6 +133,8 @@
 
   RemoteNtpTimeEstimator ntp_estimator_ RTC_GUARDED_BY(lock_);
 
+  Clock* clock_;
+
   // For receiving RTP statistics, this tracks the sampling rate value
   // per payload type set when caller set via SetReceiveCodecs.
   std::map<int, int> receive_codec_info_ RTC_GUARDED_BY(lock_);
diff --git a/modules/audio_coding/BUILD.gn b/modules/audio_coding/BUILD.gn
index 0ae4e34..655a934 100644
--- a/modules/audio_coding/BUILD.gn
+++ b/modules/audio_coding/BUILD.gn
@@ -47,6 +47,7 @@
     "../../api/audio:audio_frame_api",
     "../../api/audio_codecs:audio_codecs_api",
     "../../api/neteq:neteq_api",
+    "../../api/units:timestamp",
     "../../common_audio",
     "../../common_audio:common_audio_c",
     "../../rtc_base:audio_format_to_string",
@@ -712,6 +713,7 @@
     "../../api/neteq:neteq_api",
     "../../api/neteq:neteq_controller_api",
     "../../api/neteq:tick_timer",
+    "../../api/units:timestamp",
     "../../common_audio",
     "../../common_audio:common_audio_c",
     "../../rtc_base:audio_format_to_string",
@@ -784,6 +786,7 @@
     "../../api/neteq:custom_neteq_factory",
     "../../api/neteq:default_neteq_controller_factory",
     "../../api/neteq:neteq_api",
+    "../../api/units:timestamp",
     "../../rtc_base:buffer",
     "../../rtc_base:checks",
     "../../rtc_base:copy_on_write_buffer",
@@ -938,6 +941,7 @@
     "../../api/audio_codecs:builtin_audio_decoder_factory",
     "../../api/audio_codecs:builtin_audio_encoder_factory",
     "../../api/neteq:neteq_api",
+    "../../api/units:timestamp",
     "../../rtc_base:checks",
     "../../rtc_base:digest",
     "../../rtc_base:stringutils",
@@ -1067,6 +1071,7 @@
       "../../api/audio_codecs/ilbc:audio_encoder_ilbc",
       "../../api/audio_codecs/opus:audio_decoder_opus",
       "../../api/audio_codecs/opus:audio_encoder_opus",
+      "../../api/units:timestamp",
       "../../common_audio",
       "../../rtc_base:checks",
       "../../rtc_base:logging",
@@ -1356,6 +1361,7 @@
         ":neteq_tools_minimal",
         "../../api/audio_codecs:builtin_audio_decoder_factory",
         "../../api/neteq:neteq_api",
+        "../../api/units:timestamp",
         "../../rtc_base:checks",
         "../../rtc_base:stringutils",
         "../../system_wrappers",
@@ -1684,6 +1690,7 @@
         "../../api/neteq:tick_timer",
         "../../api/neteq:tick_timer_unittest",
         "../../api/rtc_event_log",
+        "../../api/units:timestamp",
         "../../common_audio",
         "../../common_audio:common_audio_c",
         "../../common_audio:mock_common_audio",
diff --git a/modules/audio_coding/acm2/acm_receive_test.cc b/modules/audio_coding/acm2/acm_receive_test.cc
index 66f6255..20d0a2f 100644
--- a/modules/audio_coding/acm2/acm_receive_test.cc
+++ b/modules/audio_coding/acm2/acm_receive_test.cc
@@ -122,7 +122,8 @@
     EXPECT_EQ(0, acm_receiver_->InsertPacket(
                      packet->header(),
                      rtc::ArrayView<const uint8_t>(
-                         packet->payload(), packet->payload_length_bytes())))
+                         packet->payload(), packet->payload_length_bytes()),
+                     clock_.CurrentTime()))
         << "Failure when inserting packet:" << std::endl
         << "  PT = " << static_cast<int>(packet->header().payloadType)
         << std::endl
diff --git a/modules/audio_coding/acm2/acm_receiver.cc b/modules/audio_coding/acm2/acm_receiver.cc
index ab11358..c0ac681c 100644
--- a/modules/audio_coding/acm2/acm_receiver.cc
+++ b/modules/audio_coding/acm2/acm_receiver.cc
@@ -20,6 +20,7 @@
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/audio_decoder.h"
 #include "api/neteq/neteq.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/acm2/acm_resampler.h"
 #include "modules/audio_coding/acm2/call_statistics.h"
 #include "modules/audio_coding/neteq/default_neteq_factory.h"
@@ -102,7 +103,8 @@
 }
 
 int AcmReceiver::InsertPacket(const RTPHeader& rtp_header,
-                              rtc::ArrayView<const uint8_t> incoming_payload) {
+                              rtc::ArrayView<const uint8_t> incoming_payload,
+                              Timestamp receive_time) {
   if (incoming_payload.empty()) {
     neteq_->InsertEmptyPacket(rtp_header);
     return 0;
@@ -137,7 +139,7 @@
     }
   }  // `mutex_` is released.
 
-  if (neteq_->InsertPacket(rtp_header, incoming_payload) < 0) {
+  if (neteq_->InsertPacket(rtp_header, incoming_payload, receive_time) < 0) {
     RTC_LOG(LS_ERROR) << "AcmReceiver::InsertPacket "
                       << static_cast<int>(rtp_header.payloadType)
                       << " Failed to insert packet";
diff --git a/modules/audio_coding/acm2/acm_receiver.h b/modules/audio_coding/acm2/acm_receiver.h
index 21bee16..d631403 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -28,6 +28,7 @@
 #include "api/audio_codecs/audio_format.h"
 #include "api/neteq/neteq.h"
 #include "api/neteq/neteq_factory.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/acm2/acm_resampler.h"
 #include "modules/audio_coding/acm2/call_statistics.h"
 #include "modules/audio_coding/include/audio_coding_module_typedefs.h"
@@ -70,13 +71,15 @@
   //                            information about payload type, sequence number,
   //                            timestamp, SSRC and marker bit.
   //   - incoming_payload     : Incoming audio payload.
-  //   - length_payload       : Length of incoming audio payload in bytes.
+  //   - receive_time         : Timestamp when the packet has been seen on the
+  //                            network card.
   //
   // Return value             : 0 if OK.
   //                           <0 if NetEq returned an error.
   //
   int InsertPacket(const RTPHeader& rtp_header,
-                   rtc::ArrayView<const uint8_t> incoming_payload);
+                   rtc::ArrayView<const uint8_t> incoming_payload,
+                   Timestamp receive_time = Timestamp::MinusInfinity());
 
   //
   // Asks NetEq for 10 milliseconds of decoded audio.
diff --git a/modules/audio_coding/acm2/acm_receiver_unittest.cc b/modules/audio_coding/acm2/acm_receiver_unittest.cc
index 8b35f4a..e86c718 100644
--- a/modules/audio_coding/acm2/acm_receiver_unittest.cc
+++ b/modules/audio_coding/acm2/acm_receiver_unittest.cc
@@ -16,6 +16,7 @@
 #include "absl/types/optional.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/audio_codecs/builtin_audio_encoder_factory.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
 #include "modules/audio_coding/neteq/tools/rtp_generator.h"
@@ -119,7 +120,8 @@
 
     int ret_val = receiver_->InsertPacket(
         rtp_header_,
-        rtc::ArrayView<const uint8_t>(payload_data, payload_len_bytes));
+        rtc::ArrayView<const uint8_t>(payload_data, payload_len_bytes),
+        Timestamp::MinusInfinity());
     if (ret_val < 0) {
       RTC_DCHECK_NOTREACHED();
       return -1;
@@ -373,7 +375,8 @@
 
   for (int num_calls = 0; num_calls < kNumNormalCalls; ++num_calls) {
     const uint8_t kPayload[kPayloadSizeBytes] = {0};
-    ASSERT_EQ(0, receiver_->InsertPacket(rtp_header, kPayload));
+    ASSERT_EQ(0, receiver_->InsertPacket(rtp_header, kPayload,
+                                         Timestamp::MinusInfinity()));
     ++rtp_header.sequenceNumber;
     rtp_header.timestamp += kFrameSizeSamples;
     ASSERT_EQ(0, receiver_->GetAudio(-1, &audio_frame, &muted));
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index 75e38bc..7674538 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -25,6 +25,7 @@
 #include "api/audio_codecs/opus/audio_decoder_opus.h"
 #include "api/audio_codecs/opus/audio_encoder_multi_channel_opus.h"
 #include "api/audio_codecs/opus/audio_encoder_opus.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/acm2/acm_receive_test.h"
 #include "modules/audio_coding/acm2/acm_send_test.h"
 #include "modules/audio_coding/codecs/cng/audio_encoder_cng.h"
@@ -209,9 +210,10 @@
 
   virtual void InsertPacket() {
     const uint8_t kPayload[kPayloadSizeBytes] = {0};
-    ASSERT_EQ(0, acm_receiver_->InsertPacket(rtp_header_,
-                                             rtc::ArrayView<const uint8_t>(
-                                                 kPayload, kPayloadSizeBytes)));
+    ASSERT_EQ(0, acm_receiver_->InsertPacket(
+                     rtp_header_,
+                     rtc::ArrayView<const uint8_t>(kPayload, kPayloadSizeBytes),
+                     /*receive_time=*/Timestamp::MinusInfinity()));
     rtp_utility_->Forward(&rtp_header_);
   }
 
diff --git a/modules/audio_coding/neteq/neteq_impl.cc b/modules/audio_coding/neteq/neteq_impl.cc
index 1ee4dc4..dcdac98 100644
--- a/modules/audio_coding/neteq/neteq_impl.cc
+++ b/modules/audio_coding/neteq/neteq_impl.cc
@@ -193,11 +193,12 @@
 NetEqImpl::~NetEqImpl() = default;
 
 int NetEqImpl::InsertPacket(const RTPHeader& rtp_header,
-                            rtc::ArrayView<const uint8_t> payload) {
+                            rtc::ArrayView<const uint8_t> payload,
+                            Timestamp receive_time) {
   rtc::MsanCheckInitialized(payload);
   TRACE_EVENT0("webrtc", "NetEqImpl::InsertPacket");
   MutexLock lock(&mutex_);
-  if (InsertPacketInternal(rtp_header, payload) != 0) {
+  if (InsertPacketInternal(rtp_header, payload, receive_time) != 0) {
     return kFail;
   }
   return kOK;
@@ -464,13 +465,12 @@
 // Methods below this line are private.
 
 int NetEqImpl::InsertPacketInternal(const RTPHeader& rtp_header,
-                                    rtc::ArrayView<const uint8_t> payload) {
+                                    rtc::ArrayView<const uint8_t> payload,
+                                    Timestamp receive_time) {
   if (payload.empty()) {
     RTC_LOG_F(LS_ERROR) << "payload is empty";
     return kInvalidPointer;
   }
-
-  Timestamp receive_time = clock_->CurrentTime();
   stats_->ReceivedPacket();
 
   PacketList packet_list;
diff --git a/modules/audio_coding/neteq/neteq_impl.h b/modules/audio_coding/neteq/neteq_impl.h
index f808c9e..8730d9a 100644
--- a/modules/audio_coding/neteq/neteq_impl.h
+++ b/modules/audio_coding/neteq/neteq_impl.h
@@ -13,6 +13,7 @@
 
 #include <map>
 #include <memory>
+#include <optional>
 #include <string>
 #include <utility>
 #include <vector>
@@ -24,6 +25,7 @@
 #include "api/neteq/neteq_controller_factory.h"
 #include "api/neteq/tick_timer.h"
 #include "api/rtp_packet_info.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/neteq/audio_multi_vector.h"
 #include "modules/audio_coding/neteq/expand_uma_logger.h"
 #include "modules/audio_coding/neteq/packet.h"
@@ -127,7 +129,8 @@
 
   // Inserts a new packet into NetEq. Returns 0 on success, -1 on failure.
   int InsertPacket(const RTPHeader& rtp_header,
-                   rtc::ArrayView<const uint8_t> payload) override;
+                   rtc::ArrayView<const uint8_t> payload,
+                   Timestamp receive_time) override;
 
   void InsertEmptyPacket(const RTPHeader& rtp_header) override;
 
@@ -204,7 +207,8 @@
   // above. Returns 0 on success, otherwise an error code.
   // TODO(hlundin): Merge this with InsertPacket above?
   int InsertPacketInternal(const RTPHeader& rtp_header,
-                           rtc::ArrayView<const uint8_t> payload)
+                           rtc::ArrayView<const uint8_t> payload,
+                           Timestamp receive_time)
       RTC_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
 
   // Returns true if the payload type changed (this should be followed by
diff --git a/modules/audio_coding/neteq/neteq_impl_unittest.cc b/modules/audio_coding/neteq/neteq_impl_unittest.cc
index 07c924c..9018d78 100644
--- a/modules/audio_coding/neteq/neteq_impl_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_impl_unittest.cc
@@ -194,7 +194,9 @@
         kPayloadType, SdpAudioFormat("telephone-event", sample_rate_hz, 1)));
 
     // Insert first packet.
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
 
     // Pull audio once.
     const size_t kMaxOutputSize =
@@ -373,12 +375,14 @@
   }
 
   // Insert first packet.
-  neteq_->InsertPacket(rtp_header, payload);
+  neteq_->InsertPacket(rtp_header, payload,
+                       /*receive_time=*/clock_.CurrentTime());
 
   // Insert second packet.
   rtp_header.timestamp += 160;
   rtp_header.sequenceNumber += 1;
-  neteq_->InsertPacket(rtp_header, payload);
+  neteq_->InsertPacket(rtp_header, payload,
+                       /*receive_time=*/clock_.CurrentTime());
 }
 
 TEST_F(NetEqImplTest, InsertPacketsUntilBufferIsFull) {
@@ -400,7 +404,9 @@
 
   // Insert packets. The buffer should not flush.
   for (size_t i = 1; i <= config_.max_packets_in_buffer; ++i) {
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
     rtp_header.timestamp += kPayloadLengthSamples;
     rtp_header.sequenceNumber += 1;
     EXPECT_EQ(i, packet_buffer_->NumPacketsInBuffer());
@@ -408,7 +414,9 @@
 
   // Insert one more packet and make sure the buffer got flushed. That is, it
   // should only hold one single packet.
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
   EXPECT_EQ(1u, packet_buffer_->NumPacketsInBuffer());
   const Packet* test_packet = packet_buffer_->PeekNextPacket();
   EXPECT_EQ(rtp_header.timestamp, test_packet->timestamp);
@@ -494,7 +502,8 @@
   // Insert one packet.
   clock_.AdvanceTimeMilliseconds(123456);
   Timestamp expected_receive_time = clock_.CurrentTime();
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload, expected_receive_time));
 
   // Pull audio once.
   const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
@@ -588,7 +597,9 @@
   // Insert one packet.
   clock_.AdvanceTimeMilliseconds(123456);
   Timestamp expected_receive_time = clock_.CurrentTime();
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 
   // Pull audio once.
   const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
@@ -618,14 +629,18 @@
   rtp_header.extension.set_audio_level(AudioLevel(/*voice_activity=*/false, 1));
   payload[0] = 1;
   clock_.AdvanceTimeMilliseconds(1000);
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
   rtp_header.sequenceNumber += 2;
   rtp_header.timestamp += 2 * kPayloadLengthSamples;
   rtp_header.extension.set_audio_level(AudioLevel(/*voice_activity=*/false, 2));
   payload[0] = 2;
   clock_.AdvanceTimeMilliseconds(2000);
   expected_receive_time = clock_.CurrentTime();
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 
   // Expect only the second packet to be decoded (the one with "2" as the first
   // payload byte).
@@ -684,7 +699,9 @@
 
   // Insert one packet. Note that we have not registered any payload type, so
   // this packet will be rejected.
-  EXPECT_EQ(NetEq::kFail, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kFail,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 
   // Pull audio once.
   const size_t kMaxOutputSize = static_cast<size_t>(10 * kSampleRateHz / 1000);
@@ -705,7 +722,9 @@
   for (size_t i = 0; i < 10; ++i) {
     rtp_header.sequenceNumber++;
     rtp_header.timestamp += kPayloadLengthSamples;
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
     EXPECT_EQ(i + 1, packet_buffer_->NumPacketsInBuffer());
   }
 
@@ -777,7 +796,8 @@
   header.extension.set_audio_level(AudioLevel(/*voice_activity=*/false, 12));
   header.numCSRCs = 1;
   header.arrOfCSRCs[0] = 123;
-  neteq_->InsertPacket(header, payload);
+  neteq_->InsertPacket(header, payload,
+                       /*receive_time=*/clock_.CurrentTime());
   AudioFrame frame;
   bool muted;
   neteq_->GetAudio(&frame, &muted);
@@ -875,7 +895,9 @@
   auto insert_packet = [&]() {
     rtp_header.sequenceNumber++;
     rtp_header.timestamp += kPayloadLengthSamples;
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
   };
   // Insert 10 packets.
   for (size_t i = 0; i < 10; ++i) {
@@ -959,7 +981,9 @@
   auto insert_packet = [&]() {
     rtp_header.sequenceNumber++;
     rtp_header.timestamp += kPayloadLengthSamples;
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
   };
   // Insert 10 packets.
   for (size_t i = 0; i < 10; ++i) {
@@ -1033,7 +1057,9 @@
     rtp_header.sequenceNumber++;
     rtp_header.timestamp += kPayloadLengthSamples;
     if (!lost)
-      EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+      EXPECT_EQ(NetEq::kOK,
+                neteq_->InsertPacket(rtp_header, payload,
+                                     /*receive_time=*/clock_.CurrentTime()));
   };
 
   // Insert and decode 10 packets.
@@ -1122,7 +1148,9 @@
     rtp_header.sequenceNumber += packets[i].sequence_number_delta;
     rtp_header.timestamp += packets[i].timestamp_delta;
     payload[0] = i;
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
 
     // Pointee(x) verifies that first byte of the payload equals x, this makes
     // it possible to verify that the correct payload is fed to Decode().
@@ -1220,7 +1248,9 @@
 
   // Insert one packet.
   payload[0] = kFirstPayloadValue;  // This will make Decode() fail.
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 
   // Insert another packet.
   payload[0] = kSecondPayloadValue;  // This will make Decode() successful.
@@ -1228,7 +1258,9 @@
   // The second timestamp needs to be at least 30 ms after the first to make
   // the second packet get decoded.
   rtp_header.timestamp += 3 * kPayloadLengthSamples;
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 
   AudioFrame output;
   bool muted;
@@ -1281,7 +1313,9 @@
   // Insert packets until the buffer flushes.
   for (size_t i = 0; i <= config_.max_packets_in_buffer; ++i) {
     EXPECT_EQ(i, packet_buffer_->NumPacketsInBuffer());
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
     rtp_header.timestamp += rtc::checked_cast<uint32_t>(kPayloadLengthSamples);
     ++rtp_header.sequenceNumber;
   }
@@ -1333,7 +1367,9 @@
                                           SdpAudioFormat("L16", 8000, 1)));
 
   // Insert one packet.
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 
   EXPECT_EQ(5u, neteq_->sync_buffer_for_test()->FutureLength());
 
@@ -1425,7 +1461,9 @@
   for (int i = 0; i < 20; ++i) {
     rtp_header.sequenceNumber += 1;
     rtp_header.timestamp += kFrameLengthSamples;
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
   }
 
   // Pull audio.
@@ -1550,7 +1588,9 @@
 
   EXPECT_TRUE(neteq_->RegisterPayloadType(kPayloadType,
                                           SdpAudioFormat("l16", 8000, 1)));
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
   AudioFrame output;
   bool muted;
   EXPECT_EQ(NetEq::kOK, neteq_->GetAudio(&output, &muted));
@@ -1572,7 +1612,9 @@
               Field(&NetEqController::PacketArrivedInfo::main_timestamp,
                     rtp_header.timestamp))));
 
-  EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+  EXPECT_EQ(NetEq::kOK,
+            neteq_->InsertPacket(rtp_header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()));
 }
 
 // When using a codec with 1000 channels, there should be no crashes.
@@ -1626,7 +1668,8 @@
       }));
 
   // Insert first packet.
-  neteq_->InsertPacket(rtp_header, payload);
+  neteq_->InsertPacket(rtp_header, payload,
+                       /*receive_time=*/clock_.CurrentTime());
 
   AudioFrame audio_frame;
   bool muted;
@@ -1655,12 +1698,16 @@
   header.payloadType = kCnPayloadType;
   uint8_t payload[320] = {0};
 
-  EXPECT_EQ(neteq_->InsertPacket(header, payload), NetEq::kOK);
+  EXPECT_EQ(neteq_->InsertPacket(header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()),
+            NetEq::kOK);
   EXPECT_EQ(neteq_->GetLifetimeStatistics().packets_discarded, 0u);
 
   header.payloadType = kSpeechPayloadType;
   header.timestamp += 160;
-  EXPECT_EQ(neteq_->InsertPacket(header, payload), NetEq::kOK);
+  EXPECT_EQ(neteq_->InsertPacket(header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()),
+            NetEq::kOK);
   // CN packet should be discarded, since it does not match the
   // new speech sample rate.
   EXPECT_EQ(neteq_->GetLifetimeStatistics().packets_discarded, 1u);
@@ -1688,12 +1735,16 @@
   header.timestamp = 1234;
   uint8_t payload[160] = {0};
 
-  EXPECT_EQ(neteq_->InsertPacket(header, payload), NetEq::kOK);
+  EXPECT_EQ(neteq_->InsertPacket(header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()),
+            NetEq::kOK);
   EXPECT_EQ(neteq_->GetLifetimeStatistics().packets_discarded, 0u);
 
   header.payloadType = kPcmaPayloadType;
   header.timestamp += 80;
-  EXPECT_EQ(neteq_->InsertPacket(header, payload), NetEq::kOK);
+  EXPECT_EQ(neteq_->InsertPacket(header, payload,
+                                 /*receive_time=*/clock_.CurrentTime()),
+            NetEq::kOK);
   // The previous packet should be discarded since the codec changed.
   EXPECT_EQ(neteq_->GetLifetimeStatistics().packets_discarded, 1u);
 
@@ -1780,7 +1831,9 @@
     rtp_header.ssrc = 15;
     const size_t kPayloadLengthBytes = 1;  // This can be arbitrary.
     uint8_t payload[kPayloadLengthBytes] = {0};
-    EXPECT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header, payload));
+    EXPECT_EQ(NetEq::kOK,
+              neteq_->InsertPacket(rtp_header, payload,
+                                   /*receive_time=*/clock_.CurrentTime()));
     sequence_number_++;
   }
 
diff --git a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
index da51698..69538d2 100644
--- a/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_network_stats_unittest.cc
@@ -238,7 +238,9 @@
             kPayloadType, frame_size_samples_, &rtp_header_);
         if (!Lost(next_send_time)) {
           static const uint8_t payload[kPayloadSizeByte] = {0};
-          ASSERT_EQ(NetEq::kOK, neteq_->InsertPacket(rtp_header_, payload));
+          ASSERT_EQ(NetEq::kOK,
+                    neteq_->InsertPacket(rtp_header_, payload,
+                                         Timestamp::Millis(next_send_time)));
         }
       }
       bool muted = true;
diff --git a/modules/audio_coding/neteq/neteq_stereo_unittest.cc b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
index 6fa56fd..d7bd794 100644
--- a/modules/audio_coding/neteq/neteq_stereo_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_stereo_unittest.cc
@@ -18,6 +18,7 @@
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/neteq/neteq.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "modules/audio_coding/neteq/default_neteq_factory.h"
 #include "modules/audio_coding/neteq/tools/input_audio_file.h"
@@ -109,7 +110,7 @@
     if (frame_size_samples_ * 2 != payload_size_bytes_) {
       return -1;
     }
-    int next_send_time = rtp_generator_mono_.GetRtpHeader(
+    int next_send_time_ms = rtp_generator_mono_.GetRtpHeader(
         kPayloadTypeMono, frame_size_samples_, &rtp_header_mono_);
     MakeMultiChannelInput();
     multi_payload_size_bytes_ = WebRtcPcm16b_Encode(
@@ -120,7 +121,7 @@
     }
     rtp_generator_.GetRtpHeader(kPayloadTypeMulti, frame_size_samples_,
                                 &rtp_header_);
-    return next_send_time;
+    return next_send_time_ms;
   }
 
   virtual void MakeMultiChannelInput() {
@@ -151,32 +152,35 @@
 
   void RunTest(int num_loops) {
     // Get next input packets (mono and multi-channel).
-    int next_send_time;
-    int next_arrival_time;
+    int next_send_time_ms;
+    int next_arrival_time_ms;
     do {
-      next_send_time = GetNewPackets();
-      ASSERT_NE(-1, next_send_time);
-      next_arrival_time = GetArrivalTime(next_send_time);
+      next_send_time_ms = GetNewPackets();
+      ASSERT_NE(-1, next_send_time_ms);
+      next_arrival_time_ms = GetArrivalTime(next_send_time_ms);
     } while (Lost());  // If lost, immediately read the next packet.
 
-    int time_now = 0;
+    int time_now_ms = 0;
     for (int k = 0; k < num_loops; ++k) {
-      while (time_now >= next_arrival_time) {
+      while (time_now_ms >= next_arrival_time_ms) {
         // Insert packet in mono instance.
         ASSERT_EQ(NetEq::kOK,
-                  neteq_mono_->InsertPacket(
-                      rtp_header_mono_, rtc::ArrayView<const uint8_t>(
-                                            encoded_, payload_size_bytes_)));
+                  neteq_mono_->InsertPacket(rtp_header_mono_,
+                                            rtc::ArrayView<const uint8_t>(
+                                                encoded_, payload_size_bytes_),
+                                            Timestamp::Millis(time_now_ms)));
         // Insert packet in multi-channel instance.
-        ASSERT_EQ(NetEq::kOK, neteq_->InsertPacket(
-                                  rtp_header_, rtc::ArrayView<const uint8_t>(
-                                                   encoded_multi_channel_,
-                                                   multi_payload_size_bytes_)));
+        ASSERT_EQ(NetEq::kOK,
+                  neteq_->InsertPacket(
+                      rtp_header_,
+                      rtc::ArrayView<const uint8_t>(encoded_multi_channel_,
+                                                    multi_payload_size_bytes_),
+                      Timestamp::Millis(time_now_ms)));
         // Get next input packets (mono and multi-channel).
         do {
-          next_send_time = GetNewPackets();
-          ASSERT_NE(-1, next_send_time);
-          next_arrival_time = GetArrivalTime(next_send_time);
+          next_send_time_ms = GetNewPackets();
+          ASSERT_NE(-1, next_send_time_ms);
+          next_arrival_time_ms = GetArrivalTime(next_send_time_ms);
         } while (Lost());  // If lost, immediately read the next packet.
       }
       // Get audio from mono instance.
@@ -197,7 +201,7 @@
       // Compare mono and multi-channel.
       ASSERT_NO_FATAL_FAILURE(VerifyOutput(output_size_samples_));
 
-      time_now += kTimeStepMs;
+      time_now_ms += kTimeStepMs;
       clock_.AdvanceTimeMilliseconds(kTimeStepMs);
     }
   }
diff --git a/modules/audio_coding/neteq/neteq_unittest.cc b/modules/audio_coding/neteq/neteq_unittest.cc
index 7104b7a..8ebed6f 100644
--- a/modules/audio_coding/neteq/neteq_unittest.cc
+++ b/modules/audio_coding/neteq/neteq_unittest.cc
@@ -132,7 +132,7 @@
     rtp_info.ssrc = 0x1234;     // Just an arbitrary SSRC.
     rtp_info.payloadType = 94;  // PCM16b WB codec.
     rtp_info.markerBit = 0;
-    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
   }
   // Pull out all data.
   for (size_t i = 0; i < num_frames; ++i) {
@@ -237,7 +237,8 @@
   RTPHeader rtp_info;
   PopulateRtpInfo(0, 0, &rtp_info);
   rtp_info.payloadType = 1;  // Not registered as a decoder.
-  EXPECT_EQ(NetEq::kFail, neteq_->InsertPacket(rtp_info, payload));
+  EXPECT_EQ(NetEq::kFail,
+            neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
 }
 
 #if defined(WEBRTC_CODEC_ISAC) || defined(WEBRTC_CODEC_ISACFX)
@@ -252,7 +253,7 @@
   RTPHeader rtp_info;
   PopulateRtpInfo(0, 0, &rtp_info);
   rtp_info.payloadType = 103;  // iSAC, but the payload is invalid.
-  EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+  EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
   // Set all of `out_data_` to 1, and verify that it was set to 0 by the call
   // to GetAudio.
   int16_t* out_frame_data = out_frame_.mutable_data();
@@ -340,8 +341,10 @@
           WebRtcPcm16b_Encode(block.data(), block.size(), payload);
       ASSERT_EQ(enc_len_bytes, expected_samples_per_channel * 2);
 
-      ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
-                                                      payload, enc_len_bytes)));
+      ASSERT_EQ(0, neteq_->InsertPacket(
+                       rtp_info,
+                       rtc::ArrayView<const uint8_t>(payload, enc_len_bytes),
+                       clock_.CurrentTime()));
       output.Reset();
       ASSERT_EQ(0, neteq_->GetAudio(&output, &muted));
       ASSERT_EQ(1u, output.num_channels_);
@@ -445,7 +448,7 @@
   bool muted;
   for (int i = 0; i < 3; ++i) {
     PopulateRtpInfo(seq_no, timestamp, &rtp_info);
-    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
     ++seq_no;
     timestamp += kSamples;
 
@@ -462,8 +465,10 @@
   size_t payload_len;
   PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
   // This is the first time this CNG packet is inserted.
-  ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
-                                                  payload, payload_len)));
+  ASSERT_EQ(0,
+            neteq_->InsertPacket(
+                rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len),
+                clock_.CurrentTime()));
 
   // Pull audio once and make sure CNG is played.
   ASSERT_EQ(0, neteq_->GetAudio(&out_frame_, &muted));
@@ -476,8 +481,10 @@
 
   // Insert the same CNG packet again. Note that at this point it is old, since
   // we have already decoded the first copy of it.
-  ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
-                                                  payload, payload_len)));
+  ASSERT_EQ(0,
+            neteq_->InsertPacket(
+                rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len),
+                clock_.CurrentTime()));
 
   // Pull audio until we have played `kCngPeriodMs` of CNG. Start at 10 ms since
   // we have already pulled out CNG once.
@@ -497,7 +504,7 @@
   // Insert speech again.
   for (int i = 0; i < 4; ++i) {
     PopulateRtpInfo(seq_no, timestamp, &rtp_info);
-    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
     ++seq_no;
     timestamp += kSamples;
   }
@@ -529,7 +536,8 @@
   PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
   ASSERT_EQ(NetEq::kOK,
             neteq_->InsertPacket(
-                rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len)));
+                rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len),
+                clock_.CurrentTime()));
   ++seq_no;
   timestamp += kCngPeriodSamples;
 
@@ -545,7 +553,7 @@
   do {
     ASSERT_LT(timeout_counter++, 20) << "Test timed out";
     PopulateRtpInfo(seq_no, timestamp, &rtp_info);
-    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+    ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
     ++seq_no;
     timestamp += kSamples;
 
@@ -571,7 +579,7 @@
     uint8_t payload[kPayloadBytes] = {0};
     RTPHeader rtp_info;
     PopulateRtpInfo(0, rtp_timestamp, &rtp_info);
-    EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+    EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
   }
 
   void InsertCngPacket(uint32_t rtp_timestamp) {
@@ -580,8 +588,9 @@
     size_t payload_len;
     PopulateCng(0, rtp_timestamp, &rtp_info, payload, &payload_len);
     EXPECT_EQ(NetEq::kOK,
-              neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
-                                                 payload, payload_len)));
+              neteq_->InsertPacket(
+                  rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len),
+                  clock_.CurrentTime()));
   }
 
   bool GetAudioReturnMuted() {
@@ -791,8 +800,8 @@
   uint8_t payload[kPayloadBytes] = {0};
   RTPHeader rtp_info;
   PopulateRtpInfo(0, 0, &rtp_info);
-  EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
-  EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload));
+  EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
+  EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
 
   AudioFrame out_frame1, out_frame2;
   bool muted;
@@ -815,8 +824,9 @@
   // packet.
   for (int i = 0; i < 5; ++i) {
     PopulateRtpInfo(0, kSamples * 1000 + kSamples * i, &rtp_info);
-    EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
-    EXPECT_EQ(0, neteq2_->InsertPacket(rtp_info, payload));
+    EXPECT_EQ(0, neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
+    EXPECT_EQ(0,
+              neteq2_->InsertPacket(rtp_info, payload, clock_.CurrentTime()));
   }
 
   int counter = 0;
@@ -854,7 +864,7 @@
     for (int j = 0; j < 10; j++) {
       rtp_info.sequenceNumber = seq_no++;
       rtp_info.timestamp = rtp_info.sequenceNumber * kSamples;
-      neteq_->InsertPacket(rtp_info, payload);
+      neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime());
       neteq_->GetAudio(&out_frame_, &muted);
     }
 
@@ -894,7 +904,7 @@
     if (packets_sent < kNumPackets) {
       rtp_info.sequenceNumber = packets_sent++;
       rtp_info.timestamp = rtp_info.sequenceNumber * kSamples;
-      neteq_->InsertPacket(rtp_info, payload);
+      neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime());
     }
 
     // Get packet.
@@ -950,17 +960,17 @@
   const uint8_t payload[kPayloadBytes] = {0};
 
   int expected_target_delay = neteq_->TargetDelayMs() * kSamples;
-  neteq_->InsertPacket(rtp_info, payload);
+  neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime());
 
   bool muted;
   neteq_->GetAudio(&out_frame_, &muted);
 
   rtp_info.sequenceNumber += 1;
   rtp_info.timestamp += kSamples;
-  neteq_->InsertPacket(rtp_info, payload);
+  neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime());
   rtp_info.sequenceNumber += 1;
   rtp_info.timestamp += kSamples;
-  neteq_->InsertPacket(rtp_info, payload);
+  neteq_->InsertPacket(rtp_info, payload, clock_.CurrentTime());
 
   expected_target_delay += neteq_->TargetDelayMs() * 2 * kSamples;
   // We have two packets in the buffer and kAccelerate operation will
diff --git a/modules/audio_coding/neteq/test/neteq_decoding_test.cc b/modules/audio_coding/neteq/test/neteq_decoding_test.cc
index e626d09..1767aa6 100644
--- a/modules/audio_coding/neteq/test/neteq_decoding_test.cc
+++ b/modules/audio_coding/neteq/test/neteq_decoding_test.cc
@@ -13,6 +13,7 @@
 #include "absl/strings/string_view.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/rtp_headers.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/neteq/default_neteq_factory.h"
 #include "modules/audio_coding/neteq/test/result_sink.h"
 #include "rtc_base/strings/string_builder.h"
@@ -106,11 +107,11 @@
       // Ignore payload type 104 (iSAC-swb) if ISAC is not supported.
       if (packet_->header().payloadType != 104)
 #endif
-        ASSERT_EQ(
-            0, neteq_->InsertPacket(
-                   packet_->header(),
-                   rtc::ArrayView<const uint8_t>(
-                       packet_->payload(), packet_->payload_length_bytes())));
+        ASSERT_EQ(0, neteq_->InsertPacket(packet_->header(),
+                                          rtc::ArrayView<const uint8_t>(
+                                              packet_->payload(),
+                                              packet_->payload_length_bytes()),
+                                          clock_.CurrentTime()));
     }
     // Get next packet.
     packet_ = rtp_source_->NextPacket();
@@ -239,7 +240,8 @@
       PopulateRtpInfo(seq_no, timestamp, &rtp_info);
       if (drop_seq_numbers.find(seq_no) == drop_seq_numbers.end()) {
         // This sequence number was not in the set to drop. Insert it.
-        ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+        ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload,
+                                          Timestamp::Millis(t_ms)));
       }
       NetEqNetworkStatistics network_stats;
       ASSERT_EQ(0, neteq_->NetworkStatistics(&network_stats));
@@ -298,7 +300,8 @@
       uint8_t payload[kPayloadBytes] = {0};
       RTPHeader rtp_info;
       PopulateRtpInfo(seq_no, timestamp, &rtp_info);
-      ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+      ASSERT_EQ(
+          0, neteq_->InsertPacket(rtp_info, payload, Timestamp::Millis(t_ms)));
       ++seq_no;
       timestamp += kSamples;
       next_input_time_ms += static_cast<double>(kFrameSizeMs) * drift_factor;
@@ -325,8 +328,10 @@
       size_t payload_len;
       RTPHeader rtp_info;
       PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
-      ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
-                                                      payload, payload_len)));
+      ASSERT_EQ(
+          0, neteq_->InsertPacket(
+                 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len),
+                 Timestamp::Millis(t_ms)));
       ++seq_no;
       timestamp += kCngPeriodSamples;
       next_input_time_ms += static_cast<double>(kCngPeriodMs) * drift_factor;
@@ -367,8 +372,10 @@
       size_t payload_len;
       RTPHeader rtp_info;
       PopulateCng(seq_no, timestamp, &rtp_info, payload, &payload_len);
-      ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, rtc::ArrayView<const uint8_t>(
-                                                      payload, payload_len)));
+      ASSERT_EQ(
+          0, neteq_->InsertPacket(
+                 rtp_info, rtc::ArrayView<const uint8_t>(payload, payload_len),
+                 Timestamp::Millis(t_ms)));
       ++seq_no;
       timestamp += kCngPeriodSamples;
       next_input_time_ms += kCngPeriodMs * drift_factor;
@@ -384,7 +391,8 @@
       uint8_t payload[kPayloadBytes] = {0};
       RTPHeader rtp_info;
       PopulateRtpInfo(seq_no, timestamp, &rtp_info);
-      ASSERT_EQ(0, neteq_->InsertPacket(rtp_info, payload));
+      ASSERT_EQ(
+          0, neteq_->InsertPacket(rtp_info, payload, Timestamp::Millis(t_ms)));
       ++seq_no;
       timestamp += kSamples;
       next_input_time_ms += kFrameSizeMs * drift_factor;
diff --git a/modules/audio_coding/neteq/tools/neteq_performance_test.cc b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
index ccaa87b..a560b0d 100644
--- a/modules/audio_coding/neteq/tools/neteq_performance_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_performance_test.cc
@@ -87,7 +87,8 @@
       }
       if (!lost) {
         // Insert packet.
-        int error = neteq->InsertPacket(rtp_header, input_payload);
+        int error = neteq->InsertPacket(rtp_header, input_payload,
+                                        Timestamp::Millis(time_now_ms));
         if (error != NetEq::kOK)
           return -1;
       }
diff --git a/modules/audio_coding/neteq/tools/neteq_quality_test.cc b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
index 18e6091..77a0542 100644
--- a/modules/audio_coding/neteq/tools/neteq_quality_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_quality_test.cc
@@ -16,6 +16,7 @@
 
 #include "absl/flags/flag.h"
 #include "absl/strings/string_view.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/neteq/default_neteq_factory.h"
 #include "modules/audio_coding/neteq/tools/neteq_quality_test.h"
 #include "modules/audio_coding/neteq/tools/output_audio_file.h"
@@ -415,7 +416,8 @@
     if (!PacketLost()) {
       int ret = neteq_->InsertPacket(
           rtp_header_,
-          rtc::ArrayView<const uint8_t>(payload_.data(), payload_size_bytes_));
+          rtc::ArrayView<const uint8_t>(payload_.data(), payload_size_bytes_),
+          Timestamp::Millis(packet_input_time_ms));
       if (ret != NetEq::kOK)
         return -1;
       Log() << "was sent.";
diff --git a/modules/audio_coding/neteq/tools/neteq_test.cc b/modules/audio_coding/neteq/tools/neteq_test.cc
index d47671f..7755b4e 100644
--- a/modules/audio_coding/neteq/tools/neteq_test.cc
+++ b/modules/audio_coding/neteq/tools/neteq_test.cc
@@ -13,6 +13,7 @@
 #include <iomanip>
 #include <iostream>
 
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/neteq/default_neteq_factory.h"
 #include "modules/rtp_rtcp/source/byte_io.h"
 #include "system_wrappers/include/clock.h"
@@ -114,7 +115,8 @@
       if (payload_data_length != 0) {
         int error = neteq_->InsertPacket(
             packet_data->header,
-            rtc::ArrayView<const uint8_t>(packet_data->payload));
+            rtc::ArrayView<const uint8_t>(packet_data->payload),
+            Timestamp::Millis(time_now_ms));
         if (error != NetEq::kOK && callbacks_.error_callback) {
           callbacks_.error_callback->OnInsertPacketError(*packet_data);
         }
diff --git a/modules/audio_coding/test/Channel.cc b/modules/audio_coding/test/Channel.cc
index 8f634db..f09b357 100644
--- a/modules/audio_coding/test/Channel.cc
+++ b/modules/audio_coding/test/Channel.cc
@@ -83,7 +83,8 @@
   }
 
   status = _receiverACM->InsertPacket(
-      rtp_header, rtc::ArrayView<const uint8_t>(_payloadData, payloadDataSize));
+      rtp_header, rtc::ArrayView<const uint8_t>(_payloadData, payloadDataSize),
+      /*receive_time=*/Timestamp::MinusInfinity());
 
   return status;
 }
diff --git a/modules/audio_coding/test/EncodeDecodeTest.cc b/modules/audio_coding/test/EncodeDecodeTest.cc
index cab3645..ef997f1 100644
--- a/modules/audio_coding/test/EncodeDecodeTest.cc
+++ b/modules/audio_coding/test/EncodeDecodeTest.cc
@@ -170,8 +170,10 @@
     }
 
     EXPECT_EQ(0, _acm_receiver->InsertPacket(
-                     _rtpHeader, rtc::ArrayView<const uint8_t>(
-                                     _incomingPayload, _realPayloadSizeBytes)));
+                     _rtpHeader,
+                     rtc::ArrayView<const uint8_t>(_incomingPayload,
+                                                   _realPayloadSizeBytes),
+                     /*receive_time=*/Timestamp::Millis(_nextTime)));
     _realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload,
                                              _payloadSizeBytes, &_nextTime);
     if (_realPayloadSizeBytes == 0 && _rtpStream->EndOfFile()) {
diff --git a/modules/audio_coding/test/PacketLossTest.cc b/modules/audio_coding/test/PacketLossTest.cc
index c4f6656..6b52000 100644
--- a/modules/audio_coding/test/PacketLossTest.cc
+++ b/modules/audio_coding/test/PacketLossTest.cc
@@ -14,6 +14,7 @@
 
 #include "absl/strings/string_view.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "api/units/timestamp.h"
 #include "rtc_base/strings/string_builder.h"
 #include "test/gtest.h"
 #include "test/testsupport/file_utils.h"
@@ -58,9 +59,10 @@
     }
 
     if (!PacketLost()) {
-      _acm_receiver->InsertPacket(
-          _rtpHeader, rtc::ArrayView<const uint8_t>(_incomingPayload,
-                                                    _realPayloadSizeBytes));
+      _acm_receiver->InsertPacket(_rtpHeader,
+                                  rtc::ArrayView<const uint8_t>(
+                                      _incomingPayload, _realPayloadSizeBytes),
+                                  Timestamp::Millis(_nextTime));
     }
     packet_counter_++;
     _realPayloadSizeBytes = _rtpStream->Read(&_rtpHeader, _incomingPayload,
diff --git a/modules/audio_coding/test/TestAllCodecs.cc b/modules/audio_coding/test/TestAllCodecs.cc
index dd51760..1a56fbc 100644
--- a/modules/audio_coding/test/TestAllCodecs.cc
+++ b/modules/audio_coding/test/TestAllCodecs.cc
@@ -84,7 +84,8 @@
   memcpy(payload_data_, payload_data, payload_size);
 
   status = receiver_acm_->InsertPacket(
-      rtp_header, rtc::ArrayView<const uint8_t>(payload_data_, payload_size));
+      rtp_header, rtc::ArrayView<const uint8_t>(payload_data_, payload_size),
+      /*receive_time=*/Timestamp::MinusInfinity());
 
   payload_size_ = payload_size;
   timestamp_diff_ = timestamp - last_in_timestamp_;
diff --git a/modules/audio_coding/test/TestStereo.cc b/modules/audio_coding/test/TestStereo.cc
index 1e65e4a..4573a7e 100644
--- a/modules/audio_coding/test/TestStereo.cc
+++ b/modules/audio_coding/test/TestStereo.cc
@@ -61,7 +61,8 @@
 
   if (lost_packet_ == false) {
     status = receiver_acm_->InsertPacket(
-        rtp_header, rtc::ArrayView<const uint8_t>(payload_data, payload_size));
+        rtp_header, rtc::ArrayView<const uint8_t>(payload_data, payload_size),
+        /*receive_time=*/Timestamp::MinusInfinity());
 
     if (frame_type != AudioFrameType::kAudioFrameCN) {
       payload_size_ = static_cast<int>(payload_size);
diff --git a/modules/audio_coding/test/target_delay_unittest.cc b/modules/audio_coding/test/target_delay_unittest.cc
index 2a71627..cd8fb34 100644
--- a/modules/audio_coding/test/target_delay_unittest.cc
+++ b/modules/audio_coding/test/target_delay_unittest.cc
@@ -13,6 +13,7 @@
 #include "api/audio/audio_frame.h"
 #include "api/audio_codecs/builtin_audio_decoder_factory.h"
 #include "api/rtp_headers.h"
+#include "api/units/timestamp.h"
 #include "modules/audio_coding/acm2/acm_receiver.h"
 #include "modules/audio_coding/codecs/pcm16b/pcm16b.h"
 #include "modules/audio_coding/include/audio_coding_module.h"
@@ -85,7 +86,8 @@
     rtp_header_.sequenceNumber++;
     ASSERT_EQ(0, receiver_.InsertPacket(rtp_header_,
                                         rtc::ArrayView<const uint8_t>(
-                                            payload_, kFrameSizeSamples * 2)));
+                                            payload_, kFrameSizeSamples * 2),
+                                        Timestamp::MinusInfinity()));
   }
 
   // Pull audio equivalent to the amount of audio in one RTP packet.