Ensure loss-based controller is always enabled.
The new default parameters are the ones that were used in the Chrome Finch trial. The deleted unit test is invalidated by these changes. Bug: chromium:941413 Change-Id: I597f4b0defaebe5bb3a6710b071fae2ee5c6f461 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/160652 Commit-Queue: Jonas Olsson <jonasolsson@webrtc.org> Reviewed-by: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30049}
This commit is contained in:
@ -71,56 +71,6 @@ CallClient* CreateVideoSendingClient(
|
||||
s->CreateVideoStream(route->forward(), VideoStreamConfig());
|
||||
return client;
|
||||
}
|
||||
|
||||
void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") {
|
||||
ScopedFieldTrials trial("WebRTC-SendSideBwe-WithOverhead/Enabled/");
|
||||
auto factory = CreateFeedbackOnlyFactory();
|
||||
Scenario s("googcc_unit/target_capacity" + test_name, false);
|
||||
CallClientConfig config;
|
||||
config.transport.cc_factory = &factory;
|
||||
config.transport.rates.min_rate = DataRate::kbps(10);
|
||||
config.transport.rates.max_rate = DataRate::kbps(1500);
|
||||
config.transport.rates.start_rate = DataRate::kbps(300);
|
||||
auto send_net = s.CreateMutableSimulationNode([](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(500);
|
||||
c->delay = TimeDelta::ms(100);
|
||||
c->loss_rate = 0.0;
|
||||
});
|
||||
auto ret_net = s.CreateMutableSimulationNode(
|
||||
[](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); });
|
||||
StatesPrinter* truth = s.CreatePrinter(
|
||||
"send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
|
||||
|
||||
auto* client = CreateVideoSendingClient(&s, config, {send_net->node()},
|
||||
{ret_net->node()});
|
||||
|
||||
truth->PrintRow();
|
||||
s.RunFor(TimeDelta::seconds(25));
|
||||
truth->PrintRow();
|
||||
EXPECT_NEAR(client->target_rate().kbps(), 450, 100);
|
||||
|
||||
send_net->UpdateConfig([](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(800);
|
||||
c->delay = TimeDelta::ms(100);
|
||||
});
|
||||
|
||||
truth->PrintRow();
|
||||
s.RunFor(TimeDelta::seconds(20));
|
||||
truth->PrintRow();
|
||||
EXPECT_NEAR(client->target_rate().kbps(), 750, 150);
|
||||
|
||||
send_net->UpdateConfig([](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(100);
|
||||
c->delay = TimeDelta::ms(200);
|
||||
});
|
||||
ret_net->UpdateConfig(
|
||||
[](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(200); });
|
||||
|
||||
truth->PrintRow();
|
||||
s.RunFor(TimeDelta::seconds(50));
|
||||
truth->PrintRow();
|
||||
EXPECT_NEAR(client->target_rate().kbps(), 90, 25);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
class GoogCcNetworkControllerTest : public ::testing::Test {
|
||||
@ -416,7 +366,53 @@ TEST_F(GoogCcNetworkControllerTest, LimitsToFloorIfRttIsHighInTrial) {
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest, UpdatesTargetRateBasedOnLinkCapacity) {
|
||||
UpdatesTargetRateBasedOnLinkCapacity();
|
||||
ScopedFieldTrials trial("WebRTC-SendSideBwe-WithOverhead/Enabled/");
|
||||
auto factory = CreateFeedbackOnlyFactory();
|
||||
Scenario s("googcc_unit/target_capacity", false);
|
||||
CallClientConfig config;
|
||||
config.transport.cc_factory = &factory;
|
||||
config.transport.rates.min_rate = DataRate::kbps(10);
|
||||
config.transport.rates.max_rate = DataRate::kbps(1500);
|
||||
config.transport.rates.start_rate = DataRate::kbps(300);
|
||||
auto send_net = s.CreateMutableSimulationNode([](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(500);
|
||||
c->delay = TimeDelta::ms(100);
|
||||
c->loss_rate = 0.0;
|
||||
});
|
||||
auto ret_net = s.CreateMutableSimulationNode(
|
||||
[](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(100); });
|
||||
StatesPrinter* truth = s.CreatePrinter(
|
||||
"send.truth.txt", TimeDelta::PlusInfinity(), {send_net->ConfigPrinter()});
|
||||
|
||||
auto* client = CreateVideoSendingClient(&s, config, {send_net->node()},
|
||||
{ret_net->node()});
|
||||
|
||||
truth->PrintRow();
|
||||
s.RunFor(TimeDelta::seconds(25));
|
||||
truth->PrintRow();
|
||||
EXPECT_NEAR(client->target_rate().kbps(), 450, 100);
|
||||
|
||||
send_net->UpdateConfig([](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(800);
|
||||
c->delay = TimeDelta::ms(100);
|
||||
});
|
||||
|
||||
truth->PrintRow();
|
||||
s.RunFor(TimeDelta::seconds(20));
|
||||
truth->PrintRow();
|
||||
EXPECT_NEAR(client->target_rate().kbps(), 750, 150);
|
||||
|
||||
send_net->UpdateConfig([](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(100);
|
||||
c->delay = TimeDelta::ms(200);
|
||||
});
|
||||
ret_net->UpdateConfig(
|
||||
[](NetworkSimulationConfig* c) { c->delay = TimeDelta::ms(200); });
|
||||
|
||||
truth->PrintRow();
|
||||
s.RunFor(TimeDelta::seconds(50));
|
||||
truth->PrintRow();
|
||||
EXPECT_NEAR(client->target_rate().kbps(), 90, 25);
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest, StableEstimateDoesNotVaryInSteadyState) {
|
||||
@ -456,16 +452,7 @@ TEST_F(GoogCcNetworkControllerTest, StableEstimateDoesNotVaryInSteadyState) {
|
||||
EXPECT_GE(min_stable_target / max_stable_target, min_target / max_target);
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest,
|
||||
LossBasedControlUpdatesTargetRateBasedOnLinkCapacity) {
|
||||
ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
|
||||
// TODO(srte): Should the behavior be unaffected at low loss rates?
|
||||
UpdatesTargetRateBasedOnLinkCapacity("_loss_based");
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest,
|
||||
LossBasedControlDoesModestBackoffToHighLoss) {
|
||||
ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
|
||||
TEST_F(GoogCcNetworkControllerTest, DoesModestBackoffToHighLoss) {
|
||||
Scenario s("googcc_unit/high_loss_channel", false);
|
||||
CallClientConfig config;
|
||||
config.transport.rates.min_rate = DataRate::kbps(10);
|
||||
@ -482,12 +469,11 @@ TEST_F(GoogCcNetworkControllerTest,
|
||||
auto* client = CreateVideoSendingClient(&s, config, {send_net}, {ret_net});
|
||||
|
||||
s.RunFor(TimeDelta::seconds(120));
|
||||
// Without LossBasedControl trial, bandwidth drops to ~10 kbps.
|
||||
EXPECT_GT(client->target_rate().kbps(), 100);
|
||||
}
|
||||
|
||||
DataRate AverageBitrateAfterCrossInducedLoss(std::string name) {
|
||||
Scenario s(name, false);
|
||||
TEST_F(GoogCcNetworkControllerTest, RecoversAfterCrossInducedLoss) {
|
||||
Scenario s("googcc_unit/cross_loss_based", false);
|
||||
NetworkSimulationConfig net_conf;
|
||||
net_conf.bandwidth = DataRate::kbps(1000);
|
||||
net_conf.delay = TimeDelta::ms(100);
|
||||
@ -513,33 +499,16 @@ DataRate AverageBitrateAfterCrossInducedLoss(std::string name) {
|
||||
s.net()->StopCrossTraffic(tcp_traffic);
|
||||
s.RunFor(TimeDelta::seconds(20));
|
||||
}
|
||||
return DataSize::bytes(video->receive()
|
||||
->GetStats()
|
||||
.rtp_stats.packet_counter.TotalBytes()) /
|
||||
s.TimeSinceStart();
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest,
|
||||
NoLossBasedRecoversSlowerAfterCrossInducedLoss) {
|
||||
// This test acts as a reference for the test below, showing that wihtout the
|
||||
// trial, we have worse behavior.
|
||||
DataRate average_bitrate =
|
||||
AverageBitrateAfterCrossInducedLoss("googcc_unit/no_cross_loss_based");
|
||||
RTC_DCHECK_LE(average_bitrate, DataRate::kbps(650));
|
||||
DataSize::bytes(
|
||||
video->receive()->GetStats().rtp_stats.packet_counter.TotalBytes()) /
|
||||
s.TimeSinceStart();
|
||||
|
||||
// We recover bitrate when subject to loss spikes from cross traffic.
|
||||
RTC_DCHECK_GE(average_bitrate, DataRate::kbps(720));
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest,
|
||||
LossBasedRecoversFasterAfterCrossInducedLoss) {
|
||||
// We recover bitrate better when subject to loss spikes from cross traffic
|
||||
// when loss based controller is used.
|
||||
ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
|
||||
DataRate average_bitrate =
|
||||
AverageBitrateAfterCrossInducedLoss("googcc_unit/cross_loss_based");
|
||||
RTC_DCHECK_GE(average_bitrate, DataRate::kbps(750));
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
|
||||
ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
|
||||
TEST_F(GoogCcNetworkControllerTest, CapsRateAtModerateLoss) {
|
||||
Scenario s("googcc_unit/moderate_loss_channel", false);
|
||||
CallClientConfig config;
|
||||
config.transport.rates.min_rate = DataRate::kbps(10);
|
||||
@ -560,13 +529,11 @@ TEST_F(GoogCcNetworkControllerTest, LossBasedEstimatorCapsRateAtModerateLoss) {
|
||||
s.CreateVideoStream(route->forward(), VideoStreamConfig());
|
||||
// Allow the controller to stabilize at the lower bitrate.
|
||||
s.RunFor(TimeDelta::seconds(1));
|
||||
// This increase in capacity would cause the target bitrate to increase to
|
||||
// over 4000 kbps without LossBasedControl.
|
||||
send_net->UpdateConfig(
|
||||
[](NetworkSimulationConfig* c) { c->bandwidth = DataRate::kbps(5000); });
|
||||
s.RunFor(TimeDelta::seconds(20));
|
||||
// Using LossBasedControl, the bitrate will not increase over 2500 kbps since
|
||||
// we have detected moderate loss.
|
||||
// The bitrate will not increase over 2500 kbps since we have detected
|
||||
// moderate loss.
|
||||
EXPECT_LT(client->target_rate().kbps(), 2500);
|
||||
}
|
||||
|
||||
@ -695,7 +662,6 @@ TEST_F(GoogCcNetworkControllerTest,
|
||||
}
|
||||
|
||||
TEST_F(GoogCcNetworkControllerTest, NoBandwidthTogglingInLossControlTrial) {
|
||||
ScopedFieldTrials trial("WebRTC-Bwe-LossBasedControl/Enabled/");
|
||||
Scenario s("googcc_unit/no_toggling");
|
||||
auto* send_net = s.CreateSimulationNode([&](NetworkSimulationConfig* c) {
|
||||
c->bandwidth = DataRate::kbps(2000);
|
||||
|
@ -74,20 +74,19 @@ double ExponentialUpdate(TimeDelta window, TimeDelta interval) {
|
||||
} // namespace
|
||||
|
||||
LossBasedControlConfig::LossBasedControlConfig()
|
||||
: enabled(field_trial::IsEnabled(kBweLossBasedControl)),
|
||||
min_increase_factor("min_incr", 1.02),
|
||||
: min_increase_factor("min_incr", 1.02),
|
||||
max_increase_factor("max_incr", 1.08),
|
||||
increase_low_rtt("incr_low_rtt", TimeDelta::ms(200)),
|
||||
increase_high_rtt("incr_high_rtt", TimeDelta::ms(800)),
|
||||
decrease_factor("decr", 0.99),
|
||||
decrease_factor("decr", 0.85),
|
||||
loss_window("loss_win", TimeDelta::ms(800)),
|
||||
loss_max_window("loss_max_win", TimeDelta::ms(800)),
|
||||
acknowledged_rate_max_window("ackrate_max_win", TimeDelta::ms(800)),
|
||||
increase_offset("incr_offset", DataRate::bps(1000)),
|
||||
loss_bandwidth_balance_increase("balance_incr", DataRate::kbps(0.5)),
|
||||
loss_bandwidth_balance_decrease("balance_decr", DataRate::kbps(4)),
|
||||
loss_bandwidth_balance_exponent("exponent", 0.5),
|
||||
allow_resets("resets", false),
|
||||
loss_bandwidth_balance_increase("balance_incr", DataRate::kbps(5)),
|
||||
loss_bandwidth_balance_decrease("balance_decr", DataRate::kbps(24)),
|
||||
loss_bandwidth_balance_exponent("exponent", 0.7),
|
||||
allow_resets("resets", true),
|
||||
decrease_interval("decr_intvl", TimeDelta::ms(300)),
|
||||
loss_report_timeout("timeout", TimeDelta::ms(6000)) {
|
||||
std::string trial_string = field_trial::FindFullName(kBweLossBasedControl);
|
||||
|
@ -26,7 +26,6 @@ struct LossBasedControlConfig {
|
||||
LossBasedControlConfig(const LossBasedControlConfig&);
|
||||
LossBasedControlConfig& operator=(const LossBasedControlConfig&) = default;
|
||||
~LossBasedControlConfig();
|
||||
bool enabled;
|
||||
FieldTrialParameter<double> min_increase_factor;
|
||||
FieldTrialParameter<double> max_increase_factor;
|
||||
FieldTrialParameter<TimeDelta> increase_low_rtt;
|
||||
@ -54,7 +53,6 @@ class LossBasedBandwidthEstimation {
|
||||
Timestamp at_time);
|
||||
void MaybeReset(DataRate bitrate);
|
||||
void SetInitialBitrate(DataRate bitrate);
|
||||
bool Enabled() const { return config_.enabled; }
|
||||
void UpdateLossStatistics(const std::vector<PacketResult>& packet_results,
|
||||
Timestamp at_time);
|
||||
DataRate GetEstimate() const { return loss_based_bitrate_; }
|
||||
|
@ -28,7 +28,6 @@
|
||||
namespace webrtc {
|
||||
namespace {
|
||||
constexpr TimeDelta kBweIncreaseInterval = TimeDelta::Millis<1000>();
|
||||
constexpr TimeDelta kBweDecreaseInterval = TimeDelta::Millis<300>();
|
||||
constexpr TimeDelta kStartPhase = TimeDelta::Millis<2000>();
|
||||
constexpr TimeDelta kBweConverganceTime = TimeDelta::Millis<20000>();
|
||||
constexpr int kLimitNumPackets = 20;
|
||||
@ -272,9 +271,8 @@ void SendSideBandwidthEstimation::SetSendBitrate(DataRate bitrate,
|
||||
RTC_DCHECK_GT(bitrate, DataRate::Zero());
|
||||
// Reset to avoid being capped by the estimate.
|
||||
delay_based_limit_ = DataRate::PlusInfinity();
|
||||
if (loss_based_bandwidth_estimation_.Enabled()) {
|
||||
loss_based_bandwidth_estimation_.MaybeReset(bitrate);
|
||||
}
|
||||
loss_based_bandwidth_estimation_.MaybeReset(bitrate);
|
||||
|
||||
UpdateTargetBitrate(bitrate, at_time);
|
||||
// Clear last sent bitrate history so the new value can be used directly
|
||||
// and not capped.
|
||||
@ -325,7 +323,7 @@ void SendSideBandwidthEstimation::SetAcknowledgedRate(
|
||||
absl::optional<DataRate> acknowledged_rate,
|
||||
Timestamp at_time) {
|
||||
acknowledged_rate_ = acknowledged_rate;
|
||||
if (acknowledged_rate && loss_based_bandwidth_estimation_.Enabled()) {
|
||||
if (acknowledged_rate) {
|
||||
loss_based_bandwidth_estimation_.UpdateAcknowledgedBitrate(
|
||||
*acknowledged_rate, at_time);
|
||||
}
|
||||
@ -333,10 +331,8 @@ void SendSideBandwidthEstimation::SetAcknowledgedRate(
|
||||
|
||||
void SendSideBandwidthEstimation::IncomingPacketFeedbackVector(
|
||||
const TransportPacketsFeedback& report) {
|
||||
if (loss_based_bandwidth_estimation_.Enabled()) {
|
||||
loss_based_bandwidth_estimation_.UpdateLossStatistics(
|
||||
report.packet_feedbacks, report.feedback_time);
|
||||
}
|
||||
loss_based_bandwidth_estimation_.UpdateLossStatistics(report.packet_feedbacks,
|
||||
report.feedback_time);
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost,
|
||||
@ -440,18 +436,11 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
|
||||
new_bitrate = std::max(receiver_limit_, new_bitrate);
|
||||
if (delay_based_limit_.IsFinite())
|
||||
new_bitrate = std::max(delay_based_limit_, new_bitrate);
|
||||
if (loss_based_bandwidth_estimation_.Enabled()) {
|
||||
loss_based_bandwidth_estimation_.SetInitialBitrate(new_bitrate);
|
||||
}
|
||||
loss_based_bandwidth_estimation_.SetInitialBitrate(new_bitrate);
|
||||
|
||||
if (new_bitrate != current_target_) {
|
||||
min_bitrate_history_.clear();
|
||||
if (loss_based_bandwidth_estimation_.Enabled()) {
|
||||
min_bitrate_history_.push_back(std::make_pair(at_time, new_bitrate));
|
||||
} else {
|
||||
min_bitrate_history_.push_back(
|
||||
std::make_pair(at_time, current_target_));
|
||||
}
|
||||
min_bitrate_history_.push_back(std::make_pair(at_time, new_bitrate));
|
||||
UpdateTargetBitrate(new_bitrate, at_time);
|
||||
return;
|
||||
}
|
||||
@ -464,68 +453,10 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (loss_based_bandwidth_estimation_.Enabled()) {
|
||||
loss_based_bandwidth_estimation_.Update(
|
||||
at_time, min_bitrate_history_.front().second, last_round_trip_time_);
|
||||
DataRate new_bitrate = MaybeRampupOrBackoff(current_target_, at_time);
|
||||
UpdateTargetBitrate(new_bitrate, at_time);
|
||||
return;
|
||||
}
|
||||
|
||||
TimeDelta time_since_loss_packet_report = at_time - last_loss_packet_report_;
|
||||
if (time_since_loss_packet_report < 1.2 * kMaxRtcpFeedbackInterval) {
|
||||
// We only care about loss above a given bitrate threshold.
|
||||
float loss = last_fraction_loss_ / 256.0f;
|
||||
// We only make decisions based on loss when the bitrate is above a
|
||||
// threshold. This is a crude way of handling loss which is uncorrelated
|
||||
// to congestion.
|
||||
if (current_target_ < bitrate_threshold_ || loss <= low_loss_threshold_) {
|
||||
// Loss < 2%: Increase rate by 8% of the min bitrate in the last
|
||||
// kBweIncreaseInterval.
|
||||
// Note that by remembering the bitrate over the last second one can
|
||||
// rampup up one second faster than if only allowed to start ramping
|
||||
// at 8% per second rate now. E.g.:
|
||||
// If sending a constant 100kbps it can rampup immediately to 108kbps
|
||||
// whenever a receiver report is received with lower packet loss.
|
||||
// If instead one would do: current_bitrate_ *= 1.08^(delta time),
|
||||
// it would take over one second since the lower packet loss to achieve
|
||||
// 108kbps.
|
||||
DataRate new_bitrate =
|
||||
DataRate::bps(min_bitrate_history_.front().second.bps() * 1.08 + 0.5);
|
||||
|
||||
// Add 1 kbps extra, just to make sure that we do not get stuck
|
||||
// (gives a little extra increase at low rates, negligible at higher
|
||||
// rates).
|
||||
new_bitrate += DataRate::bps(1000);
|
||||
UpdateTargetBitrate(new_bitrate, at_time);
|
||||
return;
|
||||
} else if (current_target_ > bitrate_threshold_) {
|
||||
if (loss <= high_loss_threshold_) {
|
||||
// Loss between 2% - 10%: Do nothing.
|
||||
} else {
|
||||
// Loss > 10%: Limit the rate decreases to once a kBweDecreaseInterval
|
||||
// + rtt.
|
||||
if (!has_decreased_since_last_fraction_loss_ &&
|
||||
(at_time - time_last_decrease_) >=
|
||||
(kBweDecreaseInterval + last_round_trip_time_)) {
|
||||
time_last_decrease_ = at_time;
|
||||
|
||||
// Reduce rate:
|
||||
// newRate = rate * (1 - 0.5*lossRate);
|
||||
// where packetLoss = 256*lossRate;
|
||||
DataRate new_bitrate =
|
||||
DataRate::bps((current_target_.bps() *
|
||||
static_cast<double>(512 - last_fraction_loss_)) /
|
||||
512.0);
|
||||
has_decreased_since_last_fraction_loss_ = true;
|
||||
UpdateTargetBitrate(new_bitrate, at_time);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO(srte): This is likely redundant in most cases.
|
||||
ApplyTargetLimits(at_time);
|
||||
}
|
||||
|
||||
void SendSideBandwidthEstimation::UpdatePropagationRtt(
|
||||
@ -580,8 +511,7 @@ DataRate SendSideBandwidthEstimation::MaybeRampupOrBackoff(DataRate new_bitrate,
|
||||
DataRate SendSideBandwidthEstimation::GetUpperLimit() const {
|
||||
DataRate upper_limit = std::min(delay_based_limit_, receiver_limit_);
|
||||
upper_limit = std::min(upper_limit, max_bitrate_configured_);
|
||||
if (loss_based_bandwidth_estimation_.Enabled() &&
|
||||
loss_based_bandwidth_estimation_.GetEstimate() > DataRate::Zero()) {
|
||||
if (loss_based_bandwidth_estimation_.GetEstimate() > DataRate::Zero()) {
|
||||
upper_limit =
|
||||
std::min(upper_limit, loss_based_bandwidth_estimation_.GetEstimate());
|
||||
}
|
||||
|
@ -79,59 +79,6 @@ TEST(SendSideBweTest, InitialDelayBasedBweWithProbing) {
|
||||
TestProbing(true);
|
||||
}
|
||||
|
||||
TEST(SendSideBweTest, DoesntReapplyBitrateDecreaseWithoutFollowingRemb) {
|
||||
MockRtcEventLog event_log;
|
||||
EXPECT_CALL(event_log, LogProxy(LossBasedBweUpdateWithBitrateOnly()))
|
||||
.Times(1);
|
||||
EXPECT_CALL(event_log,
|
||||
LogProxy(LossBasedBweUpdateWithBitrateAndLossFraction()))
|
||||
.Times(1);
|
||||
SendSideBandwidthEstimation bwe(&event_log);
|
||||
static const int kMinBitrateBps = 100000;
|
||||
static const int kInitialBitrateBps = 1000000;
|
||||
int64_t now_ms = 1000;
|
||||
bwe.SetMinMaxBitrate(DataRate::bps(kMinBitrateBps), DataRate::bps(1500000));
|
||||
bwe.SetSendBitrate(DataRate::bps(kInitialBitrateBps), Timestamp::ms(now_ms));
|
||||
|
||||
static const uint8_t kFractionLoss = 128;
|
||||
static const int64_t kRttMs = 50;
|
||||
now_ms += 10000;
|
||||
|
||||
EXPECT_EQ(kInitialBitrateBps, bwe.target_rate().bps());
|
||||
EXPECT_EQ(0, bwe.fraction_loss());
|
||||
EXPECT_EQ(0, bwe.round_trip_time().ms());
|
||||
|
||||
// Signal heavy loss to go down in bitrate.
|
||||
bwe.UpdatePacketsLost(/*packets_lost=*/50, /*number_of_packets=*/100,
|
||||
Timestamp::ms(now_ms));
|
||||
bwe.UpdateRtt(TimeDelta::ms(kRttMs), Timestamp::ms(now_ms));
|
||||
|
||||
// Trigger an update 2 seconds later to not be rate limited.
|
||||
now_ms += 1000;
|
||||
bwe.UpdateEstimate(Timestamp::ms(now_ms));
|
||||
EXPECT_LT(bwe.target_rate().bps(), kInitialBitrateBps);
|
||||
// Verify that the obtained bitrate isn't hitting the min bitrate, or this
|
||||
// test doesn't make sense. If this ever happens, update the thresholds or
|
||||
// loss rates so that it doesn't hit min bitrate after one bitrate update.
|
||||
EXPECT_GT(bwe.target_rate().bps(), kMinBitrateBps);
|
||||
EXPECT_EQ(kFractionLoss, bwe.fraction_loss());
|
||||
EXPECT_EQ(kRttMs, bwe.round_trip_time().ms());
|
||||
|
||||
// Triggering an update shouldn't apply further downgrade nor upgrade since
|
||||
// there's no intermediate receiver block received indicating whether this is
|
||||
// currently good or not.
|
||||
int last_bitrate_bps = bwe.target_rate().bps();
|
||||
// Trigger an update 2 seconds later to not be rate limited (but it still
|
||||
// shouldn't update).
|
||||
now_ms += 1000;
|
||||
bwe.UpdateEstimate(Timestamp::ms(now_ms));
|
||||
|
||||
EXPECT_EQ(last_bitrate_bps, bwe.target_rate().bps());
|
||||
// The old loss rate should still be applied though.
|
||||
EXPECT_EQ(kFractionLoss, bwe.fraction_loss());
|
||||
EXPECT_EQ(kRttMs, bwe.round_trip_time().ms());
|
||||
}
|
||||
|
||||
TEST(SendSideBweTest, SettingSendBitrateOverridesDelayBasedEstimate) {
|
||||
::testing::NiceMock<MockRtcEventLog> event_log;
|
||||
SendSideBandwidthEstimation bwe(&event_log);
|
||||
|
Reference in New Issue
Block a user