blob: 45262ef83602e7c15e2a9cf3b9e8066f35a92764 [file] [log] [blame]
sprang@webrtc.org70e2d112014-09-24 14:06:56 +00001/* 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
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "modules/video_coding/jitter_estimator.h"
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000011
Erik Språngb1e031a2018-11-01 11:20:49 +010012#include "rtc_base/experiments/jitter_upper_bound_experiment.h"
13#include "rtc_base/logging.h"
14#include "rtc_base/numerics/histogram_percentile_counter.h"
15#include "rtc_base/timeutils.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020016#include "system_wrappers/include/clock.h"
Erik Språngb1e031a2018-11-01 11:20:49 +010017#include "test/field_trial.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020018#include "test/gtest.h"
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000019
20namespace webrtc {
21
Erik Språngb1e031a2018-11-01 11:20:49 +010022class TestVCMJitterEstimator : public ::testing::Test {
23 protected:
24 TestVCMJitterEstimator() : fake_clock_(0) {}
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000025
Erik Språngb1e031a2018-11-01 11:20:49 +010026 virtual void SetUp() {
27 estimator_ = absl::make_unique<VCMJitterEstimator>(&fake_clock_, 0, 0);
28 }
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000029
30 void AdvanceClock(int64_t microseconds) {
31 fake_clock_.AdvanceTimeMicroseconds(microseconds);
32 }
33
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000034 SimulatedClock fake_clock_;
Erik Språngb1e031a2018-11-01 11:20:49 +010035 std::unique_ptr<VCMJitterEstimator> estimator_;
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000036};
37
38// Generates some simple test data in the form of a sawtooth wave.
39class ValueGenerator {
40 public:
oprypin60c56682017-03-24 03:22:49 -070041 explicit ValueGenerator(int32_t amplitude)
42 : amplitude_(amplitude), counter_(0) {}
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000043 virtual ~ValueGenerator() {}
44
45 int64_t Delay() { return ((counter_ % 11) - 5) * amplitude_; }
46
47 uint32_t FrameSize() { return 1000 + Delay(); }
48
49 void Advance() { ++counter_; }
50
51 private:
52 const int32_t amplitude_;
53 int64_t counter_;
54};
55
56// 5 fps, disable jitter delay altogether.
57TEST_F(TestVCMJitterEstimator, TestLowRate) {
58 ValueGenerator gen(10);
Erik Språngb1e031a2018-11-01 11:20:49 +010059 uint64_t time_delta_us = rtc::kNumMicrosecsPerSec / 5;
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000060 for (int i = 0; i < 60; ++i) {
Erik Språngb1e031a2018-11-01 11:20:49 +010061 estimator_->UpdateEstimate(gen.Delay(), gen.FrameSize());
62 AdvanceClock(time_delta_us);
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000063 if (i > 2)
Erik Språngb1e031a2018-11-01 11:20:49 +010064 EXPECT_EQ(estimator_->GetJitterEstimate(0), 0);
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000065 gen.Advance();
66 }
67}
68
Erik Språngb1e031a2018-11-01 11:20:49 +010069TEST_F(TestVCMJitterEstimator, TestUpperBound) {
70 struct TestContext {
71 TestContext() : upper_bound(0.0), percentiles(1000) {}
72 double upper_bound;
73 rtc::HistogramPercentileCounter percentiles;
74 };
75 std::vector<TestContext> test_cases(2);
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000076
Erik Språngb1e031a2018-11-01 11:20:49 +010077 test_cases[0].upper_bound = 100.0; // First use essentially no cap.
78 test_cases[1].upper_bound = 3.5; // Second, reasonably small cap.
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000079
Erik Språngb1e031a2018-11-01 11:20:49 +010080 for (TestContext& context : test_cases) {
81 // Set up field trial and reset jitter estimator.
82 char string_buf[64];
83 rtc::SimpleStringBuilder ssb(string_buf);
84 ssb << JitterUpperBoundExperiment::kJitterUpperBoundExperimentName
85 << "/Enabled-" << context.upper_bound << "/";
86 test::ScopedFieldTrials field_trials(ssb.str());
87 SetUp();
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000088
Erik Språngb1e031a2018-11-01 11:20:49 +010089 ValueGenerator gen(50);
90 uint64_t time_delta_us = rtc::kNumMicrosecsPerSec / 30;
91 for (int i = 0; i < 100; ++i) {
92 estimator_->UpdateEstimate(gen.Delay(), gen.FrameSize());
93 AdvanceClock(time_delta_us);
94 context.percentiles.Add(
95 static_cast<uint32_t>(estimator_->GetJitterEstimate(0)));
96 gen.Advance();
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000097 }
sprang@webrtc.org70e2d112014-09-24 14:06:56 +000098 }
99
Erik Språngb1e031a2018-11-01 11:20:49 +0100100 // Median should be similar after three seconds. Allow 5% error margin.
101 uint32_t median_unbound = *test_cases[0].percentiles.GetPercentile(0.5);
102 uint32_t median_bounded = *test_cases[1].percentiles.GetPercentile(0.5);
103 EXPECT_NEAR(median_unbound, median_bounded, (median_unbound * 5) / 100);
104
105 // Max should be lower for the bounded case.
106 uint32_t max_unbound = *test_cases[0].percentiles.GetPercentile(1.0);
107 uint32_t max_bounded = *test_cases[1].percentiles.GetPercentile(1.0);
108 EXPECT_GT(max_unbound, static_cast<uint32_t>(max_bounded * 1.25));
sprang@webrtc.org70e2d112014-09-24 14:06:56 +0000109}
Erik Språngb1e031a2018-11-01 11:20:49 +0100110
oprypin60c56682017-03-24 03:22:49 -0700111} // namespace webrtc