/* * 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/frame_delay_variation_kalman_filter.h" #include "test/gtest.h" namespace webrtc { namespace { // This test verifies that the initial filter state (link bandwidth, link // propagation delay) is such that a frame of size zero would take no time to // propagate. TEST(FrameDelayVariationKalmanFilterTest, InitializedFilterWithZeroSizeFrameTakesNoTimeToPropagate) { FrameDelayVariationKalmanFilter filter; // A zero-sized frame... double frame_size_variation_bytes = 0.0; // ...should take no time to propagate due to it's size... EXPECT_EQ(filter.GetFrameDelayVariationEstimateSizeBased( frame_size_variation_bytes), 0.0); // ...and no time due to the initial link propagation delay being zero. EXPECT_EQ( filter.GetFrameDelayVariationEstimateTotal(frame_size_variation_bytes), 0.0); } // TODO(brandtr): Look into if there is a factor 1000 missing here? It seems // unreasonable to have an initial link bandwidth of 512 _mega_bits per second? TEST(FrameDelayVariationKalmanFilterTest, InitializedFilterWithSmallSizeFrameTakesFixedTimeToPropagate) { FrameDelayVariationKalmanFilter filter; // A 1000-byte frame... double frame_size_variation_bytes = 1000.0; // ...should take around `1000.0 / (512e3 / 8.0) = 0.015625 ms` to transmit. double expected_frame_delay_variation_estimate_ms = 1000.0 / (512e3 / 8.0); EXPECT_EQ(filter.GetFrameDelayVariationEstimateSizeBased( frame_size_variation_bytes), expected_frame_delay_variation_estimate_ms); EXPECT_EQ( filter.GetFrameDelayVariationEstimateTotal(frame_size_variation_bytes), expected_frame_delay_variation_estimate_ms); } TEST(FrameDelayVariationKalmanFilterTest, NegativeNoiseVarianceDoesNotUpdateFilter) { FrameDelayVariationKalmanFilter filter; // Negative variance... double var_noise = -0.1; filter.PredictAndUpdate(/*frame_delay_variation_ms=*/3, /*frame_size_variation_bytes=*/200.0, /*max_frame_size_bytes=*/2000, var_noise); // ...does _not_ update the filter. EXPECT_EQ(filter.GetFrameDelayVariationEstimateTotal( /*frame_size_variation_bytes=*/0.0), 0.0); // Positive variance... var_noise = 0.1; filter.PredictAndUpdate(/*frame_delay_variation_ms=*/3, /*frame_size_variation_bytes=*/200.0, /*max_frame_size_bytes=*/2000, var_noise); // ...does update the filter. EXPECT_GT(filter.GetFrameDelayVariationEstimateTotal( /*frame_size_variation_bytes=*/0.0), 0.0); } TEST(FrameDelayVariationKalmanFilterTest, VerifyConvergenceWithAlternatingDeviations) { FrameDelayVariationKalmanFilter filter; // One frame every 33 ms. int framerate_fps = 30; // Let's assume approximately 10% delay variation. double frame_delay_variation_ms = 3; // With a bitrate of 512 kbps, each frame will be around 2000 bytes. double max_frame_size_bytes = 2000; // And again, let's assume 10% size deviation. double frame_size_variation_bytes = 200; double var_noise = 0.1; int test_duration_s = 60; for (int i = 0; i < test_duration_s * framerate_fps; ++i) { // For simplicity, assume alternating variations. double sign = (i % 2 == 0) ? 1.0 : -1.0; filter.PredictAndUpdate(sign * frame_delay_variation_ms, sign * frame_size_variation_bytes, max_frame_size_bytes, var_noise); } // Verify that the filter has converged within a margin of 0.1 ms. EXPECT_NEAR( filter.GetFrameDelayVariationEstimateTotal(frame_size_variation_bytes), frame_delay_variation_ms, 0.1); } } // namespace } // namespace webrtc