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}
This commit is contained in:
parent
773be36bd6
commit
d339dbc7d4
@ -11,13 +11,17 @@
|
||||
|
||||
#include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#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;
|
||||
|
||||
@ -17,6 +17,8 @@
|
||||
#include <vector>
|
||||
|
||||
#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<MaxBandwidthFilter> max_bandwidth_filter_;
|
||||
std::unique_ptr<MinRttFilter> min_rtt_filter_;
|
||||
std::unique_ptr<CongestionWindow> congestion_window_;
|
||||
std::unique_ptr<Random> 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<int64_t> 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 {
|
||||
|
||||
@ -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<int64_t> 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<int64_t> 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
|
||||
|
||||
@ -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<int64_t> min_rtt,
|
||||
float gain);
|
||||
int GetTargetCongestionWindow(int64_t bandwidth_estimate,
|
||||
int64_t min_rtt,
|
||||
rtc::Optional<int64_t> 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.
|
||||
|
||||
@ -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<int64_t>(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<int64_t>(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<int64_t>(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<int64_t>(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<int64_t>(100l), 2.885f);
|
||||
EXPECT_EQ(cwnd, 28850);
|
||||
}
|
||||
} // namespace bwe
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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 <cstddef>
|
||||
#include <cstdint>
|
||||
#include <climits>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#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<int64_t, size_t> bandwidth_samples_[3];
|
||||
};
|
||||
} // namespace bwe
|
||||
} // namespace testing
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user