Unittests for loss based bandwidth estimation.
Bug: none
Change-Id: I204071683c1c6e28040ea3bce900c4b04108cba7
Reviewed-on: https://webrtc-review.googlesource.com/c/112380
Commit-Queue: Christoffer Rodbro <crodbro@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25844}
diff --git a/modules/bitrate_controller/loss_based_bandwidth_estimation.cc b/modules/bitrate_controller/loss_based_bandwidth_estimation.cc
index 5d7f8aa..f22f970 100644
--- a/modules/bitrate_controller/loss_based_bandwidth_estimation.cc
+++ b/modules/bitrate_controller/loss_based_bandwidth_estimation.cc
@@ -156,9 +156,9 @@
if (acknowledged_bitrate > acknowledged_bitrate_max_) {
acknowledged_bitrate_max_ = acknowledged_bitrate;
} else {
- acknowledged_bitrate_max_ +=
+ acknowledged_bitrate_max_ -=
ExponentialUpdate(config_.acknowledged_rate_max_window, time_passed) *
- (acknowledged_bitrate - acknowledged_bitrate_max_);
+ (acknowledged_bitrate_max_ - acknowledged_bitrate);
}
}
diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
index fecd1b3..071fe09 100644
--- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
+++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc
@@ -28,6 +28,58 @@
const uint32_t kInitialBitrateKbps = 60;
const DataRate kInitialBitrate = DataRate::kbps(kInitialBitrateKbps);
const float kDefaultPacingRate = 2.5f;
+
+void UpdatesTargetRateBasedOnLinkCapacity(double loss_rate = 0.0) {
+ Scenario s("googcc_unit/target_capacity", false);
+ SimulatedTimeClientConfig config;
+ config.transport.cc =
+ TransportControllerConfig::CongestionController::kGoogCcFeedback;
+ config.transport.rates.min_rate = DataRate::kbps(10);
+ config.transport.rates.max_rate = DataRate::kbps(1500);
+ config.transport.rates.start_rate = DataRate::kbps(300);
+ NetworkNodeConfig net_conf;
+ auto send_net = s.CreateSimulationNode([loss_rate](NetworkNodeConfig* c) {
+ c->simulation.bandwidth = DataRate::kbps(500);
+ c->simulation.delay = TimeDelta::ms(100);
+ c->simulation.loss_rate = loss_rate;
+ c->update_frequency = TimeDelta::ms(5);
+ });
+ auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+ c->simulation.delay = TimeDelta::ms(100);
+ c->update_frequency = TimeDelta::ms(5);
+ });
+ StatesPrinter* truth = s.CreatePrinter(
+ "send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
+ SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
+ "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
+
+ truth->PrintRow();
+ s.RunFor(TimeDelta::seconds(25));
+ truth->PrintRow();
+ EXPECT_NEAR(client->target_rate_kbps(), 450, 100);
+
+ send_net->UpdateConfig([](NetworkNodeConfig* c) {
+ c->simulation.bandwidth = DataRate::kbps(800);
+ c->simulation.delay = TimeDelta::ms(100);
+ });
+
+ truth->PrintRow();
+ s.RunFor(TimeDelta::seconds(20));
+ truth->PrintRow();
+ EXPECT_NEAR(client->target_rate_kbps(), 750, 150);
+
+ send_net->UpdateConfig([](NetworkNodeConfig* c) {
+ c->simulation.bandwidth = DataRate::kbps(100);
+ c->simulation.delay = TimeDelta::ms(200);
+ });
+ ret_net->UpdateConfig(
+ [](NetworkNodeConfig* c) { c->simulation.delay = TimeDelta::ms(200); });
+
+ truth->PrintRow();
+ s.RunFor(TimeDelta::seconds(30));
+ truth->PrintRow();
+ EXPECT_NEAR(client->target_rate_kbps(), 90, 20);
+}
} // namespace
class GoogCcNetworkControllerTest : public ::testing::Test {
@@ -349,54 +401,7 @@
}
TEST_F(GoogCcNetworkControllerTest, UpdatesTargetRateBasedOnLinkCapacity) {
- Scenario s("googcc_unit/target_capacity", false);
- SimulatedTimeClientConfig config;
- config.transport.cc =
- TransportControllerConfig::CongestionController::kGoogCcFeedback;
- config.transport.rates.min_rate = DataRate::kbps(10);
- config.transport.rates.max_rate = DataRate::kbps(1500);
- config.transport.rates.start_rate = DataRate::kbps(300);
- NetworkNodeConfig net_conf;
- auto send_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
- c->simulation.bandwidth = DataRate::kbps(500);
- c->simulation.delay = TimeDelta::ms(100);
- c->update_frequency = TimeDelta::ms(5);
- });
- auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
- c->simulation.delay = TimeDelta::ms(100);
- c->update_frequency = TimeDelta::ms(5);
- });
- StatesPrinter* truth = s.CreatePrinter(
- "send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
- SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
- "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
-
- truth->PrintRow();
- s.RunFor(TimeDelta::seconds(25));
- truth->PrintRow();
- EXPECT_NEAR(client->target_rate_kbps(), 450, 100);
-
- send_net->UpdateConfig([](NetworkNodeConfig* c) {
- c->simulation.bandwidth = DataRate::kbps(800);
- c->simulation.delay = TimeDelta::ms(100);
- });
-
- truth->PrintRow();
- s.RunFor(TimeDelta::seconds(20));
- truth->PrintRow();
- EXPECT_NEAR(client->target_rate_kbps(), 750, 150);
-
- send_net->UpdateConfig([](NetworkNodeConfig* c) {
- c->simulation.bandwidth = DataRate::kbps(100);
- c->simulation.delay = TimeDelta::ms(200);
- });
- ret_net->UpdateConfig(
- [](NetworkNodeConfig* c) { c->simulation.delay = TimeDelta::ms(200); });
-
- truth->PrintRow();
- s.RunFor(TimeDelta::seconds(30));
- truth->PrintRow();
- EXPECT_NEAR(client->target_rate_kbps(), 90, 20);
+ UpdatesTargetRateBasedOnLinkCapacity();
}
TEST_F(GoogCcNetworkControllerTest, DefaultEstimateVariesInSteadyState) {
@@ -455,5 +460,68 @@
EXPECT_GT(min_estimate / max_estimate, 0.95);
}
+TEST_F(GoogCcNetworkControllerTest,
+ LossBasedControlUpdatesTargetRateBasedOnLinkCapacity) {
+ ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+ UpdatesTargetRateBasedOnLinkCapacity(/*loss_rate*/ 0.01);
+}
+
+TEST_F(GoogCcNetworkControllerTest,
+ LossBasedControlDoesModestBackoffToHighLoss) {
+ ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+ Scenario s("googcc_unit/high_loss_channel", false);
+ SimulatedTimeClientConfig config;
+ config.transport.cc =
+ TransportControllerConfig::CongestionController::kGoogCcFeedback;
+ config.transport.rates.min_rate = DataRate::kbps(10);
+ config.transport.rates.max_rate = DataRate::kbps(1500);
+ config.transport.rates.start_rate = DataRate::kbps(300);
+ NetworkNodeConfig net_conf;
+ auto send_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+ c->simulation.bandwidth = DataRate::kbps(2000);
+ c->simulation.delay = TimeDelta::ms(200);
+ c->simulation.loss_rate = 0.1;
+ c->update_frequency = TimeDelta::ms(5);
+ });
+ auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+ c->simulation.delay = TimeDelta::ms(200);
+ c->update_frequency = TimeDelta::ms(5);
+ });
+ SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
+ "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
+
+ s.RunFor(TimeDelta::seconds(120));
+ // Without LossBasedControl trial, bandwidth drops to ~10 kbps.
+ EXPECT_GT(client->target_rate_kbps(), 100);
+}
+
+TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
+ ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
+ Scenario s("googcc_unit/moderate_loss_channel", false);
+ SimulatedTimeClientConfig config;
+ config.transport.cc =
+ TransportControllerConfig::CongestionController::kGoogCcFeedback;
+ config.transport.rates.min_rate = DataRate::kbps(10);
+ config.transport.rates.max_rate = DataRate::kbps(5000);
+ config.transport.rates.start_rate = DataRate::kbps(300);
+ NetworkNodeConfig net_conf;
+ auto send_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+ c->simulation.bandwidth = DataRate::kbps(5000);
+ c->simulation.delay = TimeDelta::ms(100);
+ c->simulation.loss_rate = 0.02;
+ c->update_frequency = TimeDelta::ms(5);
+ });
+ auto ret_net = s.CreateSimulationNode([](NetworkNodeConfig* c) {
+ c->simulation.delay = TimeDelta::ms(100);
+ c->update_frequency = TimeDelta::ms(5);
+ });
+ SimulatedTimeClient* client = s.CreateSimulatedTimeClient(
+ "send", config, {PacketStreamConfig()}, {send_net}, {ret_net});
+
+ s.RunFor(TimeDelta::seconds(60));
+ // Without LossBasedControl trial, bitrate reaches above 4 mbps.
+ EXPECT_NEAR(client->target_rate_kbps(), 2000, 500);
+}
+
} // namespace test
} // namespace webrtc
diff --git a/test/scenario/simulated_time.cc b/test/scenario/simulated_time.cc
index 9759533..becd793 100644
--- a/test/scenario/simulated_time.cc
+++ b/test/scenario/simulated_time.cc
@@ -229,7 +229,8 @@
it->second});
receive_times_.erase(it);
}
- if (receive_times_.size() >= RawFeedbackReportPacket::MAX_FEEDBACKS) {
+ if (report.receive_times.size() >=
+ RawFeedbackReportPacket::MAX_FEEDBACKS) {
return_node_->TryDeliverPacket(FeedbackToBuffer(report),
return_receiver_id_, at_time);
report = SimpleFeedbackReportPacket();