diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc index f79164ebf0..2ebbe3338e 100644 --- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc +++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.cc @@ -49,10 +49,13 @@ bool IsValid(Timestamp timestamp) { return timestamp.IsFinite(); } +double ToKiloBytes(DataSize datasize) { return datasize.bytes() / 1000.0; } + struct PacketResultsSummary { int num_packets = 0; int num_lost_packets = 0; DataSize total_size = DataSize::Zero(); + DataSize lost_size = DataSize::Zero(); Timestamp first_send_time = Timestamp::PlusInfinity(); Timestamp last_send_time = Timestamp::MinusInfinity(); }; @@ -67,6 +70,7 @@ PacketResultsSummary GetPacketResultsSummary( for (const PacketResult& packet : packet_results) { if (!packet.IsReceived()) { packet_results_summary.num_lost_packets++; + packet_results_summary.lost_size += packet.sent_packet.size; } packet_results_summary.total_size += packet.sent_packet.size; packet_results_summary.first_send_time = std::min( @@ -444,6 +448,8 @@ absl::optional LossBasedBweV2::CreateConfig( FieldTrialParameter use_padding_for_increase("UsePadding", false); FieldTrialParameter hold_duration_factor("HoldDurationFactor", 0.0); + FieldTrialParameter use_byte_loss_rate("UseByteLossRate", false); + if (key_value_config) { ParseFieldTrial({&enabled, &bandwidth_rampup_upper_bound_factor, @@ -482,7 +488,8 @@ absl::optional LossBasedBweV2::CreateConfig( &min_num_observations, &lower_bound_by_acked_rate_factor, &use_padding_for_increase, - &hold_duration_factor}, + &hold_duration_factor, + &use_byte_loss_rate}, key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2")); } @@ -546,6 +553,7 @@ absl::optional LossBasedBweV2::CreateConfig( lower_bound_by_acked_rate_factor.Get(); config->use_padding_for_increase = use_padding_for_increase.Get(); config->hold_duration_factor = hold_duration_factor.Get(); + config->use_byte_loss_rate = use_byte_loss_rate.Get(); return config; } @@ -742,6 +750,11 @@ bool LossBasedBweV2::IsConfigValid() const { } double LossBasedBweV2::GetAverageReportedLossRatio() const { + return config_->use_byte_loss_rate ? GetAverageReportedByteLossRatio() + : GetAverageReportedPacketLossRatio(); +} + +double LossBasedBweV2::GetAverageReportedPacketLossRatio() const { if (num_observations_ <= 0) { return 0.0; } @@ -763,6 +776,27 @@ double LossBasedBweV2::GetAverageReportedLossRatio() const { return num_lost_packets / num_packets; } +double LossBasedBweV2::GetAverageReportedByteLossRatio() const { + if (num_observations_ <= 0) { + return 0.0; + } + + DataSize total_bytes = DataSize::Zero(); + DataSize lost_bytes = DataSize::Zero(); + for (const Observation& observation : observations_) { + if (!observation.IsInitialized()) { + continue; + } + + double instant_temporal_weight = + instant_upper_bound_temporal_weights_[(num_observations_ - 1) - + observation.id]; + total_bytes += instant_temporal_weight * observation.size; + lost_bytes += instant_temporal_weight * observation.lost_size; + } + return lost_bytes / total_bytes; +} + DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound() const { DataRate candidate_bandwidth_upper_bound = max_bitrate_; if (IsInLossLimitedState() && IsValid(bandwidth_limit_in_current_window_)) { @@ -846,16 +880,29 @@ LossBasedBweV2::Derivatives LossBasedBweV2::GetDerivatives( double temporal_weight = temporal_weights_[(num_observations_ - 1) - observation.id]; - - derivatives.first += - temporal_weight * - ((observation.num_lost_packets / loss_probability) - - (observation.num_received_packets / (1.0 - loss_probability))); - derivatives.second -= - temporal_weight * - ((observation.num_lost_packets / std::pow(loss_probability, 2)) + - (observation.num_received_packets / - std::pow(1.0 - loss_probability, 2))); + if (config_->use_byte_loss_rate) { + derivatives.first += + temporal_weight * + ((ToKiloBytes(observation.lost_size) / loss_probability) - + (ToKiloBytes(observation.size - observation.lost_size) / + (1.0 - loss_probability))); + derivatives.second -= + temporal_weight * + ((ToKiloBytes(observation.lost_size) / + std::pow(loss_probability, 2)) + + (ToKiloBytes(observation.size - observation.lost_size) / + std::pow(1.0 - loss_probability, 2))); + } else { + derivatives.first += + temporal_weight * + ((observation.num_lost_packets / loss_probability) - + (observation.num_received_packets / (1.0 - loss_probability))); + derivatives.second -= + temporal_weight * + ((observation.num_lost_packets / std::pow(loss_probability, 2)) + + (observation.num_received_packets / + std::pow(1.0 - loss_probability, 2))); + } } if (derivatives.second >= 0.0) { @@ -927,13 +974,23 @@ double LossBasedBweV2::GetObjective( double temporal_weight = temporal_weights_[(num_observations_ - 1) - observation.id]; - - objective += - temporal_weight * - ((observation.num_lost_packets * std::log(loss_probability)) + - (observation.num_received_packets * std::log(1.0 - loss_probability))); - objective += - temporal_weight * high_bandwidth_bias * observation.num_packets; + if (config_->use_byte_loss_rate) { + objective += + temporal_weight * + ((ToKiloBytes(observation.lost_size) * std::log(loss_probability)) + + (ToKiloBytes(observation.size - observation.lost_size) * + std::log(1.0 - loss_probability))); + objective += + temporal_weight * high_bandwidth_bias * ToKiloBytes(observation.size); + } else { + objective += + temporal_weight * + ((observation.num_lost_packets * std::log(loss_probability)) + + (observation.num_received_packets * + std::log(1.0 - loss_probability))); + objective += + temporal_weight * high_bandwidth_bias * observation.num_packets; + } } return objective; @@ -1036,6 +1093,7 @@ bool LossBasedBweV2::PushBackObservation( partial_observation_.num_lost_packets += packet_results_summary.num_lost_packets; partial_observation_.size += packet_results_summary.total_size; + partial_observation_.lost_size += packet_results_summary.lost_size; // This is the first packet report we have received. if (!IsValid(last_send_time_most_recent_observation_)) { @@ -1061,6 +1119,8 @@ bool LossBasedBweV2::PushBackObservation( observation.num_packets - observation.num_lost_packets; observation.sending_rate = GetSendingRate(partial_observation_.size / observation_duration); + observation.lost_size = partial_observation_.lost_size; + observation.size = partial_observation_.size; observation.id = num_observations_++; observations_[observation.id % config_->observation_window_size] = observation; diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h index 0468e16525..b39657c7bb 100644 --- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h +++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2.h @@ -120,6 +120,7 @@ class LossBasedBweV2 { double lower_bound_by_acked_rate_factor = 0.0; bool use_padding_for_increase = false; double hold_duration_factor = 0.0; + bool use_byte_loss_rate = false; }; struct Derivatives { @@ -134,6 +135,8 @@ class LossBasedBweV2 { int num_lost_packets = 0; int num_received_packets = 0; DataRate sending_rate = DataRate::MinusInfinity(); + DataSize size = DataSize::Zero(); + DataSize lost_size = DataSize::Zero(); int id = -1; }; @@ -141,6 +144,7 @@ class LossBasedBweV2 { int num_packets = 0; int num_lost_packets = 0; DataSize size = DataSize::Zero(); + DataSize lost_size = DataSize::Zero(); }; static absl::optional CreateConfig( @@ -149,6 +153,8 @@ class LossBasedBweV2 { // Returns `0.0` if not enough loss statistics have been received. double GetAverageReportedLossRatio() const; + double GetAverageReportedPacketLossRatio() const; + double GetAverageReportedByteLossRatio() const; std::vector GetCandidates(bool in_alr) const; DataRate GetCandidateBandwidthUpperBound() const; Derivatives GetDerivatives(const ChannelParameters& channel_parameters) const; diff --git a/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc b/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc index d9480d00d5..fc1f410bd6 100644 --- a/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc +++ b/modules/congestion_controller/goog_cc/loss_based_bwe_v2_test.cc @@ -31,6 +31,7 @@ using ::webrtc::test::ExplicitKeyValueConfig; constexpr TimeDelta kObservationDurationLowerBound = TimeDelta::Millis(250); constexpr TimeDelta kDelayedIncreaseWindow = TimeDelta::Millis(300); constexpr double kMaxIncreaseFactor = 1.5; +constexpr int kPacketSize = 15'000; class LossBasedBweV2Test : public ::testing::TestWithParam { protected: @@ -90,8 +91,8 @@ class LossBasedBweV2Test : public ::testing::TestWithParam { std::vector CreatePacketResultsWithReceivedPackets( Timestamp first_packet_timestamp) { std::vector 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.size = DataSize::Bytes(kPacketSize); + enough_feedback[1].sent_packet.size = DataSize::Bytes(kPacketSize); enough_feedback[0].sent_packet.send_time = first_packet_timestamp; enough_feedback[1].sent_packet.send_time = first_packet_timestamp + kObservationDurationLowerBound; @@ -102,12 +103,13 @@ class LossBasedBweV2Test : public ::testing::TestWithParam { return enough_feedback; } - std::vector CreatePacketResultsWith10pLossRate( - Timestamp first_packet_timestamp) { + std::vector CreatePacketResultsWith10pPacketLossRate( + Timestamp first_packet_timestamp, + DataSize lost_packet_size = DataSize::Bytes(kPacketSize)) { std::vector enough_feedback(10); - enough_feedback[0].sent_packet.size = DataSize::Bytes(15'000); + enough_feedback[0].sent_packet.size = DataSize::Bytes(kPacketSize); for (unsigned i = 0; i < enough_feedback.size(); ++i) { - enough_feedback[i].sent_packet.size = DataSize::Bytes(15'000); + enough_feedback[i].sent_packet.size = DataSize::Bytes(kPacketSize); enough_feedback[i].sent_packet.send_time = first_packet_timestamp + static_cast(i) * kObservationDurationLowerBound; @@ -116,14 +118,15 @@ class LossBasedBweV2Test : public ::testing::TestWithParam { static_cast(i + 1) * kObservationDurationLowerBound; } enough_feedback[9].receive_time = Timestamp::PlusInfinity(); + enough_feedback[9].sent_packet.size = lost_packet_size; return enough_feedback; } - std::vector CreatePacketResultsWith50pLossRate( + std::vector CreatePacketResultsWith50pPacketLossRate( Timestamp first_packet_timestamp) { std::vector 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.size = DataSize::Bytes(kPacketSize); + enough_feedback[1].sent_packet.size = DataSize::Bytes(kPacketSize); enough_feedback[0].sent_packet.send_time = first_packet_timestamp; enough_feedback[1].sent_packet.send_time = first_packet_timestamp + kObservationDurationLowerBound; @@ -136,8 +139,8 @@ class LossBasedBweV2Test : public ::testing::TestWithParam { std::vector CreatePacketResultsWith100pLossRate( Timestamp first_packet_timestamp) { std::vector 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.size = DataSize::Bytes(kPacketSize); + enough_feedback[1].sent_packet.size = DataSize::Bytes(kPacketSize); enough_feedback[0].sent_packet.send_time = first_packet_timestamp; enough_feedback[1].sent_packet.send_time = first_packet_timestamp + kObservationDurationLowerBound; @@ -461,7 +464,7 @@ TEST_F(LossBasedBweV2Test, UseAckedBitrateForEmegencyBackOff) { // Create two packet results, first packet has 50% loss rate, second packet // has 100% loss rate. std::vector enough_feedback_1 = - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); std::vector enough_feedback_2 = CreatePacketResultsWith100pLossRate( @@ -814,7 +817,7 @@ TEST_F(LossBasedBweV2Test, CreatePacketResultsWithReceivedPackets( /*first_packet_timestamp=*/Timestamp::Zero()); std::vector enough_feedback_2 = - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kDelayedIncreaseWindow - TimeDelta::Millis(2)); std::vector enough_feedback_3 = @@ -913,7 +916,7 @@ TEST_F(LossBasedBweV2Test, NotIncreaseIfInherentLossLessThanAverageLoss) { DataRate::KilobitsPerSec(600)); std::vector enough_feedback_10p_loss_1 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_10p_loss_1, @@ -921,7 +924,7 @@ TEST_F(LossBasedBweV2Test, NotIncreaseIfInherentLossLessThanAverageLoss) { /*in_alr=*/false); std::vector enough_feedback_10p_loss_2 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( @@ -947,7 +950,7 @@ TEST_F(LossBasedBweV2Test, DataRate::KilobitsPerSec(600)); std::vector enough_feedback_10p_loss_1 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_10p_loss_1, delay_based_estimate, @@ -955,7 +958,7 @@ TEST_F(LossBasedBweV2Test, /*in_alr=*/false); std::vector enough_feedback_10p_loss_2 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( @@ -981,7 +984,7 @@ TEST_F(LossBasedBweV2Test, DataRate::KilobitsPerSec(600)); std::vector enough_feedback_10p_loss_1 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_10p_loss_1, delay_based_estimate, @@ -989,7 +992,7 @@ TEST_F(LossBasedBweV2Test, /*in_alr=*/false); std::vector enough_feedback_10p_loss_2 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( @@ -1017,7 +1020,7 @@ TEST_F(LossBasedBweV2Test, DataRate::KilobitsPerSec(600)); std::vector enough_feedback_10p_loss_1 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_10p_loss_1, delay_based_estimate, @@ -1025,7 +1028,7 @@ TEST_F(LossBasedBweV2Test, /*in_alr=*/false); std::vector enough_feedback_10p_loss_2 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( @@ -1053,7 +1056,7 @@ TEST_F(LossBasedBweV2Test, DataRate::KilobitsPerSec(600)); std::vector enough_feedback_50p_loss_1 = - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_50p_loss_1, delay_based_estimate, @@ -1061,7 +1064,7 @@ TEST_F(LossBasedBweV2Test, /*in_alr=*/false); std::vector enough_feedback_50p_loss_2 = - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( @@ -1327,7 +1330,7 @@ TEST_F(LossBasedBweV2Test, HasDecreaseStateBecauseOfUpperBound) { DataRate::KilobitsPerSec(500)); std::vector enough_feedback_10p_loss_1 = - CreatePacketResultsWith10pLossRate( + CreatePacketResultsWith10pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_10p_loss_1, @@ -1357,7 +1360,7 @@ TEST_F(LossBasedBweV2Test, HasIncreaseStateBecauseOfLowerBound) { // Network has a high loss to create a loss scenario. std::vector enough_feedback_50p_loss_1 = - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( enough_feedback_50p_loss_1, @@ -1371,7 +1374,7 @@ TEST_F(LossBasedBweV2Test, HasIncreaseStateBecauseOfLowerBound) { loss_based_bandwidth_estimator.SetAcknowledgedBitrate( DataRate::KilobitsPerSec(200)); std::vector enough_feedback_50p_loss_2 = - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( @@ -1398,7 +1401,7 @@ TEST_F(LossBasedBweV2Test, loss_based_bandwidth_estimator.SetAcknowledgedBitrate( DataRate::KilobitsPerSec(150)); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()), /*delay_based_estimate=*/DataRate::PlusInfinity(), /*in_alr=*/true); @@ -1439,7 +1442,7 @@ TEST_F(LossBasedBweV2Test, HasDelayBasedStateIfLossBasedBweIsMax) { DataRate::KilobitsPerSec(1000)); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - /*feedback=*/CreatePacketResultsWith50pLossRate( + /*feedback=*/CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound), /*delay_based_estimate=*/DataRate::KilobitsPerSec(2000), @@ -1474,7 +1477,7 @@ TEST_F(LossBasedBweV2Test, IncreaseUsingPaddingStateIfFieldTrial) { loss_based_bandwidth_estimator.SetBandwidthEstimate( DataRate::KilobitsPerSec(2500)); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()), /*delay_based_estimate=*/DataRate::PlusInfinity(), /*in_alr=*/false); @@ -1498,7 +1501,7 @@ TEST_F(LossBasedBweV2Test, IncreaseEstimateIfNotHold) { loss_based_bandwidth_estimator.SetBandwidthEstimate( DataRate::KilobitsPerSec(2500)); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()), /*delay_based_estimate=*/DataRate::PlusInfinity(), /*in_alr=*/false); @@ -1527,7 +1530,7 @@ TEST_F(LossBasedBweV2Test, IncreaseEstimateAfterHoldDuration) { loss_based_bandwidth_estimator.SetBandwidthEstimate( DataRate::KilobitsPerSec(2500)); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()), /*delay_based_estimate=*/DataRate::PlusInfinity(), /*in_alr=*/false); @@ -1564,7 +1567,7 @@ TEST_F(LossBasedBweV2Test, IncreaseEstimateAfterHoldDuration) { // Get another 50p packet loss. loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero() + kObservationDurationLowerBound * 3), /*delay_based_estimate=*/DataRate::PlusInfinity(), @@ -1610,7 +1613,7 @@ TEST_F(LossBasedBweV2Test, EndHoldDurationIfDelayBasedEstimateWorks) { loss_based_bandwidth_estimator.SetBandwidthEstimate( DataRate::KilobitsPerSec(2500)); loss_based_bandwidth_estimator.UpdateBandwidthEstimate( - CreatePacketResultsWith50pLossRate( + CreatePacketResultsWith50pPacketLossRate( /*first_packet_timestamp=*/Timestamp::Zero()), /*delay_based_estimate=*/DataRate::PlusInfinity(), /*in_alr=*/false); @@ -1632,5 +1635,26 @@ TEST_F(LossBasedBweV2Test, EndHoldDurationIfDelayBasedEstimateWorks) { estimate + DataRate::KilobitsPerSec(10)); } +TEST_F(LossBasedBweV2Test, UseByteLossRate) { + ExplicitKeyValueConfig key_value_config( + ShortObservationConfig("UseByteLossRate:true")); + LossBasedBweV2 loss_based_bandwidth_estimator(&key_value_config); + loss_based_bandwidth_estimator.SetBandwidthEstimate( + DataRate::KilobitsPerSec(500)); + // Create packet feedback having 10% packet loss but more than 50% byte loss. + loss_based_bandwidth_estimator.UpdateBandwidthEstimate( + CreatePacketResultsWith10pPacketLossRate( + /*first_packet_timestamp=*/Timestamp::Zero(), + /*lost_packet_size=*/DataSize::Bytes(kPacketSize * 20)), + /*delay_based_estimate=*/DataRate::PlusInfinity(), + /*in_alr=*/false); + EXPECT_EQ(loss_based_bandwidth_estimator.GetLossBasedResult().state, + LossBasedState::kDecreasing); + // The estimate is bounded by the instant upper bound due to high loss. + EXPECT_LT( + loss_based_bandwidth_estimator.GetLossBasedResult().bandwidth_estimate, + DataRate::KilobitsPerSec(150)); +} + } // namespace } // namespace webrtc