blob: 05334885f21864128a4ffc4b66795d96a8177e4c [file] [log] [blame]
/*
* Copyright 2021 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/congestion_controller/goog_cc/loss_based_bwe_v2.h"
#include <string>
#include "api/transport/network_types.h"
#include "api/units/data_rate.h"
#include "api/units/data_size.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/strings/string_builder.h"
#include "test/explicit_key_value_config.h"
#include "test/gtest.h"
namespace webrtc {
namespace {
using ::webrtc::test::ExplicitKeyValueConfig;
constexpr TimeDelta kObservationDurationLowerBound = TimeDelta::Millis(200);
std::string Config(bool enabled, bool valid) {
char buffer[1024];
rtc::SimpleStringBuilder config_string(buffer);
config_string << "WebRTC-Bwe-LossBasedBweV2/";
if (enabled) {
config_string << "Enabled:true";
} else {
config_string << "Enabled:false";
}
if (valid) {
config_string << ",BwRampupUpperBoundFactor:1.2";
} else {
config_string << ",BwRampupUpperBoundFactor:0.0";
}
config_string
<< ",CandidateFactors:0.9|1.1,HigherBwBiasFactor:0.01,"
"InherentLossLowerBound:0.001,InherentLossUpperBoundBwBalance:14kbps,"
"InherentLossUpperBoundOffset:0.9,InitialInherentLossEstimate:0.01,"
"NewtonIterations:2,NewtonStepSize:0.4,ObservationWindowSize:15,"
"SendingRateSmoothingFactor:0.01,"
"InstantUpperBoundTemporalWeightFactor:0.97,"
"InstantUpperBoundBwBalance:90kbps,"
"InstantUpperBoundLossOffset:0.1,TemporalWeightFactor:0.98";
config_string.AppendFormat(
",ObservationDurationLowerBound:%dms",
static_cast<int>(kObservationDurationLowerBound.ms()));
config_string << "/";
return config_string.str();
}
TEST(LossBasedBweV2Test, EnabledWhenGivenValidConfigurationValues) {
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
EXPECT_TRUE(loss_based_bandwidth_estimator.IsEnabled());
}
TEST(LossBasedBweV2Test, DisabledWhenGivenDisabledConfiguration) {
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/false, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
EXPECT_FALSE(loss_based_bandwidth_estimator.IsEnabled());
}
TEST(LossBasedBweV2Test, DisabledWhenGivenNonValidConfigurationValues) {
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/false));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
EXPECT_FALSE(loss_based_bandwidth_estimator.IsEnabled());
}
TEST(LossBasedBweV2Test, DisabledWhenGivenNonPositiveCandidateFactor) {
ExplicitKeyValueConfig key_value_config_negative_candidate_factor(
"WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:-1.3|1.1/");
LossBasedBweV2 loss_based_bandwidth_estimator_1(
&key_value_config_negative_candidate_factor);
EXPECT_FALSE(loss_based_bandwidth_estimator_1.IsEnabled());
ExplicitKeyValueConfig key_value_config_zero_candidate_factor(
"WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:0.0|1.1/");
LossBasedBweV2 loss_based_bandwidth_estimator_2(
&key_value_config_zero_candidate_factor);
EXPECT_FALSE(loss_based_bandwidth_estimator_2.IsEnabled());
}
TEST(LossBasedBweV2Test,
DisabledWhenGivenConfigurationThatDoesNotAllowGeneratingCandidates) {
ExplicitKeyValueConfig key_value_config(
"WebRTC-Bwe-LossBasedBweV2/"
"Enabled:true,CandidateFactors:1.0,AckedRateCandidate:false,"
"DelayBasedCandidate:false/");
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
EXPECT_FALSE(loss_based_bandwidth_estimator.IsEnabled());
}
TEST(LossBasedBweV2Test, BandwidthEstimateGivenInitializationAndThenFeedback) {
PacketResult enough_feedback[2];
enough_feedback[0].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback[1].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback[0].sent_packet.send_time = Timestamp::Zero();
enough_feedback[1].sent_packet.send_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback[0].receive_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback[1].receive_time =
Timestamp::Zero() + 2 * kObservationDurationLowerBound;
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback, DataRate::PlusInfinity());
EXPECT_TRUE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(loss_based_bandwidth_estimator.GetBandwidthEstimate().IsFinite());
}
TEST(LossBasedBweV2Test, NoBandwidthEstimateGivenNoInitialization) {
PacketResult enough_feedback[2];
enough_feedback[0].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback[1].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback[0].sent_packet.send_time = Timestamp::Zero();
enough_feedback[1].sent_packet.send_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback[0].receive_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback[1].receive_time =
Timestamp::Zero() + 2 * kObservationDurationLowerBound;
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback, DataRate::PlusInfinity());
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator.GetBandwidthEstimate().IsPlusInfinity());
}
TEST(LossBasedBweV2Test, NoBandwidthEstimateGivenNotEnoughFeedback) {
// Create packet results where the observation duration is less than the lower
// bound.
PacketResult not_enough_feedback[2];
not_enough_feedback[0].sent_packet.size = DataSize::Bytes(15'000);
not_enough_feedback[1].sent_packet.size = DataSize::Bytes(15'000);
not_enough_feedback[0].sent_packet.send_time = Timestamp::Zero();
not_enough_feedback[1].sent_packet.send_time =
Timestamp::Zero() + kObservationDurationLowerBound / 2;
not_enough_feedback[0].receive_time =
Timestamp::Zero() + kObservationDurationLowerBound / 2;
not_enough_feedback[1].receive_time =
Timestamp::Zero() + kObservationDurationLowerBound;
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator.GetBandwidthEstimate().IsPlusInfinity());
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
not_enough_feedback, DataRate::PlusInfinity());
EXPECT_FALSE(loss_based_bandwidth_estimator.IsReady());
EXPECT_TRUE(
loss_based_bandwidth_estimator.GetBandwidthEstimate().IsPlusInfinity());
}
TEST(LossBasedBweV2Test,
SetValueIsTheEstimateUntilAdditionalFeedbackHasBeenReceived) {
PacketResult enough_feedback_1[2];
PacketResult enough_feedback_2[2];
enough_feedback_1[0].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_1[1].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_2[0].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_2[1].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_1[0].sent_packet.send_time = Timestamp::Zero();
enough_feedback_1[1].sent_packet.send_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback_2[0].sent_packet.send_time =
Timestamp::Zero() + 2 * kObservationDurationLowerBound;
enough_feedback_2[1].sent_packet.send_time =
Timestamp::Zero() + 3 * kObservationDurationLowerBound;
enough_feedback_1[0].receive_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback_1[1].receive_time =
Timestamp::Zero() + 2 * kObservationDurationLowerBound;
enough_feedback_2[0].receive_time =
Timestamp::Zero() + 3 * kObservationDurationLowerBound;
enough_feedback_2[1].receive_time =
Timestamp::Zero() + 4 * kObservationDurationLowerBound;
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_1, DataRate::PlusInfinity());
EXPECT_NE(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_2, DataRate::PlusInfinity());
EXPECT_NE(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
DataRate::KilobitsPerSec(600));
}
TEST(LossBasedBweV2Test,
SetAcknowledgedBitrateOnlyAffectsTheBweWhenAdditionalFeedbackIsGiven) {
PacketResult enough_feedback_1[2];
PacketResult enough_feedback_2[2];
enough_feedback_1[0].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_1[1].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_2[0].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_2[1].sent_packet.size = DataSize::Bytes(15'000);
enough_feedback_1[0].sent_packet.send_time = Timestamp::Zero();
enough_feedback_1[1].sent_packet.send_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback_2[0].sent_packet.send_time =
Timestamp::Zero() + 2 * kObservationDurationLowerBound;
enough_feedback_2[1].sent_packet.send_time =
Timestamp::Zero() + 3 * kObservationDurationLowerBound;
enough_feedback_1[0].receive_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback_1[1].receive_time =
Timestamp::Zero() + 2 * kObservationDurationLowerBound;
enough_feedback_2[0].receive_time =
Timestamp::Zero() + 3 * kObservationDurationLowerBound;
enough_feedback_2[1].receive_time =
Timestamp::Zero() + 4 * kObservationDurationLowerBound;
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator_1(&key_value_config);
LossBasedBweV2 loss_based_bandwidth_estimator_2(&key_value_config);
loss_based_bandwidth_estimator_1.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator_2.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(
enough_feedback_1, DataRate::PlusInfinity());
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(
enough_feedback_1, DataRate::PlusInfinity());
EXPECT_EQ(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(),
DataRate::KilobitsPerSec(660));
loss_based_bandwidth_estimator_1.SetAcknowledgedBitrate(
DataRate::KilobitsPerSec(600));
EXPECT_EQ(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(),
DataRate::KilobitsPerSec(660));
loss_based_bandwidth_estimator_1.UpdateBandwidthEstimate(
enough_feedback_2, DataRate::PlusInfinity());
loss_based_bandwidth_estimator_2.UpdateBandwidthEstimate(
enough_feedback_2, DataRate::PlusInfinity());
EXPECT_NE(loss_based_bandwidth_estimator_1.GetBandwidthEstimate(),
loss_based_bandwidth_estimator_2.GetBandwidthEstimate());
}
TEST(LossBasedBweV2Test,
BandwidthEstimateIsCappedToBeTcpFairGivenTooHighLossRate) {
PacketResult enough_feedback_no_received_packets[2];
enough_feedback_no_received_packets[0].sent_packet.size =
DataSize::Bytes(15'000);
enough_feedback_no_received_packets[1].sent_packet.size =
DataSize::Bytes(15'000);
enough_feedback_no_received_packets[0].sent_packet.send_time =
Timestamp::Zero();
enough_feedback_no_received_packets[1].sent_packet.send_time =
Timestamp::Zero() + kObservationDurationLowerBound;
enough_feedback_no_received_packets[0].receive_time =
Timestamp::PlusInfinity();
enough_feedback_no_received_packets[1].receive_time =
Timestamp::PlusInfinity();
ExplicitKeyValueConfig key_value_config(
Config(/*enabled=*/true, /*valid=*/true));
LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config);
loss_based_bandwidth_estimator.SetBandwidthEstimate(
DataRate::KilobitsPerSec(600));
loss_based_bandwidth_estimator.UpdateBandwidthEstimate(
enough_feedback_no_received_packets, DataRate::PlusInfinity());
EXPECT_EQ(loss_based_bandwidth_estimator.GetBandwidthEstimate(),
DataRate::KilobitsPerSec(100));
}
} // namespace
} // namespace webrtc