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
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:
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.
64TEST_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.
81TEST_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.
98TEST_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.
114TEST_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