blob: 04480a7c2f8ed97273d3810061617b74e95bbb71 [file] [log] [blame]
sprang@webrtc.org70e2d112014-09-24 14:06:56 +00001/* Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
2 *
3 * Use of this source code is governed by a BSD-style license
4 * that can be found in the LICENSE file in the root of the source
5 * tree. An additional intellectual property rights grant can be found
6 * in the file PATENTS. All contributing project authors may
7 * be found in the AUTHORS file in the root of the source tree.
8 */
9
Henrik Kjellander2557b862015-11-18 22:00:21 +010010#include "webrtc/modules/video_coding/jitter_estimator.h"
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000011
Henrik Kjellander98f53512015-10-28 18:17:40 +010012#include "webrtc/system_wrappers/include/clock.h"
kwibergac9f8762016-09-30 22:29:43 -070013#include "webrtc/test/gtest.h"
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000014
15namespace webrtc {
16
17class TestEstimator : public VCMJitterEstimator {
18 public:
19 explicit TestEstimator(bool exp_enabled)
20 : VCMJitterEstimator(&fake_clock_, 0, 0),
21 fake_clock_(0),
22 exp_enabled_(exp_enabled) {}
23
24 virtual bool LowRateExperimentEnabled() { return exp_enabled_; }
25
26 void AdvanceClock(int64_t microseconds) {
27 fake_clock_.AdvanceTimeMicroseconds(microseconds);
28 }
29
30 private:
31 SimulatedClock fake_clock_;
32 const bool exp_enabled_;
33};
34
35class TestVCMJitterEstimator : public ::testing::Test {
36 protected:
37 TestVCMJitterEstimator()
38 : regular_estimator_(false), low_rate_estimator_(true) {}
39
40 virtual void SetUp() { regular_estimator_.Reset(); }
41
42 TestEstimator regular_estimator_;
43 TestEstimator low_rate_estimator_;
44};
45
46// Generates some simple test data in the form of a sawtooth wave.
47class ValueGenerator {
48 public:
oprypin60c56682017-03-24 03:22:49 -070049 explicit ValueGenerator(int32_t amplitude)
50 : amplitude_(amplitude), counter_(0) {}
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000051 virtual ~ValueGenerator() {}
52
53 int64_t Delay() { return ((counter_ % 11) - 5) * amplitude_; }
54
55 uint32_t FrameSize() { return 1000 + Delay(); }
56
57 void Advance() { ++counter_; }
58
59 private:
60 const int32_t amplitude_;
61 int64_t counter_;
62};
63
64// 5 fps, disable jitter delay altogether.
65TEST_F(TestVCMJitterEstimator, TestLowRate) {
66 ValueGenerator gen(10);
67 uint64_t time_delta = 1000000 / 5;
68 for (int i = 0; i < 60; ++i) {
69 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
70 regular_estimator_.AdvanceClock(time_delta);
71 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
72 low_rate_estimator_.AdvanceClock(time_delta);
73 EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0);
74 if (i > 2)
75 EXPECT_EQ(low_rate_estimator_.GetJitterEstimate(0), 0);
76 gen.Advance();
77 }
78}
79
80// 8 fps, steady state estimate should be in interpolated interval between 0
81// and value of previous method.
82TEST_F(TestVCMJitterEstimator, TestMidRate) {
83 ValueGenerator gen(10);
84 uint64_t time_delta = 1000000 / 8;
85 for (int i = 0; i < 60; ++i) {
86 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
87 regular_estimator_.AdvanceClock(time_delta);
88 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
89 low_rate_estimator_.AdvanceClock(time_delta);
90 EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0);
91 EXPECT_GT(low_rate_estimator_.GetJitterEstimate(0), 0);
92 EXPECT_GE(regular_estimator_.GetJitterEstimate(0),
93 low_rate_estimator_.GetJitterEstimate(0));
94 gen.Advance();
95 }
96}
97
98// 30 fps, steady state estimate should be same as previous method.
99TEST_F(TestVCMJitterEstimator, TestHighRate) {
100 ValueGenerator gen(10);
101 uint64_t time_delta = 1000000 / 30;
102 for (int i = 0; i < 60; ++i) {
103 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
104 regular_estimator_.AdvanceClock(time_delta);
105 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
106 low_rate_estimator_.AdvanceClock(time_delta);
107 EXPECT_EQ(regular_estimator_.GetJitterEstimate(0),
108 low_rate_estimator_.GetJitterEstimate(0));
109 gen.Advance();
110 }
111}
112
113// 10 fps, high jitter then low jitter. Low rate estimator should converge
114// faster to low noise estimate.
115TEST_F(TestVCMJitterEstimator, TestConvergence) {
116 // Reach a steady state with high noise.
117 ValueGenerator gen(50);
118 uint64_t time_delta = 1000000 / 10;
119 for (int i = 0; i < 100; ++i) {
120 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
121 regular_estimator_.AdvanceClock(time_delta * 2);
122 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
123 low_rate_estimator_.AdvanceClock(time_delta * 2);
124 gen.Advance();
125 }
126
127 int threshold = regular_estimator_.GetJitterEstimate(0) / 2;
128
129 // New generator with zero noise.
130 ValueGenerator low_gen(0);
131 int regular_iterations = 0;
132 int low_rate_iterations = 0;
133 for (int i = 0; i < 500; ++i) {
134 if (regular_iterations == 0) {
135 regular_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize());
136 regular_estimator_.AdvanceClock(time_delta);
137 if (regular_estimator_.GetJitterEstimate(0) < threshold) {
138 regular_iterations = i;
139 }
140 }
141
142 if (low_rate_iterations == 0) {
143 low_rate_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize());
144 low_rate_estimator_.AdvanceClock(time_delta);
145 if (low_rate_estimator_.GetJitterEstimate(0) < threshold) {
146 low_rate_iterations = i;
147 }
148 }
149
150 if (regular_iterations != 0 && low_rate_iterations != 0) {
151 break;
152 }
153
154 gen.Advance();
155 }
156
157 EXPECT_NE(regular_iterations, 0);
158 EXPECT_NE(low_rate_iterations, 0);
159 EXPECT_LE(low_rate_iterations, regular_iterations);
160}
oprypin60c56682017-03-24 03:22:49 -0700161} // namespace webrtc