summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/modules/video_coding/timing/frame_delay_variation_kalman_filter_unittest.cc
blob: 6103f3a1bcce07437a63d08a60c7dc6899fd7821 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/*
 *  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.
 */

#include "modules/video_coding/timing/frame_delay_variation_kalman_filter.h"

#include "test/gtest.h"

namespace webrtc {
namespace {

// This test verifies that the initial filter state (link bandwidth, link
// propagation delay) is such that a frame of size zero would take no time to
// propagate.
TEST(FrameDelayVariationKalmanFilterTest,
     InitializedFilterWithZeroSizeFrameTakesNoTimeToPropagate) {
  FrameDelayVariationKalmanFilter filter;

  // A zero-sized frame...
  double frame_size_variation_bytes = 0.0;

  // ...should take no time to propagate due to it's size...
  EXPECT_EQ(filter.GetFrameDelayVariationEstimateSizeBased(
                frame_size_variation_bytes),
            0.0);

  // ...and no time due to the initial link propagation delay being zero.
  EXPECT_EQ(
      filter.GetFrameDelayVariationEstimateTotal(frame_size_variation_bytes),
      0.0);
}

// TODO(brandtr): Look into if there is a factor 1000 missing here? It seems
// unreasonable to have an initial link bandwidth of 512 _mega_bits per second?
TEST(FrameDelayVariationKalmanFilterTest,
     InitializedFilterWithSmallSizeFrameTakesFixedTimeToPropagate) {
  FrameDelayVariationKalmanFilter filter;

  // A 1000-byte frame...
  double frame_size_variation_bytes = 1000.0;
  // ...should take around `1000.0 / (512e3 / 8.0) = 0.015625 ms` to transmit.
  double expected_frame_delay_variation_estimate_ms = 1000.0 / (512e3 / 8.0);

  EXPECT_EQ(filter.GetFrameDelayVariationEstimateSizeBased(
                frame_size_variation_bytes),
            expected_frame_delay_variation_estimate_ms);
  EXPECT_EQ(
      filter.GetFrameDelayVariationEstimateTotal(frame_size_variation_bytes),
      expected_frame_delay_variation_estimate_ms);
}

TEST(FrameDelayVariationKalmanFilterTest,
     NegativeNoiseVarianceDoesNotUpdateFilter) {
  FrameDelayVariationKalmanFilter filter;

  // Negative variance...
  double var_noise = -0.1;
  filter.PredictAndUpdate(/*frame_delay_variation_ms=*/3,
                          /*frame_size_variation_bytes=*/200.0,
                          /*max_frame_size_bytes=*/2000, var_noise);

  // ...does _not_ update the filter.
  EXPECT_EQ(filter.GetFrameDelayVariationEstimateTotal(
                /*frame_size_variation_bytes=*/0.0),
            0.0);

  // Positive variance...
  var_noise = 0.1;
  filter.PredictAndUpdate(/*frame_delay_variation_ms=*/3,
                          /*frame_size_variation_bytes=*/200.0,
                          /*max_frame_size_bytes=*/2000, var_noise);

  // ...does update the filter.
  EXPECT_GT(filter.GetFrameDelayVariationEstimateTotal(
                /*frame_size_variation_bytes=*/0.0),
            0.0);
}

TEST(FrameDelayVariationKalmanFilterTest,
     VerifyConvergenceWithAlternatingDeviations) {
  FrameDelayVariationKalmanFilter filter;

  // One frame every 33 ms.
  int framerate_fps = 30;
  // Let's assume approximately 10% delay variation.
  double frame_delay_variation_ms = 3;
  // With a bitrate of 512 kbps, each frame will be around 2000 bytes.
  double max_frame_size_bytes = 2000;
  // And again, let's assume 10% size deviation.
  double frame_size_variation_bytes = 200;
  double var_noise = 0.1;
  int test_duration_s = 60;

  for (int i = 0; i < test_duration_s * framerate_fps; ++i) {
    // For simplicity, assume alternating variations.
    double sign = (i % 2 == 0) ? 1.0 : -1.0;
    filter.PredictAndUpdate(sign * frame_delay_variation_ms,
                            sign * frame_size_variation_bytes,
                            max_frame_size_bytes, var_noise);
  }

  // Verify that the filter has converged within a margin of 0.1 ms.
  EXPECT_NEAR(
      filter.GetFrameDelayVariationEstimateTotal(frame_size_variation_bytes),
      frame_delay_variation_ms, 0.1);
}

}  // namespace
}  // namespace webrtc