|  | /*  Copyright (c) 2014 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 "webrtc/modules/video_coding/jitter_estimator.h" | 
|  |  | 
|  | #include "webrtc/system_wrappers/include/clock.h" | 
|  | #include "webrtc/test/gtest.h" | 
|  |  | 
|  | namespace webrtc { | 
|  |  | 
|  | class TestEstimator : public VCMJitterEstimator { | 
|  | public: | 
|  | explicit TestEstimator(bool exp_enabled) | 
|  | : VCMJitterEstimator(&fake_clock_, 0, 0), | 
|  | fake_clock_(0), | 
|  | exp_enabled_(exp_enabled) {} | 
|  |  | 
|  | virtual bool LowRateExperimentEnabled() { return exp_enabled_; } | 
|  |  | 
|  | void AdvanceClock(int64_t microseconds) { | 
|  | fake_clock_.AdvanceTimeMicroseconds(microseconds); | 
|  | } | 
|  |  | 
|  | private: | 
|  | SimulatedClock fake_clock_; | 
|  | const bool exp_enabled_; | 
|  | }; | 
|  |  | 
|  | class TestVCMJitterEstimator : public ::testing::Test { | 
|  | protected: | 
|  | TestVCMJitterEstimator() | 
|  | : regular_estimator_(false), low_rate_estimator_(true) {} | 
|  |  | 
|  | virtual void SetUp() { regular_estimator_.Reset(); } | 
|  |  | 
|  | TestEstimator regular_estimator_; | 
|  | TestEstimator low_rate_estimator_; | 
|  | }; | 
|  |  | 
|  | // Generates some simple test data in the form of a sawtooth wave. | 
|  | class ValueGenerator { | 
|  | public: | 
|  | ValueGenerator(int32_t amplitude) : amplitude_(amplitude), counter_(0) {} | 
|  | virtual ~ValueGenerator() {} | 
|  |  | 
|  | int64_t Delay() { return ((counter_ % 11) - 5) * amplitude_; } | 
|  |  | 
|  | uint32_t FrameSize() { return 1000 + Delay(); } | 
|  |  | 
|  | void Advance() { ++counter_; } | 
|  |  | 
|  | private: | 
|  | const int32_t amplitude_; | 
|  | int64_t counter_; | 
|  | }; | 
|  |  | 
|  | // 5 fps, disable jitter delay altogether. | 
|  | TEST_F(TestVCMJitterEstimator, TestLowRate) { | 
|  | ValueGenerator gen(10); | 
|  | uint64_t time_delta = 1000000 / 5; | 
|  | for (int i = 0; i < 60; ++i) { | 
|  | regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | regular_estimator_.AdvanceClock(time_delta); | 
|  | low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | low_rate_estimator_.AdvanceClock(time_delta); | 
|  | EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0); | 
|  | if (i > 2) | 
|  | EXPECT_EQ(low_rate_estimator_.GetJitterEstimate(0), 0); | 
|  | gen.Advance(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // 8 fps, steady state estimate should be in interpolated interval between 0 | 
|  | // and value of previous method. | 
|  | TEST_F(TestVCMJitterEstimator, TestMidRate) { | 
|  | ValueGenerator gen(10); | 
|  | uint64_t time_delta = 1000000 / 8; | 
|  | for (int i = 0; i < 60; ++i) { | 
|  | regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | regular_estimator_.AdvanceClock(time_delta); | 
|  | low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | low_rate_estimator_.AdvanceClock(time_delta); | 
|  | EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0); | 
|  | EXPECT_GT(low_rate_estimator_.GetJitterEstimate(0), 0); | 
|  | EXPECT_GE(regular_estimator_.GetJitterEstimate(0), | 
|  | low_rate_estimator_.GetJitterEstimate(0)); | 
|  | gen.Advance(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // 30 fps, steady state estimate should be same as previous method. | 
|  | TEST_F(TestVCMJitterEstimator, TestHighRate) { | 
|  | ValueGenerator gen(10); | 
|  | uint64_t time_delta = 1000000 / 30; | 
|  | for (int i = 0; i < 60; ++i) { | 
|  | regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | regular_estimator_.AdvanceClock(time_delta); | 
|  | low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | low_rate_estimator_.AdvanceClock(time_delta); | 
|  | EXPECT_EQ(regular_estimator_.GetJitterEstimate(0), | 
|  | low_rate_estimator_.GetJitterEstimate(0)); | 
|  | gen.Advance(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // 10 fps, high jitter then low jitter. Low rate estimator should converge | 
|  | // faster to low noise estimate. | 
|  | TEST_F(TestVCMJitterEstimator, TestConvergence) { | 
|  | // Reach a steady state with high noise. | 
|  | ValueGenerator gen(50); | 
|  | uint64_t time_delta = 1000000 / 10; | 
|  | for (int i = 0; i < 100; ++i) { | 
|  | regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | regular_estimator_.AdvanceClock(time_delta * 2); | 
|  | low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize()); | 
|  | low_rate_estimator_.AdvanceClock(time_delta * 2); | 
|  | gen.Advance(); | 
|  | } | 
|  |  | 
|  | int threshold = regular_estimator_.GetJitterEstimate(0) / 2; | 
|  |  | 
|  | // New generator with zero noise. | 
|  | ValueGenerator low_gen(0); | 
|  | int regular_iterations = 0; | 
|  | int low_rate_iterations = 0; | 
|  | for (int i = 0; i < 500; ++i) { | 
|  | if (regular_iterations == 0) { | 
|  | regular_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize()); | 
|  | regular_estimator_.AdvanceClock(time_delta); | 
|  | if (regular_estimator_.GetJitterEstimate(0) < threshold) { | 
|  | regular_iterations = i; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (low_rate_iterations == 0) { | 
|  | low_rate_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize()); | 
|  | low_rate_estimator_.AdvanceClock(time_delta); | 
|  | if (low_rate_estimator_.GetJitterEstimate(0) < threshold) { | 
|  | low_rate_iterations = i; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (regular_iterations != 0 && low_rate_iterations != 0) { | 
|  | break; | 
|  | } | 
|  |  | 
|  | gen.Advance(); | 
|  | } | 
|  |  | 
|  | EXPECT_NE(regular_iterations, 0); | 
|  | EXPECT_NE(low_rate_iterations, 0); | 
|  | EXPECT_LE(low_rate_iterations, regular_iterations); | 
|  | } | 
|  | } |