From d339dbc7d4758e62b02740feda85c82dd6b2eba5 Mon Sep 17 00:00:00 2001 From: gnish Date: Tue, 1 Aug 2017 03:06:17 -0700 Subject: [PATCH] Added implementations for entering/exiting STARTUP, DRAIN, PROBE_BW, PROBE_RTT modes, also updated MaxBandwidthFilter class, with the filter implementation which stores three best estimates for the filter window. BUG=webrtc:7713 Review-Url: https://codereview.webrtc.org/2982233002 Cr-Commit-Position: refs/heads/master@{#19196} --- .../test/estimators/bbr.cc | 118 ++++++++++++++++-- .../test/estimators/bbr.h | 30 ++++- .../test/estimators/congestion_window.cc | 44 +++---- .../test/estimators/congestion_window.h | 10 +- .../estimators/congestion_window_unittest.cc | 19 +-- .../test/estimators/max_bandwidth_filter.cc | 49 ++++++-- .../test/estimators/max_bandwidth_filter.h | 27 ++-- .../max_bandwidth_filter_unittest.cc | 26 +++- 8 files changed, 255 insertions(+), 68 deletions(-) diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc index a2463fc872..11979bf446 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc @@ -11,13 +11,17 @@ #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" +#include + +#include "webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h" #include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" +#include "webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h" namespace webrtc { namespace testing { namespace bwe { namespace { -const int kFeedbackIntervalsMs = 100; +const int kFeedbackIntervalsMs = 3; // BBR uses this value to double sending rate each round trip. Design document // suggests using this value. const float kHighGain = 2.885f; @@ -28,6 +32,23 @@ const float kDrainGain = 1 / kHighGain; // experiments, according to the design document. const float kStartupGrowthTarget = 1.25f; const int kMaxRoundsWithoutGrowth = 3; +// Pacing gain values for Probe Bandwidth mode. +const float kPacingGain[] = {1.25, 0.75, 1, 1, 1, 1, 1, 1}; +const size_t kGainCycleLength = sizeof(kPacingGain) / sizeof(kPacingGain[0]); +// The least amount of rounds PROBE_RTT mode should last. +const int kProbeRttDurationRounds = 1; +// The least amount of milliseconds PROBE_RTT mode should last. +const int kProbeRttDurationMs = 200; +// Gain value for congestion window for assuming that network has no queues. +const float kTargetCongestionWindowGain = 1; +// Gain value for congestion window in PROBE_BW mode. In theory it should be +// equal to 1, but in practice because of delayed acks and the way networks +// work, it is nice to have some extra room in congestion window for full link +// utilization. Value chosen by observations on different tests. +const float kCruisingCongestionWindowGain = 1.5f; +// Expiration time for min_rtt sample, which is set to 10 seconds according to +// BBR design doc. +const int64_t kMinRttFilterSizeMs = 10000; } // namespace BbrBweSender::BbrBweSender(Clock* clock) @@ -35,10 +56,19 @@ BbrBweSender::BbrBweSender(Clock* clock) clock_(clock), mode_(STARTUP), max_bandwidth_filter_(new MaxBandwidthFilter()), + min_rtt_filter_(new MinRttFilter()), + congestion_window_(new CongestionWindow()), + rand_(new Random(time(NULL))), round_count_(0), last_packet_sent_(0), round_trip_end_(0), - full_bandwidth_reached_(false) { + full_bandwidth_reached_(false), + cycle_start_time_ms_(0), + cycle_index_(0), + prior_in_flight_(0), + probe_rtt_start_time_ms_(0), + minimum_congestion_window_start_time_ms_(), + minimum_congestion_window_start_round_(0) { // Initially enter Startup mode. EnterStartup(); } @@ -81,7 +111,7 @@ void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { TryUpdatingCyclePhase(now_ms); break; case PROBE_RTT: - TryExitingProbeRtt(now_ms); + TryExitingProbeRtt(now_ms, 0); break; } TryEnteringProbeRtt(now_ms); @@ -89,6 +119,14 @@ void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { // controllers. } +size_t BbrBweSender::TargetCongestionWindow(float gain) { + size_t target_congestion_window = + congestion_window_->GetTargetCongestionWindow( + max_bandwidth_filter_->max_bandwidth_estimate_bps(), + min_rtt_filter_->min_rtt_ms(), gain); + return target_congestion_window; +} + bool BbrBweSender::UpdateBandwidthAndMinRtt() { return false; } @@ -107,14 +145,78 @@ void BbrBweSender::TryExitingStartup() { } } -void BbrBweSender::TryExitingDrain(int64_t now_ms) {} +void BbrBweSender::TryExitingDrain(int64_t now_ms) { + if (congestion_window_->data_inflight() <= + TargetCongestionWindow(kTargetCongestionWindowGain)) + EnterProbeBw(now_ms); +} -void BbrBweSender::EnterProbeBw(int64_t now_ms) {} +// Start probing with a random gain value, which is different form 0.75, +// starting with 0.75 doesn't offer any benefits as there are no queues to be +// drained. +void BbrBweSender::EnterProbeBw(int64_t now_ms) { + mode_ = PROBE_BW; + congestion_window_gain_ = kCruisingCongestionWindowGain; + int index = rand_->Rand(kGainCycleLength - 2); + if (index == 1) + index = kGainCycleLength - 1; + pacing_gain_ = kPacingGain[index]; + cycle_start_time_ms_ = now_ms; + cycle_index_ = index; +} -void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) {} +void BbrBweSender::TryUpdatingCyclePhase(int64_t now_ms) { + // Each phase should last rougly min_rtt ms time. + bool advance_cycle_phase = false; + if (min_rtt_filter_->min_rtt_ms()) + advance_cycle_phase = + now_ms - cycle_start_time_ms_ > *min_rtt_filter_->min_rtt_ms(); + // If BBR was probing and it couldn't increase data inflight sufficiently in + // one min_rtt time, continue probing. BBR design doc isn't clear about this, + // but condition helps in quicker ramp-up and performs better. + if (pacing_gain_ > 1.0 && + prior_in_flight_ < TargetCongestionWindow(pacing_gain_)) + advance_cycle_phase = false; + // If BBR has already drained queues there is no point in continuing draining + // phase. + if (pacing_gain_ < 1.0 && prior_in_flight_ <= TargetCongestionWindow(1)) + advance_cycle_phase = true; + if (advance_cycle_phase) { + cycle_index_++; + cycle_index_ %= kGainCycleLength; + pacing_gain_ = kPacingGain[cycle_index_]; + cycle_start_time_ms_ = now_ms; + } +} -void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) {} -void BbrBweSender::TryExitingProbeRtt(int64_t now_ms) {} +void BbrBweSender::TryEnteringProbeRtt(int64_t now_ms) { + if (min_rtt_filter_->min_rtt_expired(now_ms, kMinRttFilterSizeMs) && + mode_ != PROBE_RTT) { + mode_ = PROBE_RTT; + pacing_gain_ = 1; + probe_rtt_start_time_ms_ = now_ms; + minimum_congestion_window_start_time_ms_.reset(); + } +} + +// minimum_congestion_window_start_time_'s value is set to the first moment when +// data inflight was less then kMinimumCongestionWindowBytes, we should make +// sure that BBR has been in PROBE_RTT mode for at least one round or 200ms. +void BbrBweSender::TryExitingProbeRtt(int64_t now_ms, int64_t round) { + if (!minimum_congestion_window_start_time_ms_) { + if (congestion_window_->data_inflight() <= + CongestionWindow::kMinimumCongestionWindowBytes) { + *minimum_congestion_window_start_time_ms_ = now_ms; + minimum_congestion_window_start_round_ = round; + } + } else { + if (now_ms - *minimum_congestion_window_start_time_ms_ >= + kProbeRttDurationMs && + round - minimum_congestion_window_start_round_ >= + kProbeRttDurationRounds) + EnterProbeBw(now_ms); + } +} int64_t BbrBweSender::TimeUntilNextProcess() { return 100; diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h index a4d8d5ef63..2782f353d0 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h @@ -17,6 +17,8 @@ #include #include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" +#include "webrtc/rtc_base/optional.h" +#include "webrtc/rtc_base/random.h" namespace webrtc { namespace testing { @@ -59,13 +61,16 @@ class BbrBweSender : public BweSender { void TryExitingStartup(); void TryExitingDrain(int64_t now_ms); void EnterProbeBw(int64_t now_ms); - void EnterProbeRtt(int64_t now_ms); void TryUpdatingCyclePhase(int64_t now_ms); void TryEnteringProbeRtt(int64_t now_ms); - void TryExitingProbeRtt(int64_t now_ms); + void TryExitingProbeRtt(int64_t now_ms, int64_t round); + size_t TargetCongestionWindow(float gain); Clock* const clock_; Mode mode_; std::unique_ptr max_bandwidth_filter_; + std::unique_ptr min_rtt_filter_; + std::unique_ptr congestion_window_; + std::unique_ptr rand_; uint64_t round_count_; uint64_t last_packet_sent_; uint64_t round_trip_end_; @@ -75,6 +80,27 @@ class BbrBweSender : public BweSender { // If optimal bandwidth has been discovered and reached, (for example after // Startup mode) set this variable to true. bool full_bandwidth_reached_; + + // Entering time for PROBE_BW mode's cycle phase. + int64_t cycle_start_time_ms_; + + // Index number of the currently used gain value in PROBE_BW mode, from 0 to + // kGainCycleLength - 1. + int64_t cycle_index_; + + // Data inflight prior to the moment when last feedback was received. + size_t prior_in_flight_; + + // Time we entered PROBE_RTT mode. + int64_t probe_rtt_start_time_ms_; + + // First moment of time when data inflight decreased below + // kMinimumCongestionWindow in PROBE_RTT mode. + rtc::Optional minimum_congestion_window_start_time_ms_; + + // First round when data inflight decreased below kMinimumCongestionWindow in + // PROBE_RTT mode. + int64_t minimum_congestion_window_start_round_; }; class BbrBweReceiver : public BweReceiver { diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc index a52d17d711..3d357704b5 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.cc @@ -19,29 +19,27 @@ namespace webrtc { namespace testing { namespace bwe { namespace { -// kStartingCongestionWindow is used to set congestion window when bandwidth -// delay product is equal to zero, so that we don't set window to zero as well. -// Chosen randomly by me, because this value shouldn't make any significant -// difference, as bandwidth delay product is more than zero almost every time. -const int kStartingCongestionWindow = 6000; -// Size of congestion window while in PROBE_RTT mode, suggested by BBR's source -// code of QUIC's implementation. -const int kMinimumCongestionWindow = 5840; +// kStartingCongestionWindowBytes is used to set congestion window when +// bandwidth delay product is equal to zero, so that we don't set window to zero +// as well. Chosen randomly by me, because this value shouldn't make any +// significant difference, as bandwidth delay product is more than zero almost +// every time. +const int kStartingCongestionWindowBytes = 6000; } // namespace +const int CongestionWindow::kMinimumCongestionWindowBytes; + CongestionWindow::CongestionWindow() : data_inflight_bytes_(0) {} CongestionWindow::~CongestionWindow() {} -int CongestionWindow::GetCongestionWindow( - BbrBweSender::Mode mode, - int64_t bandwidth_estimate_bytes_per_ms, - int64_t min_rtt_ms, - float gain) { +int CongestionWindow::GetCongestionWindow(BbrBweSender::Mode mode, + int64_t bandwidth_estimate_bps, + rtc::Optional min_rtt_ms, + float gain) { if (mode == BbrBweSender::PROBE_RTT) - return kMinimumCongestionWindow; - return GetTargetCongestionWindow(bandwidth_estimate_bytes_per_ms, min_rtt_ms, - gain); + return CongestionWindow::kMinimumCongestionWindowBytes; + return GetTargetCongestionWindow(bandwidth_estimate_bps, min_rtt_ms, gain); } void CongestionWindow::PacketSent(size_t sent_packet_size_bytes) { @@ -53,16 +51,20 @@ void CongestionWindow::AckReceived(size_t received_packet_size_bytes) { } int CongestionWindow::GetTargetCongestionWindow( - int64_t bandwidth_estimate_bytes_per_ms, - int64_t min_rtt_ms, + int64_t bandwidth_estimate_bps, + rtc::Optional min_rtt_ms, float gain) { - int bdp = min_rtt_ms * bandwidth_estimate_bytes_per_ms; + // If we have no rtt sample yet, return the starting congestion window size. + if (!min_rtt_ms) + return gain * kStartingCongestionWindowBytes; + int bdp = *min_rtt_ms * bandwidth_estimate_bps; int congestion_window = bdp * gain; // Congestion window could be zero in rare cases, when either no bandwidth // estimate is available, or path's min_rtt value is zero. if (!congestion_window) - congestion_window = gain * kStartingCongestionWindow; - return std::max(congestion_window, kMinimumCongestionWindow); + congestion_window = gain * kStartingCongestionWindowBytes; + return std::max(congestion_window, + CongestionWindow::kMinimumCongestionWindowBytes); } } // namespace bwe } // namespace testing diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h index 4fc1a12548..b9b2300d19 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h @@ -14,19 +14,25 @@ #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" +#include "webrtc/rtc_base/optional.h" + namespace webrtc { namespace testing { namespace bwe { class CongestionWindow { public: + // Size of congestion window while in PROBE_RTT mode, suggested by BBR's + // source code of QUIC's implementation. + static const int kMinimumCongestionWindowBytes = 4000; + CongestionWindow(); ~CongestionWindow(); int GetCongestionWindow(BbrBweSender::Mode mode, int64_t bandwidth_estimate, - int64_t min_rtt, + rtc::Optional min_rtt, float gain); int GetTargetCongestionWindow(int64_t bandwidth_estimate, - int64_t min_rtt, + rtc::Optional min_rtt, float gain); // Packet sent from sender, meaning it is inflight until we receive it and we // should add packet's size to data_inflight. diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc index bc0d370bca..0c6d59cbc6 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window_unittest.cc @@ -19,7 +19,7 @@ namespace bwe { namespace { // These are the same values used in CongestionWindow class. const int64_t kStartingCongestionWindow = 6000; -const int64_t kMinimumCongestionWindow = 5840; +const int64_t kMinimumCongestionWindow = 4000; } // namespace TEST(CongestionWindowTest, InitializationCheck) { @@ -46,35 +46,38 @@ TEST(CongestionWindowTest, DataInflight) { TEST(CongestionWindowTest, ZeroBandwidthDelayProduct) { CongestionWindow congestion_window; int64_t target_congestion_window = - congestion_window.GetTargetCongestionWindow(100, 0, 2.885f); + congestion_window.GetTargetCongestionWindow( + 100, rtc::Optional(0), 2.885f); EXPECT_EQ(target_congestion_window, 2.885f * kStartingCongestionWindow); } TEST(CongestionWindowTest, BelowMinimumTargetCongestionWindow) { CongestionWindow congestion_window; int64_t target_congestion_window = - congestion_window.GetTargetCongestionWindow(100, 2, 2.885f); + congestion_window.GetTargetCongestionWindow( + 100, rtc::Optional(2), 2.885f); EXPECT_EQ(target_congestion_window, kMinimumCongestionWindow); } TEST(CongestionWindowTest, AboveMinimumTargetCongestionWindow) { CongestionWindow congestion_window; int64_t target_congestion_window = - congestion_window.GetTargetCongestionWindow(100000, 2, 2.885f); + congestion_window.GetTargetCongestionWindow( + 100000, rtc::Optional(2), 2.885f); EXPECT_EQ(target_congestion_window, 577000); } TEST(CongestionWindowTest, MinimumCongestionWindow) { CongestionWindow congestion_window; - int64_t cwnd = congestion_window.GetCongestionWindow(BbrBweSender::PROBE_RTT, - 100, 100, 2.885f); + int64_t cwnd = congestion_window.GetCongestionWindow( + BbrBweSender::PROBE_RTT, 100, rtc::Optional(100), 2.885f); EXPECT_EQ(cwnd, kMinimumCongestionWindow); } TEST(CongestionWindowTest, CalculateCongestionWindow) { CongestionWindow congestion_window; - int64_t cwnd = congestion_window.GetCongestionWindow(BbrBweSender::STARTUP, - 100, 100, 2.885f); + int64_t cwnd = congestion_window.GetCongestionWindow( + BbrBweSender::STARTUP, 100, rtc::Optional(100l), 2.885f); EXPECT_EQ(cwnd, 28850); } } // namespace bwe diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc index 53fb59cbb0..708846b3dc 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc @@ -16,22 +16,49 @@ namespace testing { namespace bwe { MaxBandwidthFilter::MaxBandwidthFilter() : bandwidth_last_round_bytes_per_ms_(0), - round_bandwidth_updated_(0), - max_bandwidth_estimate_bytes_per_ms_(0), + max_bandwidth_estimate_bps_(0), rounds_without_growth_(0) {} MaxBandwidthFilter::~MaxBandwidthFilter() {} -// Rounds are units for packets rtt_time, after packet has been acknowledged, -// one round has passed from its send time. -void MaxBandwidthFilter::AddBandwidthSample(int64_t sample_bytes_per_ms, +// For detailed explanation about implementing bandwidth filter this way visit +// "Bbr design" doc. |sample_bps| was measured during |round|. +void MaxBandwidthFilter::AddBandwidthSample(int64_t sample_bps, int64_t round, size_t filter_size_round) { - if (round - round_bandwidth_updated_ >= filter_size_round || - sample_bytes_per_ms >= max_bandwidth_estimate_bytes_per_ms_) { - max_bandwidth_estimate_bytes_per_ms_ = sample_bytes_per_ms; - round_bandwidth_updated_ = round; + if (bandwidth_samples_[0].first == 0 || + sample_bps >= bandwidth_samples_[0].first || + round - bandwidth_samples_[2].second >= filter_size_round) + bandwidth_samples_[0] = bandwidth_samples_[1] = + bandwidth_samples_[2] = {sample_bps, round}; + if (sample_bps >= bandwidth_samples_[1].first) { + bandwidth_samples_[1] = {sample_bps, round}; + bandwidth_samples_[2] = bandwidth_samples_[1]; + } else { + if (sample_bps >= bandwidth_samples_[2].first) + bandwidth_samples_[2] = {sample_bps, round}; } + if (round - bandwidth_samples_[0].second >= filter_size_round) { + bandwidth_samples_[0] = bandwidth_samples_[1]; + bandwidth_samples_[1] = bandwidth_samples_[2]; + bandwidth_samples_[2] = {sample_bps, round}; + if (round - bandwidth_samples_[0].second >= filter_size_round) { + bandwidth_samples_[0] = bandwidth_samples_[1]; + bandwidth_samples_[1] = bandwidth_samples_[2]; + } + max_bandwidth_estimate_bps_ = bandwidth_samples_[0].first; + return; + } + if (bandwidth_samples_[1].first == bandwidth_samples_[0].first && + round - bandwidth_samples_[1].second > filter_size_round / 4) { + bandwidth_samples_[2] = bandwidth_samples_[1] = {sample_bps, round}; + max_bandwidth_estimate_bps_ = bandwidth_samples_[0].first; + return; + } + if (bandwidth_samples_[2].first == bandwidth_samples_[1].first && + round - bandwidth_samples_[2].second > filter_size_round / 2) + bandwidth_samples_[2] = {sample_bps, round}; + max_bandwidth_estimate_bps_ = bandwidth_samples_[0].first; } bool MaxBandwidthFilter::FullBandwidthReached(float growth_target, @@ -40,8 +67,8 @@ bool MaxBandwidthFilter::FullBandwidthReached(float growth_target, // found and full bandwidth is not reached. int64_t minimal_bandwidth = bandwidth_last_round_bytes_per_ms_ * growth_target; - if (max_bandwidth_estimate_bytes_per_ms_ >= minimal_bandwidth) { - bandwidth_last_round_bytes_per_ms_ = max_bandwidth_estimate_bytes_per_ms_; + if (max_bandwidth_estimate_bps_ >= minimal_bandwidth) { + bandwidth_last_round_bytes_per_ms_ = max_bandwidth_estimate_bps_; rounds_without_growth_ = 0; return false; } diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h index c873979573..6bb320f55a 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h @@ -12,8 +12,16 @@ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MAX_BANDWIDTH_FILTER_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MAX_BANDWIDTH_FILTER_H_ -#include -#include +#include +#include +#include +#include +#include +#include + +#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h" +#include "webrtc/modules/remote_bitrate_estimator/include/send_time_history.h" +#include "webrtc/modules/remote_bitrate_estimator/test/bwe.h" namespace webrtc { namespace testing { @@ -23,23 +31,20 @@ class MaxBandwidthFilter { MaxBandwidthFilter(); ~MaxBandwidthFilter(); - int64_t max_bandwidth_estimate_bytes_per_ms() { - return max_bandwidth_estimate_bytes_per_ms_; - } + int64_t max_bandwidth_estimate_bps() { return max_bandwidth_estimate_bps_; } - // Save bandwidth sample for the current round. We save bandwidth samples for - // past 10 rounds to provide better bandwidth estimate. + // Adds bandwidth sample to the bandwidth filter. void AddBandwidthSample(int64_t sample, int64_t round, size_t filter_size); - // Check if bandwidth has grown by certain multiplier for past x rounds, - // to decide whether or not full bandwidth was reached. + // Checks if bandwidth has grown by certain multiplier for past x rounds, + // to decide whether or full bandwidth was reached. bool FullBandwidthReached(float growth_target, int max_rounds_without_growth); private: int64_t bandwidth_last_round_bytes_per_ms_; - uint64_t round_bandwidth_updated_; - int64_t max_bandwidth_estimate_bytes_per_ms_; + int64_t max_bandwidth_estimate_bps_; int64_t rounds_without_growth_; + std::pair bandwidth_samples_[3]; }; } // namespace bwe } // namespace testing diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc index 36d72753a0..7f97f2a33d 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter_unittest.cc @@ -17,27 +17,43 @@ namespace testing { namespace bwe { TEST(MaxBandwidthFilterTest, InitializationCheck) { MaxBandwidthFilter max_bandwidth_filter; - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bytes_per_ms(), 0); + EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 0); } TEST(MaxBandwidthFilterTest, AddOneBandwidthSample) { MaxBandwidthFilter max_bandwidth_filter; max_bandwidth_filter.AddBandwidthSample(13, 4, 10); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bytes_per_ms(), 13); + EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 13); } TEST(MaxBandwidthFilterTest, AddSeveralBandwidthSamples) { MaxBandwidthFilter max_bandwidth_filter; max_bandwidth_filter.AddBandwidthSample(10, 5, 10); max_bandwidth_filter.AddBandwidthSample(13, 6, 10); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bytes_per_ms(), 13); + EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 13); } -TEST(MaxBandwidthFilterTest, SampleTimeOut) { +TEST(MaxBandwidthFilterTest, FirstSampleTimeOut) { MaxBandwidthFilter max_bandwidth_filter; max_bandwidth_filter.AddBandwidthSample(13, 5, 10); max_bandwidth_filter.AddBandwidthSample(10, 15, 10); - EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bytes_per_ms(), 10); + EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 10); +} + +TEST(MaxBandwidthFilterTest, SecondSampleBecomesTheFirst) { + MaxBandwidthFilter max_bandwidth_filter; + max_bandwidth_filter.AddBandwidthSample(4, 5, 10); + max_bandwidth_filter.AddBandwidthSample(3, 10, 10); + max_bandwidth_filter.AddBandwidthSample(2, 15, 10); + EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 3); +} + +TEST(MaxBandwidthFilterTest, ThirdSampleBecomesTheFirst) { + MaxBandwidthFilter max_bandwidth_filter; + max_bandwidth_filter.AddBandwidthSample(4, 5, 10); + max_bandwidth_filter.AddBandwidthSample(3, 10, 10); + max_bandwidth_filter.AddBandwidthSample(2, 25, 10); + EXPECT_EQ(max_bandwidth_filter.max_bandwidth_estimate_bps(), 2); } TEST(MaxBandwidthFilterTest, FullBandwidthReached) {