Add jitter estimation logic to `DefaultVideoJitterTiming`.

Adds `JitterEstimator` and `InterFrameDelayVariationCalculator` to `DefaultVideoJitterTiming`.

Usage will be wired up separately.

Bug: b/493549134
Change-Id: I29b5d5eaf0ce8349ab9345f0b06786cb4cdc76e6
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/480460
Reviewed-by: Rasmus Brandt <brandtr@webrtc.org>
Commit-Queue: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#47958}
diff --git a/modules/video_coding/timing/BUILD.gn b/modules/video_coding/timing/BUILD.gn
index db022ba..70ef264 100644
--- a/modules/video_coding/timing/BUILD.gn
+++ b/modules/video_coding/timing/BUILD.gn
@@ -101,8 +101,12 @@
     "default_video_jitter_timing.h",
   ]
   deps = [
+    ":inter_frame_delay_variation_calculator",
+    ":jitter_estimator",
     ":timestamp_extrapolator",
     "../../../api:field_trials_view",
+    "../../../api/units:data_size",
+    "../../../api/units:time_delta",
     "../../../api/units:timestamp",
     "../../../system_wrappers",
   ]
diff --git a/modules/video_coding/timing/default_video_jitter_timing.cc b/modules/video_coding/timing/default_video_jitter_timing.cc
index 76e4238..01a3335 100644
--- a/modules/video_coding/timing/default_video_jitter_timing.cc
+++ b/modules/video_coding/timing/default_video_jitter_timing.cc
@@ -14,7 +14,11 @@
 #include <optional>
 
 #include "api/field_trials_view.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
+#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
+#include "modules/video_coding/timing/jitter_estimator.h"
 #include "modules/video_coding/timing/timestamp_extrapolator.h"
 #include "system_wrappers/include/clock.h"
 
@@ -23,10 +27,13 @@
 DefaultVideoJitterTiming::DefaultVideoJitterTiming(
     Clock* clock,
     const FieldTrialsView& field_trials)
-    : clock_(clock), ts_extrapolator_(clock_->CurrentTime(), field_trials) {}
+    : clock_(clock),
+      ts_extrapolator_(clock_->CurrentTime(), field_trials),
+      jitter_estimator_(clock_, field_trials) {}
 
 void DefaultVideoJitterTiming::Reset() {
   ts_extrapolator_.Reset(clock_->CurrentTime());
+  jitter_estimator_.Reset();
 }
 
 void DefaultVideoJitterTiming::OnCompleteTemporalUnit(uint32_t rtp_timestamp,
@@ -39,4 +46,26 @@
   return ts_extrapolator_.ExtrapolateLocalTime(rtp_timestamp);
 }
 
+std::optional<TimeDelta> DefaultVideoJitterTiming::OnDecodableTemporalUnit(
+    uint32_t rtp_timestamp,
+    DataSize superframe_size,
+    Timestamp max_receive_time,
+    bool was_retransmitted) {
+  if (was_retransmitted) {
+    jitter_estimator_.FrameNacked();
+    return std::nullopt;
+  }
+  std::optional<TimeDelta> inter_frame_delay_variation =
+      ifdv_calculator_.Calculate(rtp_timestamp, max_receive_time);
+  if (inter_frame_delay_variation) {
+    jitter_estimator_.UpdateEstimate(*inter_frame_delay_variation,
+                                     superframe_size);
+  }
+  return jitter_estimator_.GetEstimate();
+}
+
+void DefaultVideoJitterTiming::UpdateRtt(TimeDelta rtt) {
+  jitter_estimator_.UpdateRtt(rtt);
+}
+
 }  // namespace webrtc
diff --git a/modules/video_coding/timing/default_video_jitter_timing.h b/modules/video_coding/timing/default_video_jitter_timing.h
index fc5398c..a88eb0a 100644
--- a/modules/video_coding/timing/default_video_jitter_timing.h
+++ b/modules/video_coding/timing/default_video_jitter_timing.h
@@ -15,7 +15,11 @@
 #include <optional>
 
 #include "api/field_trials_view.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
+#include "modules/video_coding/timing/inter_frame_delay_variation_calculator.h"
+#include "modules/video_coding/timing/jitter_estimator.h"
 #include "modules/video_coding/timing/timestamp_extrapolator.h"
 #include "system_wrappers/include/clock.h"
 
@@ -36,9 +40,21 @@
   // Returns the extrapolated local time for a given RTP timestamp.
   std::optional<Timestamp> ExtrapolateLocalTime(uint32_t rtp_timestamp) const;
 
+  // Updates the jitter estimator with the information of a decodable temporal
+  // unit. Returns the current jitter estimate if available.
+  std::optional<TimeDelta> OnDecodableTemporalUnit(uint32_t rtp_timestamp,
+                                                   DataSize superframe_size,
+                                                   Timestamp max_receive_time,
+                                                   bool was_retransmitted);
+
+  // Updates the jitter estimator with the current RTT.
+  void UpdateRtt(TimeDelta rtt);
+
  private:
   Clock* const clock_;
   TimestampExtrapolator ts_extrapolator_;
+  JitterEstimator jitter_estimator_;
+  InterFrameDelayVariationCalculator ifdv_calculator_;
 };
 
 }  // namespace webrtc
diff --git a/modules/video_coding/timing/default_video_jitter_timing_unittest.cc b/modules/video_coding/timing/default_video_jitter_timing_unittest.cc
index 4710156..f73cdda 100644
--- a/modules/video_coding/timing/default_video_jitter_timing_unittest.cc
+++ b/modules/video_coding/timing/default_video_jitter_timing_unittest.cc
@@ -14,6 +14,8 @@
 #include <optional>
 
 #include "api/field_trials.h"
+#include "api/units/data_size.h"
+#include "api/units/time_delta.h"
 #include "api/units/timestamp.h"
 #include "system_wrappers/include/clock.h"
 #include "test/create_test_field_trials.h"
@@ -24,6 +26,8 @@
 
 constexpr uint32_t kRtpTimestamp = 12345;
 constexpr Timestamp kInitialTime = Timestamp::Millis(789);
+constexpr DataSize kFrameSize = DataSize::Bytes(1000);
+constexpr TimeDelta kRtt = TimeDelta::Millis(100);
 
 TEST(DefaultVideoJitterTimingTest, ExtrapolatorReturnsNulloptInitially) {
   FieldTrials field_trials = CreateTestFieldTrials();
@@ -54,5 +58,88 @@
   EXPECT_EQ(timing.ExtrapolateLocalTime(kRtpTimestamp), std::nullopt);
 }
 
+TEST(DefaultVideoJitterTimingTest, OnDecodableTemporalUnitReturnsEstimate) {
+  FieldTrials field_trials = CreateTestFieldTrials();
+  SimulatedClock clock(kInitialTime);
+  DefaultVideoJitterTiming timing(&clock, field_trials);
+
+  EXPECT_NE(timing.OnDecodableTemporalUnit(kRtpTimestamp, kFrameSize,
+                                           clock.CurrentTime(),
+                                           /*was_retransmitted=*/false),
+            std::nullopt);
+}
+
+TEST(DefaultVideoJitterTimingTest,
+     OnDecodableTemporalUnitReturnsNulloptOnRetransmission) {
+  FieldTrials field_trials = CreateTestFieldTrials();
+  SimulatedClock clock(kInitialTime);
+  DefaultVideoJitterTiming timing(&clock, field_trials);
+
+  EXPECT_EQ(timing.OnDecodableTemporalUnit(kRtpTimestamp, kFrameSize,
+                                           clock.CurrentTime(),
+                                           /*was_retransmitted=*/true),
+            std::nullopt);
+}
+
+TEST(DefaultVideoJitterTimingTest, EstimateIncludesRttAfterRetransmission) {
+  constexpr double kMargin = 0.8;
+  FieldTrials field_trials =
+      CreateTestFieldTrials("WebRTC-JitterEstimatorConfig/nack_limit:1/");
+  SimulatedClock clock(kInitialTime);
+  DefaultVideoJitterTiming timing(&clock, field_trials);
+
+  timing.UpdateRtt(kRtt);
+
+  std::optional<TimeDelta> initial_estimate = timing.OnDecodableTemporalUnit(
+      /*rtp_timestamp=*/3000, kFrameSize, clock.CurrentTime(),
+      /*was_retransmitted=*/false);
+  ASSERT_TRUE(initial_estimate.has_value());
+
+  // Retransmitted frame.
+  clock.AdvanceTime(TimeDelta::Millis(33));
+  EXPECT_EQ(timing.OnDecodableTemporalUnit(/*rtp_timestamp=*/6000, kFrameSize,
+                                           clock.CurrentTime(),
+                                           /*was_retransmitted=*/true),
+            std::nullopt);
+
+  // Get estimate after retransmission.
+  clock.AdvanceTime(TimeDelta::Millis(33));
+  EXPECT_GT(timing.OnDecodableTemporalUnit(/*rtp_timestamp=*/9000, kFrameSize,
+                                           clock.CurrentTime(),
+                                           /*was_retransmitted=*/false),
+            *initial_estimate + kMargin * kRtt);
+}
+
+TEST(DefaultVideoJitterTimingTest, ResetClearsJitterEstimator) {
+  constexpr double kMargin = 0.5;
+  FieldTrials field_trials =
+      CreateTestFieldTrials("WebRTC-JitterEstimatorConfig/nack_limit:1/");
+  SimulatedClock clock(kInitialTime);
+  DefaultVideoJitterTiming timing(&clock, field_trials);
+
+  timing.UpdateRtt(kRtt);
+
+  std::optional<TimeDelta> initial_estimate = timing.OnDecodableTemporalUnit(
+      /*rtp_timestamp=*/3000, kFrameSize, clock.CurrentTime(),
+      /*was_retransmitted=*/false);
+  ASSERT_TRUE(initial_estimate.has_value());
+
+  // Retransmitted frame.
+  clock.AdvanceTime(TimeDelta::Millis(33));
+  EXPECT_EQ(timing.OnDecodableTemporalUnit(/*rtp_timestamp=*/6000, kFrameSize,
+                                           clock.CurrentTime(),
+                                           /*was_retransmitted=*/true),
+            std::nullopt);
+
+  timing.Reset();
+
+  // Get estimate after retransmission and reset, should not include RTT.
+  clock.AdvanceTime(TimeDelta::Millis(33));
+  EXPECT_LT(timing.OnDecodableTemporalUnit(/*rtp_timestamp=*/9000, kFrameSize,
+                                           clock.CurrentTime(),
+                                           /*was_retransmitted=*/false),
+            *initial_estimate + kMargin * kRtt);
+}
+
 }  // namespace
 }  // namespace webrtc