blob: 05502e6f5b1579e2d2835b3653ec695c9068d1eb [file] [log] [blame]
/*
* Copyright (c) 2022 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 "modules/video_coding/timing/rtt_filter.h"
#include "api/units/time_delta.h"
#include "test/gmock.h"
#include "test/gtest.h"
namespace webrtc {
TEST(RttFilterTest, RttIsCapped) {
RttFilter rtt_filter;
rtt_filter.Update(TimeDelta::Seconds(500));
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Seconds(3));
}
// If the difference between samples is more than away 2.5 stddev from the mean
// then this is considered a jump. After more than 5 data points at the new
// level, the RTT is reset to the new level.
TEST(RttFilterTest, PositiveJumpDetection) {
RttFilter rtt_filter;
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
// Trigger 5 jumps.
rtt_filter.Update(TimeDelta::Millis(1400));
rtt_filter.Update(TimeDelta::Millis(1500));
rtt_filter.Update(TimeDelta::Millis(1600));
rtt_filter.Update(TimeDelta::Millis(1600));
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Millis(1600));
rtt_filter.Update(TimeDelta::Millis(1600));
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Millis(1600));
}
TEST(RttFilterTest, NegativeJumpDetection) {
RttFilter rtt_filter;
for (int i = 0; i < 10; ++i)
rtt_filter.Update(TimeDelta::Millis(1500));
// Trigger 5 negative data points that jump rtt down.
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
// Before 5 data points at the new level, max RTT is still 1500.
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Millis(1500));
rtt_filter.Update(TimeDelta::Millis(300));
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Millis(300));
}
TEST(RttFilterTest, JumpsResetByDirectionShift) {
RttFilter rtt_filter;
for (int i = 0; i < 10; ++i)
rtt_filter.Update(TimeDelta::Millis(1500));
// Trigger 4 negative jumps, then a positive one. This resets the jump
// detection.
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(200));
rtt_filter.Update(TimeDelta::Millis(2000));
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Millis(2000));
rtt_filter.Update(TimeDelta::Millis(300));
EXPECT_EQ(rtt_filter.Rtt(), TimeDelta::Millis(2000));
}
// If the difference between the max and average is more than 3.5 stddevs away
// then a drift is detected, and a short filter is applied to find a new max
// rtt.
TEST(RttFilterTest, DriftDetection) {
RttFilter rtt_filter;
// Descend RTT by 30ms and settle at 700ms RTT. A drift is detected after rtt
// of 700ms is reported around 50 times for these targets.
constexpr TimeDelta kStartRtt = TimeDelta::Millis(1000);
constexpr TimeDelta kDriftTarget = TimeDelta::Millis(700);
constexpr TimeDelta kDelta = TimeDelta::Millis(30);
for (TimeDelta rtt = kStartRtt; rtt >= kDriftTarget; rtt -= kDelta)
rtt_filter.Update(rtt);
EXPECT_EQ(rtt_filter.Rtt(), kStartRtt);
for (int i = 0; i < 50; ++i)
rtt_filter.Update(kDriftTarget);
EXPECT_EQ(rtt_filter.Rtt(), kDriftTarget);
}
} // namespace webrtc