| /* |
| * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved. |
| * |
| * Use of this source code is governed by a BSD-style license |
| * that can be found in the LICENSE file in the root of the source |
| * tree. An additional intellectual property rights grant can be found |
| * in the file PATENTS. All contributing project authors may |
| * be found in the AUTHORS file in the root of the source tree. |
| */ |
| |
| #ifndef MODULES_VIDEO_CODING_TIMING_FRAME_DELAY_VARIATION_KALMAN_FILTER_H_ |
| #define MODULES_VIDEO_CODING_TIMING_FRAME_DELAY_VARIATION_KALMAN_FILTER_H_ |
| |
| #include "api/units/data_size.h" |
| #include "api/units/time_delta.h" |
| |
| namespace webrtc { |
| |
| // This class uses a linear Kalman filter (see |
| // https://en.wikipedia.org/wiki/Kalman_filter) to estimate the frame delay |
| // variation (i.e., the difference in transmission time between a frame and the |
| // prior frame) for a frame, given its size variation in bytes (i.e., the |
| // difference in size between a frame and the prior frame). The idea is that, |
| // given a fixed link bandwidth, a larger frame (in bytes) would take |
| // proportionally longer to arrive than a correspondingly smaller frame. Using |
| // the variations of frame delay and frame size, the underlying bandwidth and |
| // queuing delay variation of the network link can be estimated. |
| // |
| // The filter takes as input the frame delay variation, the difference between |
| // the actual inter-frame arrival time and the expected inter-frame arrival time |
| // (based on RTP timestamp), and frame size variation, the inter-frame size |
| // delta for a single frame. The frame delay variation is seen as the |
| // measurement and the frame size variation is used in the observation model. |
| // The hidden state of the filter is the link bandwidth and queuing delay |
| // buildup. The estimated state can be used to get the expected frame delay |
| // variation for a frame, given its frame size variation. This information can |
| // then be used to estimate the frame delay variation coming from network |
| // jitter. |
| // |
| // Mathematical details: |
| // * The state (`x` in Wikipedia notation) is a 2x1 vector comprising the |
| // reciprocal of link bandwidth [1 / bytes per ms] and the |
| // link queuing delay buildup [ms]. |
| // * The state transition matrix (`F`) is the 2x2 identity matrix, meaning that |
| // link bandwidth and link queuing delay buildup are modeled as independent. |
| // * The measurement (`z`) is the (scalar) frame delay variation [ms]. |
| // * The observation matrix (`H`) is a 1x2 vector set as |
| // `{frame_size_variation [bytes], 1.0}`. |
| // * The state estimate covariance (`P`) is a symmetric 2x2 matrix. |
| // * The process noise covariance (`Q`) is a constant 2x2 diagonal matrix |
| // [(1 / bytes per ms)^2, ms^2]. |
| // * The observation noise covariance (`r`) is a scalar [ms^2] that is |
| // determined externally to this class. |
| class FrameDelayVariationKalmanFilter { |
| public: |
| FrameDelayVariationKalmanFilter(); |
| ~FrameDelayVariationKalmanFilter() = default; |
| |
| // Predicts and updates the filter, given a new pair of frame delay variation |
| // and frame size variation. |
| // |
| // Inputs: |
| // `frame_delay_variation_ms`: |
| // Frame delay variation as calculated by the `InterFrameDelay` estimator. |
| // |
| // `frame_size_variation_bytes`: |
| // Frame size variation, i.e., the current frame size minus the previous |
| // frame size (in bytes). Note that this quantity may be negative. |
| // |
| // `max_frame_size_bytes`: |
| // Filtered largest frame size received since the last reset. |
| // |
| // `var_noise`: |
| // Variance of the estimated random jitter. |
| // |
| // TODO(bugs.webrtc.org/14381): For now use doubles as input parameters as |
| // units defined in api/units have insufficient underlying precision for |
| // jitter estimation. |
| void PredictAndUpdate(double frame_delay_variation_ms, |
| double frame_size_variation_bytes, |
| double max_frame_size_bytes, |
| double var_noise); |
| |
| // Given a frame size variation, returns the estimated frame delay variation |
| // explained by the link bandwidth alone. |
| double GetFrameDelayVariationEstimateSizeBased( |
| double frame_size_variation_bytes) const; |
| |
| // Given a frame size variation, returns the estimated frame delay variation |
| // explained by both link bandwidth and link queuing delay buildup. |
| double GetFrameDelayVariationEstimateTotal( |
| double frame_size_variation_bytes) const; |
| |
| private: |
| // State estimate (bandwidth [1 / bytes per ms], queue buildup [ms]). |
| double estimate_[2]; |
| double estimate_cov_[2][2]; // Estimate covariance. |
| |
| // Process noise covariance. This is a diagonal matrix, so we only store the |
| // diagonal entries. |
| double process_noise_cov_diag_[2]; |
| }; |
| |
| } // namespace webrtc |
| |
| #endif // MODULES_VIDEO_CODING_TIMING_FRAME_DELAY_VARIATION_KALMAN_FILTER_H_ |