xref: /aosp_15_r20/external/webrtc/modules/video_coding/timing/jitter_estimator.h (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3  *
4  *  Use of this source code is governed by a BSD-style license
5  *  that can be found in the LICENSE file in the root of the source
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #ifndef MODULES_VIDEO_CODING_TIMING_JITTER_ESTIMATOR_H_
12 #define MODULES_VIDEO_CODING_TIMING_JITTER_ESTIMATOR_H_
13 
14 #include <algorithm>
15 #include <memory>
16 #include <queue>
17 
18 #include "absl/strings/string_view.h"
19 #include "absl/types/optional.h"
20 #include "api/field_trials_view.h"
21 #include "api/units/data_size.h"
22 #include "api/units/frequency.h"
23 #include "api/units/time_delta.h"
24 #include "api/units/timestamp.h"
25 #include "modules/video_coding/timing/frame_delay_variation_kalman_filter.h"
26 #include "modules/video_coding/timing/rtt_filter.h"
27 #include "rtc_base/experiments/struct_parameters_parser.h"
28 #include "rtc_base/numerics/moving_percentile_filter.h"
29 #include "rtc_base/rolling_accumulator.h"
30 
31 namespace webrtc {
32 
33 class Clock;
34 
35 class JitterEstimator {
36  public:
37   // Configuration struct for statically overriding some constants and
38   // behaviour, configurable through field trials.
39   struct Config {
40     static constexpr char kFieldTrialsKey[] = "WebRTC-JitterEstimatorConfig";
41 
42     // Parses a field trial string and validates the values.
43     static Config ParseAndValidate(absl::string_view field_trial);
44 
ParserConfig45     std::unique_ptr<StructParametersParser> Parser() {
46       // clang-format off
47       return StructParametersParser::Create(
48           "avg_frame_size_median", &avg_frame_size_median,
49           "max_frame_size_percentile", &max_frame_size_percentile,
50           "frame_size_window", &frame_size_window,
51           "num_stddev_delay_clamp", &num_stddev_delay_clamp,
52           "num_stddev_delay_outlier", &num_stddev_delay_outlier,
53           "num_stddev_size_outlier", &num_stddev_size_outlier,
54           "congestion_rejection_factor", &congestion_rejection_factor,
55           "estimate_noise_when_congested", &estimate_noise_when_congested);
56       // clang-format on
57     }
58 
MaxFrameSizePercentileEnabledConfig59     bool MaxFrameSizePercentileEnabled() const {
60       return max_frame_size_percentile.has_value();
61     }
62 
63     // If true, the "avg" frame size is calculated as the median over a window
64     // of recent frame sizes.
65     bool avg_frame_size_median = false;
66 
67     // If set, the "max" frame size is calculated as this percentile over a
68     // window of recent frame sizes.
69     absl::optional<double> max_frame_size_percentile = absl::nullopt;
70 
71     // The length of the percentile filters' window, in number of frames.
72     absl::optional<int> frame_size_window = absl::nullopt;
73 
74     // The incoming frame delay variation samples are clamped to be at most
75     // this number of standard deviations away from zero.
76     //
77     // Increasing this value clamps fewer samples.
78     absl::optional<double> num_stddev_delay_clamp = absl::nullopt;
79 
80     // A (relative) frame delay variation sample is an outlier if its absolute
81     // deviation from the Kalman filter model falls outside this number of
82     // sample standard deviations.
83     //
84     // Increasing this value rejects fewer samples.
85     absl::optional<double> num_stddev_delay_outlier = absl::nullopt;
86 
87     // An (absolute) frame size sample is an outlier if its positive deviation
88     // from the estimated average frame size falls outside this number of sample
89     // standard deviations.
90     //
91     // Increasing this value rejects fewer samples.
92     absl::optional<double> num_stddev_size_outlier = absl::nullopt;
93 
94     // A (relative) frame size variation sample is deemed "congested", and is
95     // thus rejected, if its value is less than this factor times the estimated
96     // max frame size.
97     //
98     // Decreasing this value rejects fewer samples.
99     absl::optional<double> congestion_rejection_factor = absl::nullopt;
100 
101     // If true, the noise estimate will be updated for congestion rejected
102     // frames. This is currently enabled by default, but that may not be optimal
103     // since congested frames typically are not spread around the line with
104     // Gaussian noise. (This is the whole reason for the congestion rejection!)
105     bool estimate_noise_when_congested = true;
106   };
107 
108   JitterEstimator(Clock* clock, const FieldTrialsView& field_trials);
109   JitterEstimator(const JitterEstimator&) = delete;
110   JitterEstimator& operator=(const JitterEstimator&) = delete;
111   ~JitterEstimator();
112 
113   // Resets the estimate to the initial state.
114   void Reset();
115 
116   // Updates the jitter estimate with the new data.
117   //
118   // Input:
119   //          - frame_delay      : Delay-delta calculated by UTILDelayEstimate.
120   //          - frame_size       : Frame size of the current frame.
121   void UpdateEstimate(TimeDelta frame_delay, DataSize frame_size);
122 
123   // Returns the current jitter estimate and adds an RTT dependent term in cases
124   // of retransmission.
125   //  Input:
126   //          - rtt_multiplier   : RTT param multiplier (when applicable).
127   //          - rtt_mult_add_cap : Multiplier cap from the RTTMultExperiment.
128   //
129   // Return value              : Jitter estimate.
130   TimeDelta GetJitterEstimate(double rtt_multiplier,
131                               absl::optional<TimeDelta> rtt_mult_add_cap);
132 
133   // Updates the nack counter.
134   void FrameNacked();
135 
136   // Updates the RTT filter.
137   //
138   // Input:
139   //          - rtt          : Round trip time.
140   void UpdateRtt(TimeDelta rtt);
141 
142   // Returns the configuration. Only to be used by unit tests.
143   Config GetConfigForTest() const;
144 
145  private:
146   // Updates the random jitter estimate, i.e. the variance of the time
147   // deviations from the line given by the Kalman filter.
148   //
149   // Input:
150   //          - d_dT              : The deviation from the kalman estimate.
151   void EstimateRandomJitter(double d_dT);
152 
153   double NoiseThreshold() const;
154 
155   // Calculates the current jitter estimate.
156   //
157   // Return value                 : The current jitter estimate.
158   TimeDelta CalculateEstimate();
159 
160   // Post process the calculated estimate.
161   void PostProcessEstimate();
162 
163   // Returns the estimated incoming frame rate.
164   Frequency GetFrameRate() const;
165 
166   // Configuration that may override some internals.
167   const Config config_;
168 
169   // Filters the {frame_delay_delta, frame_size_delta} measurements through
170   // a linear Kalman filter.
171   FrameDelayVariationKalmanFilter kalman_filter_;
172 
173   // TODO(bugs.webrtc.org/14381): Update `avg_frame_size_bytes_` to DataSize
174   // when api/units have sufficient precision.
175   double avg_frame_size_bytes_;  // Average frame size
176   double var_frame_size_bytes2_;  // Frame size variance. Unit is bytes^2.
177   // Largest frame size received (descending with a factor kPsi).
178   // Used by default.
179   // TODO(bugs.webrtc.org/14381): Update `max_frame_size_bytes_` to DataSize
180   // when api/units have sufficient precision.
181   double max_frame_size_bytes_;
182   // Percentile frame sized received (over a window). Only used if configured.
183   MovingMedianFilter<int64_t> avg_frame_size_median_bytes_;
184   MovingPercentileFilter<int64_t> max_frame_size_bytes_percentile_;
185   // TODO(bugs.webrtc.org/14381): Update `startup_frame_size_sum_bytes_` to
186   // DataSize when api/units have sufficient precision.
187   double startup_frame_size_sum_bytes_;
188   size_t startup_frame_size_count_;
189 
190   absl::optional<Timestamp> last_update_time_;
191   // The previously returned jitter estimate
192   absl::optional<TimeDelta> prev_estimate_;
193   // Frame size of the previous frame
194   absl::optional<DataSize> prev_frame_size_;
195   // Average of the random jitter. Unit is milliseconds.
196   double avg_noise_ms_;
197   // Variance of the time-deviation from the line. Unit is milliseconds^2.
198   double var_noise_ms2_;
199   size_t alpha_count_;
200   // The filtered sum of jitter estimates
201   TimeDelta filter_jitter_estimate_ = TimeDelta::Zero();
202 
203   size_t startup_count_;
204   // Time when the latest nack was seen
205   Timestamp latest_nack_ = Timestamp::Zero();
206   // Keeps track of the number of nacks received, but never goes above
207   // kNackLimit.
208   size_t nack_count_;
209   RttFilter rtt_filter_;
210 
211   // Tracks frame rates in microseconds.
212   rtc::RollingAccumulator<uint64_t> fps_counter_;
213   Clock* clock_;
214 };
215 
216 }  // namespace webrtc
217 
218 #endif  // MODULES_VIDEO_CODING_TIMING_JITTER_ESTIMATOR_H_
219