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}
This commit is contained in:
Christoffer Rodbro 2018-11-29 17:12:52 +01:00 committed by Commit Bot
parent b535c13e25
commit 5976bde2e6
3 changed files with 120 additions and 51 deletions

View file

@ -156,9 +156,9 @@ void LossBasedBandwidthEstimation::UpdateAcknowledgedBitrate(
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);
}
}

View file

@ -28,6 +28,58 @@ namespace {
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, LimitsToMinRateIfRttIsHighInTrial) {
}
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 @@ TEST_F(GoogCcNetworkControllerTest, StableEstimateDoesNotVaryInSteadyState) {
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

View file

@ -229,7 +229,8 @@ bool SimulatedFeedback::TryDeliverPacket(rtc::CopyOnWriteBuffer packet,
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();