measure decode time in TimeDelta instead of ms

increasing precision since summing up rounded values leads to
a rounding error, in particular for small frames which take very
little time to decode.

BUG=webrtc:12526,webrtc:13756

Change-Id: I647c702808856a002c746ed9f115aa9bcaddc1f3
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/262810
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Philipp Hancke <philipp.hancke@googlemail.com>
Cr-Commit-Position: refs/heads/main@{#37249}
diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h
index fb06d52..714d8e4 100644
--- a/call/video_receive_stream.h
+++ b/call/video_receive_stream.h
@@ -105,7 +105,7 @@
     uint32_t frames_dropped = 0;
     uint32_t frames_decoded = 0;
     // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totaldecodetime
-    uint64_t total_decode_time_ms = 0;
+    webrtc::TimeDelta total_decode_time = webrtc::TimeDelta::Millis(0);
     // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totalprocessingdelay
     webrtc::TimeDelta total_processing_delay = webrtc::TimeDelta::Millis(0);
     // TODO(bugs.webrtc.org/13986): standardize
diff --git a/media/base/media_channel.h b/media/base/media_channel.h
index 22673ce..bcc095e 100644
--- a/media/base/media_channel.h
+++ b/media/base/media_channel.h
@@ -620,7 +620,7 @@
   uint32_t frames_rendered = 0;
   absl::optional<uint64_t> qp_sum;
   // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totaldecodetime
-  uint64_t total_decode_time_ms = 0;
+  webrtc::TimeDelta total_decode_time = webrtc::TimeDelta::Millis(0);
   // https://w3c.github.io/webrtc-stats/#dom-rtcinboundrtpstreamstats-totalprocessingdelay
   webrtc::TimeDelta total_processing_delay = webrtc::TimeDelta::Millis(0);
   webrtc::TimeDelta total_assembly_time = webrtc::TimeDelta::Millis(0);
diff --git a/media/engine/webrtc_video_engine.cc b/media/engine/webrtc_video_engine.cc
index 278f87b..0ce0f0c 100644
--- a/media/engine/webrtc_video_engine.cc
+++ b/media/engine/webrtc_video_engine.cc
@@ -3208,7 +3208,7 @@
   info.key_frames_decoded = stats.frame_counts.key_frames;
   info.frames_rendered = stats.frames_rendered;
   info.qp_sum = stats.qp_sum;
-  info.total_decode_time_ms = stats.total_decode_time_ms;
+  info.total_decode_time = stats.total_decode_time;
   info.total_processing_delay = stats.total_processing_delay;
   info.total_assembly_time = stats.total_assembly_time;
   info.frames_assembled_from_multiple_packets =
diff --git a/media/engine/webrtc_video_engine_unittest.cc b/media/engine/webrtc_video_engine_unittest.cc
index b93b4f7..12c5615 100644
--- a/media/engine/webrtc_video_engine_unittest.cc
+++ b/media/engine/webrtc_video_engine_unittest.cc
@@ -6152,7 +6152,7 @@
   stats.frames_rendered = 13;
   stats.frames_decoded = 14;
   stats.qp_sum = 15;
-  stats.total_decode_time_ms = 16;
+  stats.total_decode_time = webrtc::TimeDelta::Millis(16);
   stats.total_assembly_time = webrtc::TimeDelta::Millis(4);
   stats.frames_assembled_from_multiple_packets = 2;
   stream->SetStats(stats);
@@ -6182,7 +6182,7 @@
   EXPECT_EQ(rtc::checked_cast<unsigned int>(stats.frame_counts.key_frames),
             info.receivers[0].key_frames_decoded);
   EXPECT_EQ(stats.qp_sum, info.receivers[0].qp_sum);
-  EXPECT_EQ(stats.total_decode_time_ms, info.receivers[0].total_decode_time_ms);
+  EXPECT_EQ(stats.total_decode_time, info.receivers[0].total_decode_time);
   EXPECT_EQ(stats.total_assembly_time, info.receivers[0].total_assembly_time);
   EXPECT_EQ(stats.frames_assembled_from_multiple_packets,
             info.receivers[0].frames_assembled_from_multiple_packets);
diff --git a/modules/video_coding/generic_decoder.cc b/modules/video_coding/generic_decoder.cc
index 68eb1fc..5cb20f9 100644
--- a/modules/video_coding/generic_decoder.cc
+++ b/modules/video_coding/generic_decoder.cc
@@ -174,7 +174,7 @@
 
   decodedImage.set_timestamp_us(frameInfo->renderTimeMs *
                                 rtc::kNumMicrosecsPerMillisec);
-  _receiveCallback->FrameToRender(decodedImage, qp, decode_time.ms(),
+  _receiveCallback->FrameToRender(decodedImage, qp, decode_time,
                                   frameInfo->content_type);
 }
 
diff --git a/modules/video_coding/generic_decoder_unittest.cc b/modules/video_coding/generic_decoder_unittest.cc
index 65e8dba..811c296 100644
--- a/modules/video_coding/generic_decoder_unittest.cc
+++ b/modules/video_coding/generic_decoder_unittest.cc
@@ -33,7 +33,7 @@
  public:
   int32_t FrameToRender(VideoFrame& videoFrame,  // NOLINT
                         absl::optional<uint8_t> qp,
-                        int32_t decode_time_ms,
+                        TimeDelta decode_time,
                         VideoContentType content_type) override {
     {
       MutexLock lock(&lock_);
diff --git a/modules/video_coding/include/video_coding_defines.h b/modules/video_coding/include/video_coding_defines.h
index 2f1d8c8..8b93b07 100644
--- a/modules/video_coding/include/video_coding_defines.h
+++ b/modules/video_coding/include/video_coding_defines.h
@@ -51,7 +51,7 @@
  public:
   virtual int32_t FrameToRender(VideoFrame& videoFrame,  // NOLINT
                                 absl::optional<uint8_t> qp,
-                                int32_t decode_time_ms,
+                                TimeDelta decode_time,
                                 VideoContentType content_type) = 0;
 
   virtual void OnDroppedFrames(uint32_t frames_dropped);
diff --git a/modules/video_coding/video_receiver_unittest.cc b/modules/video_coding/video_receiver_unittest.cc
index 4fc3794..f2ebce8 100644
--- a/modules/video_coding/video_receiver_unittest.cc
+++ b/modules/video_coding/video_receiver_unittest.cc
@@ -38,10 +38,11 @@
   MockVCMReceiveCallback() {}
   virtual ~MockVCMReceiveCallback() {}
 
-  MOCK_METHOD(int32_t,
-              FrameToRender,
-              (VideoFrame&, absl::optional<uint8_t>, int32_t, VideoContentType),
-              (override));
+  MOCK_METHOD(
+      int32_t,
+      FrameToRender,
+      (VideoFrame&, absl::optional<uint8_t>, TimeDelta, VideoContentType),
+      (override));
   MOCK_METHOD(void, OnIncomingPayloadType, (int), (override));
   MOCK_METHOD(void, OnDecoderImplementationName, (const char*), (override));
 };
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
index 04ea8b2..7f7218e 100644
--- a/pc/rtc_stats_collector.cc
+++ b/pc/rtc_stats_collector.cc
@@ -556,7 +556,7 @@
   if (video_receiver_info.qp_sum)
     inbound_video->qp_sum = *video_receiver_info.qp_sum;
   inbound_video->total_decode_time =
-      static_cast<double>(video_receiver_info.total_decode_time_ms) /
+      static_cast<double>(video_receiver_info.total_decode_time.ms()) /
       rtc::kNumMillisecsPerSec;
   inbound_video->total_processing_delay =
       static_cast<double>(video_receiver_info.total_processing_delay.ms()) /
diff --git a/pc/rtc_stats_collector_unittest.cc b/pc/rtc_stats_collector_unittest.cc
index c008c1b..8a10a7d 100644
--- a/pc/rtc_stats_collector_unittest.cc
+++ b/pc/rtc_stats_collector_unittest.cc
@@ -2168,7 +2168,8 @@
   video_media_info.receivers[0].key_frames_decoded = 3;
   video_media_info.receivers[0].frames_dropped = 13;
   video_media_info.receivers[0].qp_sum = absl::nullopt;
-  video_media_info.receivers[0].total_decode_time_ms = 9000;
+  video_media_info.receivers[0].total_decode_time =
+      webrtc::TimeDelta::Seconds(9);
   video_media_info.receivers[0].total_processing_delay =
       webrtc::TimeDelta::Millis(600);
   video_media_info.receivers[0].total_assembly_time =
diff --git a/video/receive_statistics_proxy2.cc b/video/receive_statistics_proxy2.cc
index 0f816bb..286ef62 100644
--- a/video/receive_statistics_proxy2.cc
+++ b/video/receive_statistics_proxy2.cc
@@ -828,7 +828,7 @@
 
 void ReceiveStatisticsProxy::OnDecodedFrame(const VideoFrame& frame,
                                             absl::optional<uint8_t> qp,
-                                            int32_t decode_time_ms,
+                                            TimeDelta decode_time,
                                             VideoContentType content_type) {
   webrtc::TimeDelta processing_delay = webrtc::TimeDelta::Millis(0);
   webrtc::Timestamp current_time = clock_->CurrentTime();
@@ -853,17 +853,17 @@
   // "com.apple.coremedia.decompressionsession.clientcallback"
   VideoFrameMetaData meta(frame, current_time);
   worker_thread_->PostTask(
-      ToQueuedTask(task_safety_, [meta, qp, decode_time_ms, processing_delay,
+      ToQueuedTask(task_safety_, [meta, qp, decode_time, processing_delay,
                                   assembly_time, content_type, this]() {
-        OnDecodedFrame(meta, qp, decode_time_ms, processing_delay,
-                       assembly_time, content_type);
+        OnDecodedFrame(meta, qp, decode_time, processing_delay, assembly_time,
+                       content_type);
       }));
 }
 
 void ReceiveStatisticsProxy::OnDecodedFrame(
     const VideoFrameMetaData& frame_meta,
     absl::optional<uint8_t> qp,
-    int32_t decode_time_ms,
+    TimeDelta decode_time,
     webrtc::TimeDelta processing_delay,
     webrtc::TimeDelta assembly_time,
     VideoContentType content_type) {
@@ -903,9 +903,9 @@
         << "QP sum was already set and no QP was given for a frame.";
     stats_.qp_sum.reset();
   }
-  decode_time_counter_.Add(decode_time_ms);
-  stats_.decode_ms = decode_time_ms;
-  stats_.total_decode_time_ms += decode_time_ms;
+  decode_time_counter_.Add(decode_time.ms());
+  stats_.decode_ms = decode_time.ms();
+  stats_.total_decode_time += decode_time;
   stats_.total_processing_delay += processing_delay;
   stats_.total_assembly_time += assembly_time;
   if (!assembly_time.IsZero()) {
@@ -913,7 +913,7 @@
   }
   if (enable_decode_time_histograms_) {
     UpdateDecodeTimeHistograms(frame_meta.width, frame_meta.height,
-                               decode_time_ms);
+                               decode_time.ms());
   }
 
   last_content_type_ = content_type;
diff --git a/video/receive_statistics_proxy2.h b/video/receive_statistics_proxy2.h
index 7470768..657920f 100644
--- a/video/receive_statistics_proxy2.h
+++ b/video/receive_statistics_proxy2.h
@@ -59,7 +59,7 @@
 
   void OnDecodedFrame(const VideoFrame& frame,
                       absl::optional<uint8_t> qp,
-                      int32_t decode_time_ms,
+                      webrtc::TimeDelta decode_time,
                       VideoContentType content_type);
 
   // Called asyncronously on the worker thread as a result of a call to the
@@ -67,7 +67,7 @@
   // the actual decoding happens.
   void OnDecodedFrame(const VideoFrameMetaData& frame_meta,
                       absl::optional<uint8_t> qp,
-                      int32_t decode_time_ms,
+                      webrtc::TimeDelta decode_time,
                       webrtc::TimeDelta processing_delay,
                       webrtc::TimeDelta assembly_time,
                       VideoContentType content_type);
diff --git a/video/receive_statistics_proxy2_unittest.cc b/video/receive_statistics_proxy2_unittest.cc
index f38f9cf..afcba15 100644
--- a/video/receive_statistics_proxy2_unittest.cc
+++ b/video/receive_statistics_proxy2_unittest.cc
@@ -113,7 +113,8 @@
   EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
   for (uint32_t i = 1; i <= 3; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0),
                                       VideoContentType::UNSPECIFIED);
     EXPECT_EQ(i, FlushAndGetStats().frames_decoded);
   }
@@ -124,7 +125,8 @@
   const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
   for (int i = 0; i < kRequiredSamples; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0),
                                       VideoContentType::UNSPECIFIED);
     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
   }
@@ -140,7 +142,8 @@
   const int kRequiredSamples = metrics::kMinRunTimeInSeconds * kFps;
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
   for (int i = 0; i < kRequiredSamples - 1; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0),
                                       VideoContentType::UNSPECIFIED);
     fake_clock_.AdvanceTimeMilliseconds(1000 / kFps);
   }
@@ -153,28 +156,29 @@
        OnDecodedFrameWithQpDoesNotResetFramesDecodedOrTotalDecodeTime) {
   EXPECT_EQ(0u, statistics_proxy_->GetStats().frames_decoded);
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  unsigned int expected_total_decode_time_ms = 0;
+  TimeDelta expected_total_decode_time = TimeDelta::Millis(0);
   unsigned int expected_frames_decoded = 0;
   for (uint32_t i = 1; i <= 3; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(1),
                                       VideoContentType::UNSPECIFIED);
-    expected_total_decode_time_ms += 1;
+    expected_total_decode_time += TimeDelta::Millis(1);
     ++expected_frames_decoded;
     loop_.Flush();
     EXPECT_EQ(expected_frames_decoded,
               statistics_proxy_->GetStats().frames_decoded);
-    EXPECT_EQ(expected_total_decode_time_ms,
-              statistics_proxy_->GetStats().total_decode_time_ms);
+    EXPECT_EQ(expected_total_decode_time,
+              statistics_proxy_->GetStats().total_decode_time);
   }
-  statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
+  statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
                                     VideoContentType::UNSPECIFIED);
   ++expected_frames_decoded;
-  expected_total_decode_time_ms += 3;
+  expected_total_decode_time += TimeDelta::Millis(3);
   loop_.Flush();
   EXPECT_EQ(expected_frames_decoded,
             statistics_proxy_->GetStats().frames_decoded);
-  EXPECT_EQ(expected_total_decode_time_ms,
-            statistics_proxy_->GetStats().total_decode_time_ms);
+  EXPECT_EQ(expected_total_decode_time,
+            statistics_proxy_->GetStats().total_decode_time);
 }
 
 TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesProcessingDelay) {
@@ -191,7 +195,8 @@
   frame.set_packet_infos(RtpPacketInfos(packet_infos));
   for (int i = 1; i <= 3; ++i) {
     fake_clock_.AdvanceTime(kProcessingDelay);
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(1),
                                       VideoContentType::UNSPECIFIED);
     expected_total_processing_delay += i * kProcessingDelay;
     ++expected_frames_decoded;
@@ -202,7 +207,7 @@
               statistics_proxy_->GetStats().total_processing_delay);
   }
   fake_clock_.AdvanceTime(kProcessingDelay);
-  statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
+  statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
                                     VideoContentType::UNSPECIFIED);
   ++expected_frames_decoded;
   expected_total_processing_delay += 4 * kProcessingDelay;
@@ -226,7 +231,7 @@
   RtpPacketInfos::vector_type single_packet_frame = {
       RtpPacketInfo({}, {}, {}, {}, {}, Now())};
   frame.set_packet_infos(RtpPacketInfos(single_packet_frame));
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 1,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(1),
                                     VideoContentType::UNSPECIFIED);
   ++expected_frames_decoded;
   loop_.Flush();
@@ -243,7 +248,7 @@
       RtpPacketInfo({}, {}, {}, {}, {}, Now() + 2 * kAssemblyTime),
   };
   frame.set_packet_infos(RtpPacketInfos(ordered_frame));
-  statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
+  statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
                                     VideoContentType::UNSPECIFIED);
   ++expected_frames_decoded;
   ++expected_frames_assembled_from_multiple_packets;
@@ -264,7 +269,7 @@
       RtpPacketInfo({}, {}, {}, {}, {}, Now() + kAssemblyTime),
   };
   frame.set_packet_infos(RtpPacketInfos(unordered_frame));
-  statistics_proxy_->OnDecodedFrame(frame, 1u, 3,
+  statistics_proxy_->OnDecodedFrame(frame, 1u, TimeDelta::Millis(3),
                                     VideoContentType::UNSPECIFIED);
   ++expected_frames_decoded;
   ++expected_frames_assembled_from_multiple_packets;
@@ -282,10 +287,10 @@
 TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesQpSum) {
   EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
+  statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
-  statistics_proxy_->OnDecodedFrame(frame, 127u, 0,
+  statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(130u, FlushAndGetStats().qp_sum);
 }
@@ -293,12 +298,12 @@
 TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameIncreasesTotalDecodeTime) {
   EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, 3u, 4,
+  statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(4),
                                     VideoContentType::UNSPECIFIED);
-  EXPECT_EQ(4u, FlushAndGetStats().total_decode_time_ms);
-  statistics_proxy_->OnDecodedFrame(frame, 127u, 7,
+  EXPECT_EQ(4u, FlushAndGetStats().total_decode_time.ms());
+  statistics_proxy_->OnDecodedFrame(frame, 127u, TimeDelta::Millis(7),
                                     VideoContentType::UNSPECIFIED);
-  EXPECT_EQ(11u, FlushAndGetStats().total_decode_time_ms);
+  EXPECT_EQ(11u, FlushAndGetStats().total_decode_time.ms());
 }
 
 TEST_F(ReceiveStatisticsProxy2Test, ReportsContentType) {
@@ -307,11 +312,11 @@
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
   EXPECT_EQ(kRealtimeString, videocontenttypehelpers::ToString(
                                  statistics_proxy_->GetStats().content_type));
-  statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
+  statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(0),
                                     VideoContentType::SCREENSHARE);
   EXPECT_EQ(kScreenshareString,
             videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
-  statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
+  statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(kRealtimeString,
             videocontenttypehelpers::ToString(FlushAndGetStats().content_type));
@@ -329,7 +334,7 @@
   EXPECT_EQ(expected_total_squared_inter_frame_delay,
             statistics_proxy_->GetStats().total_squared_inter_frame_delay);
 
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_DOUBLE_EQ(expected_total_inter_frame_delay,
                    FlushAndGetStats().total_inter_frame_delay);
@@ -337,7 +342,7 @@
                    FlushAndGetStats().total_squared_inter_frame_delay);
 
   fake_clock_.AdvanceTime(kInterFrameDelay1);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   expected_total_inter_frame_delay += kInterFrameDelay1.seconds<double>();
   expected_total_squared_inter_frame_delay +=
@@ -349,7 +354,7 @@
       statistics_proxy_->GetStats().total_squared_inter_frame_delay);
 
   fake_clock_.AdvanceTime(kInterFrameDelay2);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   expected_total_inter_frame_delay += kInterFrameDelay2.seconds<double>();
   expected_total_squared_inter_frame_delay +=
@@ -361,7 +366,7 @@
       statistics_proxy_->GetStats().total_squared_inter_frame_delay);
 
   fake_clock_.AdvanceTime(kInterFrameDelay3);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   expected_total_inter_frame_delay += kInterFrameDelay3.seconds<double>();
   expected_total_squared_inter_frame_delay +=
@@ -379,22 +384,22 @@
   const int64_t kInterframeDelayMs2 = 200;
   const int64_t kInterframeDelayMs3 = 100;
   EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
 
   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(kInterframeDelayMs1, FlushAndGetStats().interframe_delay_max_ms);
 
   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(kInterframeDelayMs2, FlushAndGetStats().interframe_delay_max_ms);
 
   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   // kInterframeDelayMs3 is smaller than kInterframeDelayMs2.
   EXPECT_EQ(kInterframeDelayMs2, FlushAndGetStats().interframe_delay_max_ms);
@@ -406,23 +411,23 @@
   const int64_t kInterframeDelayMs2 = 750;
   const int64_t kInterframeDelayMs3 = 700;
   EXPECT_EQ(-1, statistics_proxy_->GetStats().interframe_delay_max_ms);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(-1, FlushAndGetStats().interframe_delay_max_ms);
 
   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs1);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(kInterframeDelayMs1, FlushAndGetStats().interframe_delay_max_ms);
 
   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs2);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   // Still first delay is the maximum
   EXPECT_EQ(kInterframeDelayMs1, FlushAndGetStats().interframe_delay_max_ms);
 
   fake_clock_.AdvanceTimeMilliseconds(kInterframeDelayMs3);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   // Now the first sample is out of the window, so the second is the maximum.
   EXPECT_EQ(kInterframeDelayMs2, FlushAndGetStats().interframe_delay_max_ms);
@@ -532,7 +537,7 @@
 TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameWithoutQpQpSumWontExist) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
   EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
 }
@@ -540,10 +545,10 @@
 TEST_F(ReceiveStatisticsProxy2Test, OnDecodedFrameWithoutQpResetsQpSum) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
   EXPECT_EQ(absl::nullopt, statistics_proxy_->GetStats().qp_sum);
-  statistics_proxy_->OnDecodedFrame(frame, 3u, 0,
+  statistics_proxy_->OnDecodedFrame(frame, 3u, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(3u, FlushAndGetStats().qp_sum);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
   EXPECT_EQ(absl::nullopt, FlushAndGetStats().qp_sum);
 }
@@ -1014,7 +1019,8 @@
     // Since OnRenderedFrame is never called the fps in each sample will be 0,
     // i.e. bad
     frame.set_ntp_time_ms(fake_clock_.CurrentNtpInMilliseconds());
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0),
                                       VideoContentType::UNSPECIFIED);
     statistics_proxy_->OnRenderedFrame(MetaData(frame));
     fake_clock_.AdvanceTimeMilliseconds(1000 / kDefaultFps);
@@ -1083,7 +1089,7 @@
 
 TEST_F(ReceiveStatisticsProxy2Test, ZeroDelayReportedIfFrameNotDelayed) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
 
   // Frame not delayed, delayed frames to render: 0%.
@@ -1104,7 +1110,7 @@
 TEST_F(ReceiveStatisticsProxy2Test,
        DelayedFrameHistogramsAreNotUpdatedIfMinRuntimeHasNotPassed) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
 
   // Frame not delayed, delayed frames to render: 0%.
@@ -1125,7 +1131,7 @@
 TEST_F(ReceiveStatisticsProxy2Test,
        DelayedFramesHistogramsAreNotUpdatedIfNoRenderedFrames) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
 
   // Min run time has passed. No rendered frames.
@@ -1140,7 +1146,7 @@
 
 TEST_F(ReceiveStatisticsProxy2Test, DelayReportedIfFrameIsDelayed) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
 
   // Frame delayed 1 ms, delayed frames to render: 100%.
@@ -1163,7 +1169,7 @@
 
 TEST_F(ReceiveStatisticsProxy2Test, AverageDelayOfDelayedFramesIsReported) {
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0,
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
                                     VideoContentType::UNSPECIFIED);
 
   // Two frames delayed (6 ms, 10 ms), delayed frames to render: 50%.
@@ -1315,12 +1321,14 @@
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
 
   for (int i = 0; i < kMinRequiredSamples; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
   }
   // One extra with double the interval.
   fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
+                                    content_type_);
 
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
   const int kExpectedInterFrame =
@@ -1350,16 +1358,19 @@
 
   for (int i = 0; i <= kMinRequiredSamples - kLastFivePercentsSamples; ++i) {
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
   }
   // Last 5% of intervals are double in size.
   for (int i = 0; i < kLastFivePercentsSamples; ++i) {
     fake_clock_.AdvanceTimeMilliseconds(2 * kInterFrameDelayMs);
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
   }
   // Final sample is outlier and 10 times as big.
   fake_clock_.AdvanceTimeMilliseconds(10 * kInterFrameDelayMs);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
+                                    content_type_);
 
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
   const int kExpectedInterFrame = kInterFrameDelayMs * 2;
@@ -1381,7 +1392,8 @@
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
 
   for (int i = 0; i < kMinRequiredSamples; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
   }
 
@@ -1404,7 +1416,8 @@
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
 
   for (int i = 0; i <= kMinRequiredSamples; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
   }
 
@@ -1416,9 +1429,11 @@
 
   // Insert two more frames. The interval during the pause should be
   // disregarded in the stats.
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
+                                    content_type_);
   fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
+                                    content_type_);
 
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
   if (videocontenttypehelpers::IsScreenshare(content_type_)) {
@@ -1454,7 +1469,7 @@
   for (int i = 0; i < kMinRequiredSamples; ++i) {
     VideoFrameMetaData meta = MetaData(frame);
     statistics_proxy_->OnDecodedFrame(
-        meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
+        meta, absl::nullopt, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
@@ -1463,7 +1478,7 @@
   fake_clock_.AdvanceTimeMilliseconds(kFreezeDelayMs);
   VideoFrameMetaData meta = MetaData(frame);
   statistics_proxy_->OnDecodedFrame(
-      meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
+      meta, absl::nullopt, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
       webrtc::TimeDelta::Millis(0), content_type_);
   statistics_proxy_->OnRenderedFrame(meta);
 
@@ -1502,7 +1517,8 @@
 
   for (int i = 0; i < kMinRequiredSamples; ++i) {
     fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(MetaData(frame));
   }
 
@@ -1510,14 +1526,16 @@
   // Add freeze.
   loop_.Flush();
   fake_clock_.AdvanceTimeMilliseconds(kFreezeDurationMs);
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
+                                    content_type_);
   statistics_proxy_->OnRenderedFrame(MetaData(frame));
 
   // Add pause.
   loop_.Flush();
   fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
   statistics_proxy_->OnStreamInactive();
-  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, TimeDelta::Millis(0),
+                                    content_type_);
   statistics_proxy_->OnRenderedFrame(MetaData(frame));
 
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
@@ -1548,7 +1566,7 @@
   for (int i = 0; i <= kMinRequiredSamples; ++i) {
     VideoFrameMetaData meta = MetaData(frame);
     statistics_proxy_->OnDecodedFrame(
-        meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
+        meta, absl::nullopt, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
@@ -1560,7 +1578,7 @@
   for (int i = 0; i <= kMinRequiredSamples * 3; ++i) {
     VideoFrameMetaData meta = MetaData(frame);
     statistics_proxy_->OnDecodedFrame(
-        meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
+        meta, absl::nullopt, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
@@ -1591,13 +1609,15 @@
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
 
   for (int i = 0; i <= kMinRequiredSamples; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
 
     statistics_proxy_->OnStreamInactive();
     fake_clock_.AdvanceTimeMilliseconds(kPauseDurationMs);
 
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type_);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type_);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
   }
 
@@ -1623,7 +1643,7 @@
   for (int i = 0; i < kMinRequiredSamples; ++i) {
     VideoFrameMetaData meta = MetaData(frame_hd);
     statistics_proxy_->OnDecodedFrame(
-        meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
+        meta, absl::nullopt, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
@@ -1632,7 +1652,7 @@
   for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
     VideoFrameMetaData meta = MetaData(frame_sd);
     statistics_proxy_->OnDecodedFrame(
-        meta, absl::nullopt, 0, webrtc::TimeDelta::Millis(0),
+        meta, absl::nullopt, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
@@ -1663,7 +1683,7 @@
   for (int i = 0; i < kMinRequiredSamples; ++i) {
     VideoFrameMetaData meta = MetaData(frame);
     statistics_proxy_->OnDecodedFrame(
-        meta, kLowQp, 0, webrtc::TimeDelta::Millis(0),
+        meta, kLowQp, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
@@ -1672,13 +1692,14 @@
   for (int i = 0; i < 2 * kMinRequiredSamples; ++i) {
     VideoFrameMetaData meta = MetaData(frame);
     statistics_proxy_->OnDecodedFrame(
-        meta, kHighQp, 0, webrtc::TimeDelta::Millis(0),
+        meta, kHighQp, TimeDelta::Millis(0), webrtc::TimeDelta::Millis(0),
         webrtc::TimeDelta::Millis(0), content_type_);
     statistics_proxy_->OnRenderedFrame(meta);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
   }
   // Extra last frame.
-  statistics_proxy_->OnDecodedFrame(frame, kHighQp, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame, kHighQp, TimeDelta::Millis(0),
+                                    content_type_);
   statistics_proxy_->OnRenderedFrame(MetaData(frame));
 
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
@@ -1703,7 +1724,8 @@
   webrtc::VideoFrame frame_ld = CreateFrame(320, 180);
 
   // Call once to pass content type.
-  statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt, 0, content_type_);
+  statistics_proxy_->OnDecodedFrame(frame_hd, absl::nullopt,
+                                    TimeDelta::Millis(0), content_type_);
 
   loop_.Flush();
   statistics_proxy_->OnRenderedFrame(MetaData(frame_hd));
@@ -1740,7 +1762,8 @@
   webrtc::VideoFrame frame = CreateFrame(kWidth, kHeight);
 
   for (int i = 0; i < kMinRequiredSamples; ++i) {
-    statistics_proxy_->OnDecodedFrame(frame, kLowQp, kDecodeMs, content_type_);
+    statistics_proxy_->OnDecodedFrame(
+        frame, kLowQp, TimeDelta::Millis(kDecodeMs), content_type_);
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs);
   }
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
@@ -1760,13 +1783,15 @@
   videocontenttypehelpers::SetSimulcastId(&content_type, 1);
   for (int i = 0; i <= kMinRequiredSamples; ++i) {
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs1);
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type);
   }
 
   videocontenttypehelpers::SetSimulcastId(&content_type, 2);
   for (int i = 0; i <= kMinRequiredSamples; ++i) {
     fake_clock_.AdvanceTimeMilliseconds(kInterFrameDelayMs2);
-    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt, 0, content_type);
+    statistics_proxy_->OnDecodedFrame(frame, absl::nullopt,
+                                      TimeDelta::Millis(0), content_type);
   }
   FlushAndUpdateHistograms(absl::nullopt, StreamDataCounters(), nullptr);
 
@@ -1876,7 +1901,7 @@
 
   for (int i = 0; i < kNumberOfFrames; ++i) {
     statistics_proxy_->OnDecodedFrame(frame, /*qp=*/absl::nullopt,
-                                      kDecodeTimeMs,
+                                      TimeDelta::Millis(kDecodeTimeMs),
                                       VideoContentType::UNSPECIFIED);
     fake_clock_.AdvanceTimeMilliseconds(kFrameDurationMs);
   }
diff --git a/video/video_analyzer.cc b/video/video_analyzer.cc
index f298f33..311fd31 100644
--- a/video/video_analyzer.cc
+++ b/video/video_analyzer.cc
@@ -496,9 +496,8 @@
     // `total_decode_time_ms` gives a good estimate of the mean decode time,
     // `decode_ms` is used to keep track of the standard deviation.
     if (receive_stats.frames_decoded > 0)
-      mean_decode_time_ms_ =
-          static_cast<double>(receive_stats.total_decode_time_ms) /
-          receive_stats.frames_decoded;
+      mean_decode_time_ms_ = receive_stats.total_decode_time.ms<double>() /
+                             receive_stats.frames_decoded;
     if (receive_stats.decode_ms > 0)
       decode_time_ms_.AddSample(receive_stats.decode_ms);
     if (receive_stats.max_decode_ms > 0)
diff --git a/video/video_stream_decoder2.cc b/video/video_stream_decoder2.cc
index 6ef6002..0a8825d 100644
--- a/video/video_stream_decoder2.cc
+++ b/video/video_stream_decoder2.cc
@@ -44,9 +44,9 @@
 // Release. Acquiring the same lock in the path of decode callback can deadlock.
 int32_t VideoStreamDecoder::FrameToRender(VideoFrame& video_frame,
                                           absl::optional<uint8_t> qp,
-                                          int32_t decode_time_ms,
+                                          TimeDelta decode_time,
                                           VideoContentType content_type) {
-  receive_stats_callback_->OnDecodedFrame(video_frame, qp, decode_time_ms,
+  receive_stats_callback_->OnDecodedFrame(video_frame, qp, decode_time,
                                           content_type);
   incoming_video_stream_->OnFrame(video_frame);
   return 0;
diff --git a/video/video_stream_decoder2.h b/video/video_stream_decoder2.h
index a301d32..995008d 100644
--- a/video/video_stream_decoder2.h
+++ b/video/video_stream_decoder2.h
@@ -41,7 +41,7 @@
   // Implements VCMReceiveCallback.
   int32_t FrameToRender(VideoFrame& video_frame,
                         absl::optional<uint8_t> qp,
-                        int32_t decode_time_ms,
+                        TimeDelta decode_time,
                         VideoContentType content_type) override;
   void OnDroppedFrames(uint32_t frames_dropped) override;
   void OnIncomingPayloadType(int payload_type) override;