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