1 /* 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 10 #include "webrtc/modules/video_coding/main/source/jitter_estimator.h" 11 12 #include "testing/gtest/include/gtest/gtest.h" 13 #include "webrtc/system_wrappers/interface/clock.h" 14 15 namespace webrtc { 16 17 class 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 35 class 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. 47 class ValueGenerator { 48 public: 49 ValueGenerator(int32_t amplitude) : amplitude_(amplitude), counter_(0) {} 50 virtual ~ValueGenerator() {} 51 52 int64_t Delay() { return ((counter_ % 11) - 5) * amplitude_; } 53 54 uint32_t FrameSize() { return 1000 + Delay(); } 55 56 void Advance() { ++counter_; } 57 58 private: 59 const int32_t amplitude_; 60 int64_t counter_; 61 }; 62 63 // 5 fps, disable jitter delay altogether. 64 TEST_F(TestVCMJitterEstimator, TestLowRate) { 65 ValueGenerator gen(10); 66 uint64_t time_delta = 1000000 / 5; 67 for (int i = 0; i < 60; ++i) { 68 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 69 regular_estimator_.AdvanceClock(time_delta); 70 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 71 low_rate_estimator_.AdvanceClock(time_delta); 72 EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0); 73 if (i > 2) 74 EXPECT_EQ(low_rate_estimator_.GetJitterEstimate(0), 0); 75 gen.Advance(); 76 } 77 } 78 79 // 8 fps, steady state estimate should be in interpolated interval between 0 80 // and value of previous method. 81 TEST_F(TestVCMJitterEstimator, TestMidRate) { 82 ValueGenerator gen(10); 83 uint64_t time_delta = 1000000 / 8; 84 for (int i = 0; i < 60; ++i) { 85 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 86 regular_estimator_.AdvanceClock(time_delta); 87 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 88 low_rate_estimator_.AdvanceClock(time_delta); 89 EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0); 90 EXPECT_GT(low_rate_estimator_.GetJitterEstimate(0), 0); 91 EXPECT_GE(regular_estimator_.GetJitterEstimate(0), 92 low_rate_estimator_.GetJitterEstimate(0)); 93 gen.Advance(); 94 } 95 } 96 97 // 30 fps, steady state estimate should be same as previous method. 98 TEST_F(TestVCMJitterEstimator, TestHighRate) { 99 ValueGenerator gen(10); 100 uint64_t time_delta = 1000000 / 30; 101 for (int i = 0; i < 60; ++i) { 102 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 103 regular_estimator_.AdvanceClock(time_delta); 104 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 105 low_rate_estimator_.AdvanceClock(time_delta); 106 EXPECT_EQ(regular_estimator_.GetJitterEstimate(0), 107 low_rate_estimator_.GetJitterEstimate(0)); 108 gen.Advance(); 109 } 110 } 111 112 // 10 fps, high jitter then low jitter. Low rate estimator should converge 113 // faster to low noise estimate. 114 TEST_F(TestVCMJitterEstimator, TestConvergence) { 115 // Reach a steady state with high noise. 116 ValueGenerator gen(50); 117 uint64_t time_delta = 1000000 / 10; 118 for (int i = 0; i < 100; ++i) { 119 regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 120 regular_estimator_.AdvanceClock(time_delta * 2); 121 low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); 122 low_rate_estimator_.AdvanceClock(time_delta * 2); 123 gen.Advance(); 124 } 125 126 int threshold = regular_estimator_.GetJitterEstimate(0) / 2; 127 128 // New generator with zero noise. 129 ValueGenerator low_gen(0); 130 int regular_iterations = 0; 131 int low_rate_iterations = 0; 132 for (int i = 0; i < 500; ++i) { 133 if (regular_iterations == 0) { 134 regular_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize()); 135 regular_estimator_.AdvanceClock(time_delta); 136 if (regular_estimator_.GetJitterEstimate(0) < threshold) { 137 regular_iterations = i; 138 } 139 } 140 141 if (low_rate_iterations == 0) { 142 low_rate_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize()); 143 low_rate_estimator_.AdvanceClock(time_delta); 144 if (low_rate_estimator_.GetJitterEstimate(0) < threshold) { 145 low_rate_iterations = i; 146 } 147 } 148 149 if (regular_iterations != 0 && low_rate_iterations != 0) { 150 break; 151 } 152 153 gen.Advance(); 154 } 155 156 EXPECT_NE(regular_iterations, 0); 157 EXPECT_NE(low_rate_iterations, 0); 158 EXPECT_LE(low_rate_iterations, regular_iterations); 159 } 160 } 161