Home | History | Annotate | Download | only in video_coding
      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/jitter_estimator.h"
     11 
     12 #include "testing/gtest/include/gtest/gtest.h"
     13 #include "webrtc/system_wrappers/include/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