18fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org/*  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
28fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org *
38fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org *  Use of this source code is governed by a BSD-style license
48fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org *  that can be found in the LICENSE file in the root of the source
58fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org *  tree. An additional intellectual property rights grant can be found
68fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org *  in the file PATENTS.  All contributing project authors may
78fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org *  be found in the AUTHORS file in the root of the source tree.
88fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org */
98fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
108fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org#include "webrtc/modules/video_coding/main/source/jitter_estimator.h"
118fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
128fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org#include "testing/gtest/include/gtest/gtest.h"
138fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org#include "webrtc/system_wrappers/interface/clock.h"
148fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
158fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgnamespace webrtc {
168fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
178fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgclass TestEstimator : public VCMJitterEstimator {
188fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org public:
198fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  explicit TestEstimator(bool exp_enabled)
208fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      : VCMJitterEstimator(&fake_clock_, 0, 0),
218fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org        fake_clock_(0),
228fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org        exp_enabled_(exp_enabled) {}
238fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
248fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  virtual bool LowRateExperimentEnabled() { return exp_enabled_; }
258fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
268fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  void AdvanceClock(int64_t microseconds) {
278fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    fake_clock_.AdvanceTimeMicroseconds(microseconds);
288fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  }
298fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
308fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org private:
318fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  SimulatedClock fake_clock_;
328fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  const bool exp_enabled_;
338fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org};
348fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
358fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgclass TestVCMJitterEstimator : public ::testing::Test {
368fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org protected:
378fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  TestVCMJitterEstimator()
388fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      : regular_estimator_(false), low_rate_estimator_(true) {}
398fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
408fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  virtual void SetUp() { regular_estimator_.Reset(); }
418fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
428fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  TestEstimator regular_estimator_;
438fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  TestEstimator low_rate_estimator_;
448fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org};
458fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
468fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// Generates some simple test data in the form of a sawtooth wave.
478fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgclass ValueGenerator {
488fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org public:
498fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  ValueGenerator(int32_t amplitude) : amplitude_(amplitude), counter_(0) {}
508fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  virtual ~ValueGenerator() {}
518fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
528fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  int64_t Delay() { return ((counter_ % 11) - 5) * amplitude_; }
538fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
548fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  uint32_t FrameSize() { return 1000 + Delay(); }
558fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
568fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  void Advance() { ++counter_; }
578fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
588fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org private:
598fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  const int32_t amplitude_;
608fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  int64_t counter_;
618fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org};
628fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
638fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// 5 fps, disable jitter delay altogether.
648fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgTEST_F(TestVCMJitterEstimator, TestLowRate) {
658fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  ValueGenerator gen(10);
668fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  uint64_t time_delta = 1000000 / 5;
678fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  for (int i = 0; i < 60; ++i) {
688fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
698fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.AdvanceClock(time_delta);
708fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
718fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.AdvanceClock(time_delta);
728fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0);
738fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    if (i > 2)
748fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      EXPECT_EQ(low_rate_estimator_.GetJitterEstimate(0), 0);
758fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    gen.Advance();
768fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  }
778fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org}
788fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
798fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// 8 fps, steady state estimate should be in interpolated interval between 0
808fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// and value of previous method.
818fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgTEST_F(TestVCMJitterEstimator, TestMidRate) {
828fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  ValueGenerator gen(10);
838fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  uint64_t time_delta = 1000000 / 8;
848fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  for (int i = 0; i < 60; ++i) {
858fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
868fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.AdvanceClock(time_delta);
878fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
888fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.AdvanceClock(time_delta);
898fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    EXPECT_GT(regular_estimator_.GetJitterEstimate(0), 0);
908fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    EXPECT_GT(low_rate_estimator_.GetJitterEstimate(0), 0);
918fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    EXPECT_GE(regular_estimator_.GetJitterEstimate(0),
928fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org              low_rate_estimator_.GetJitterEstimate(0));
938fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    gen.Advance();
948fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  }
958fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org}
968fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
978fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// 30 fps, steady state estimate should be same as previous method.
988fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgTEST_F(TestVCMJitterEstimator, TestHighRate) {
998fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  ValueGenerator gen(10);
1008fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  uint64_t time_delta = 1000000 / 30;
1018fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  for (int i = 0; i < 60; ++i) {
1028fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
1038fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.AdvanceClock(time_delta);
1048fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
1058fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.AdvanceClock(time_delta);
1068fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    EXPECT_EQ(regular_estimator_.GetJitterEstimate(0),
1078fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org              low_rate_estimator_.GetJitterEstimate(0));
1088fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    gen.Advance();
1098fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  }
1108fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org}
1118fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1128fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// 10 fps, high jitter then low jitter. Low rate estimator should converge
1138fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org// faster to low noise estimate.
1148fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.orgTEST_F(TestVCMJitterEstimator, TestConvergence) {
1158fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  // Reach a steady state with high noise.
1168fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  ValueGenerator gen(50);
1178fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  uint64_t time_delta = 1000000 / 10;
1188fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  for (int i = 0; i < 100; ++i) {
1198fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
1208fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    regular_estimator_.AdvanceClock(time_delta * 2);
1218fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.UpdateEstimate(gen.Delay(), gen.FrameSize());
1228fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    low_rate_estimator_.AdvanceClock(time_delta * 2);
1238fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    gen.Advance();
1248fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  }
1258fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1268fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  int threshold = regular_estimator_.GetJitterEstimate(0) / 2;
1278fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1288fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  // New generator with zero noise.
1298fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  ValueGenerator low_gen(0);
1308fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  int regular_iterations = 0;
1318fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  int low_rate_iterations = 0;
1328fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  for (int i = 0; i < 500; ++i) {
1338fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    if (regular_iterations == 0) {
1348fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      regular_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize());
1358fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      regular_estimator_.AdvanceClock(time_delta);
1368fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      if (regular_estimator_.GetJitterEstimate(0) < threshold) {
1378fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org        regular_iterations = i;
1388fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      }
1398fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    }
1408fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1418fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    if (low_rate_iterations == 0) {
1428fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      low_rate_estimator_.UpdateEstimate(low_gen.Delay(), low_gen.FrameSize());
1438fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      low_rate_estimator_.AdvanceClock(time_delta);
1448fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      if (low_rate_estimator_.GetJitterEstimate(0) < threshold) {
1458fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org        low_rate_iterations = i;
1468fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      }
1478fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    }
1488fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1498fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    if (regular_iterations != 0 && low_rate_iterations != 0) {
1508fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org      break;
1518fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    }
1528fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1538fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org    gen.Advance();
1548fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  }
1558fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org
1568fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  EXPECT_NE(regular_iterations, 0);
1578fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  EXPECT_NE(low_rate_iterations, 0);
1588fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org  EXPECT_LE(low_rate_iterations, regular_iterations);
1598fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org}
1608fa619d50b6e966389da02c45df23ce1a68089cbsprang@webrtc.org}
161