diff --git a/webrtc/modules/remote_bitrate_estimator/BUILD.gn b/webrtc/modules/remote_bitrate_estimator/BUILD.gn index 49b5d3285d..5a3afc65fd 100644 --- a/webrtc/modules/remote_bitrate_estimator/BUILD.gn +++ b/webrtc/modules/remote_bitrate_estimator/BUILD.gn @@ -75,6 +75,7 @@ if (rtc_include_tests) { "test/estimators/bbr.cc", "test/estimators/bbr.h", "test/estimators/congestion_window.h", + "test/estimators/max_bandwidth_filter.cc", "test/estimators/max_bandwidth_filter.h", "test/estimators/min_rtt_filter.h", "test/estimators/nada.cc", diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc index bc5c3f32e1..f211fc7c32 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc @@ -95,7 +95,7 @@ BweSender* CreateBweSender(BandwidthEstimatorType estimator, case kNadaEstimator: return new NadaBweSender(kbps, observer, clock); case kBbrEstimator: - return new BbrBweSender(); + return new BbrBweSender(clock); case kTcpEstimator: FALLTHROUGH(); case kNullEstimator: diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc index 1361277508..ad96b076dc 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc @@ -157,7 +157,7 @@ BbrBweFeedback::BbrBweFeedback( int flow_id, int64_t send_time_us, int64_t latest_send_time_ms, - const std::vector>& packet_feedback_vector) + const std::vector& packet_feedback_vector) : FeedbackPacket(flow_id, send_time_us, latest_send_time_ms), packet_feedback_vector_(packet_feedback_vector) {} diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc index 0d4dfb4c4b..fb7d29a387 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.cc @@ -11,18 +11,34 @@ #include "webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h" -#include -#include -#include - -#include "webrtc/base/logging.h" -#include "webrtc/modules/congestion_controller/delay_based_bwe.h" -#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" +#include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" namespace webrtc { namespace testing { namespace bwe { -BbrBweSender::BbrBweSender() : BweSender() { +namespace { +const int kFeedbackIntervalsMs = 100; +// BBR uses this value to double sending rate each round trip. Design document +// suggests using this value. +const float kHighGain = 2.885f; +// BBR uses this value to drain queues created during STARTUP in one round trip +// time. +const float kDrainGain = 1 / kHighGain; +// kStartupGrowthTarget and kMaxRoundsWithoutGrowth are chosen from +// experiments,according to design document. +const float kStartupGrowthTarget = 1.25f; +const int kMaxRoundsWithoutGrowth = 3; +} // namespace + +BbrBweSender::BbrBweSender(Clock* clock) + : BweSender(0), + clock_(clock), + mode_(STARTUP), + max_bandwidth_filter_(new MaxBandwidthFilter()), + round_count_(0), + last_packet_sent_(0), + round_trip_end_(0), + full_bandwidth_reached_(false) { // Initially enter Startup mode. EnterStartup(); } @@ -30,18 +46,66 @@ BbrBweSender::BbrBweSender() : BweSender() { BbrBweSender::~BbrBweSender() {} int BbrBweSender::GetFeedbackIntervalMs() const { - return 0; + return kFeedbackIntervalsMs; } -void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) {} +void BbrBweSender::GiveFeedback(const FeedbackPacket& feedback) { + const BbrBweFeedback& fb = static_cast(feedback); + // feedback_vector holds values of acknowledged packets' sequence numbers. + const std::vector& feedback_vector = fb.packet_feedback_vector(); + // Check if new round started for the connection. Round is the period of time + // from sending packet to its acknowledgement. + bool new_round_started = false; + if (!feedback_vector.empty()) { + uint64_t last_acked_packet = *feedback_vector.rbegin(); + if (last_acked_packet > round_trip_end_) { + new_round_started = true; + round_count_++; + round_trip_end_ = last_packet_sent_; + } + } + if (new_round_started && !full_bandwidth_reached_) { + full_bandwidth_reached_ = max_bandwidth_filter_->FullBandwidthReached( + kStartupGrowthTarget, kMaxRoundsWithoutGrowth); + } + int now = clock_->TimeInMilliseconds(); + switch (mode_) { + break; + case STARTUP: + TryExitingStartup(); + break; + case DRAIN: + TryExitingDrain(now); + break; + case PROBE_BW: + TryUpdatingCyclePhase(now); + break; + case PROBE_RTT: + TryExitingProbeRtt(now); + break; + } + TryEnteringProbeRtt(now); + // TODO(gnish): implement functions updating congestion window and pacing rate + // controllers. +} bool BbrBweSender::UpdateBandwidthAndMinRtt() { return false; } -void BbrBweSender::EnterStartup() {} +void BbrBweSender::EnterStartup() { + mode_ = STARTUP; + pacing_gain_ = kHighGain; + congestion_window_gain_ = kHighGain; +} -void BbrBweSender::TryExitingStartup() {} +void BbrBweSender::TryExitingStartup() { + if (full_bandwidth_reached_) { + mode_ = DRAIN; + pacing_gain_ = kDrainGain; + congestion_window_gain_ = kHighGain; + } +} void BbrBweSender::TryExitingDrain(int64_t now) {} @@ -49,22 +113,22 @@ void BbrBweSender::EnterProbeBw(int64_t now) {} void BbrBweSender::TryUpdatingCyclePhase(int64_t now) {} -void BbrBweSender::EnterProbeRtt(int64_t now) {} - +void BbrBweSender::TryEnteringProbeRtt(int64_t now) {} void BbrBweSender::TryExitingProbeRtt(int64_t now) {} int64_t BbrBweSender::TimeUntilNextProcess() { return 100; } -void BbrBweSender::OnPacketsSent(const Packets& packets) {} +void BbrBweSender::OnPacketsSent(const Packets& packets) { + last_packet_sent_ = + static_cast(packets.back())->sequence_number(); +} void BbrBweSender::Process() {} BbrBweReceiver::BbrBweReceiver(int flow_id) - : BweReceiver(flow_id, kReceivingRateTimeWindowMs), - clock_(0), - packet_feedbacks_() {} + : BweReceiver(flow_id, kReceivingRateTimeWindowMs), clock_(0) {} BbrBweReceiver::~BbrBweReceiver() {} diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h index ebb2e6e5ee..06e403b2d3 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/bbr.h @@ -12,14 +12,10 @@ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_BBR_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_BBR_H_ -#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 { @@ -30,7 +26,7 @@ class MinRttFilter; class CongestionWindow; class BbrBweSender : public BweSender { public: - BbrBweSender(); + explicit BbrBweSender(Clock* clock); virtual ~BbrBweSender(); enum Mode { // Startup phase. @@ -64,8 +60,21 @@ class BbrBweSender : public BweSender { void TryExitingDrain(int64_t now); void EnterProbeBw(int64_t now); void EnterProbeRtt(int64_t now); - void TryExitingProbeRtt(int64_t now); void TryUpdatingCyclePhase(int64_t now); + void TryEnteringProbeRtt(int64_t now); + void TryExitingProbeRtt(int64_t now); + Clock* const clock_; + Mode mode_; + std::unique_ptr max_bandwidth_filter_; + uint64_t round_count_; + uint64_t last_packet_sent_; + uint64_t round_trip_end_; + float pacing_gain_; + float congestion_window_gain_; + + // If optimal bandwidth has been discovered and reached, (for example after + // Startup mode) set this variable to true. + bool full_bandwidth_reached_; }; class BbrBweReceiver : public BweReceiver { @@ -78,7 +87,6 @@ class BbrBweReceiver : public BweReceiver { private: SimulatedClock clock_; - std::vector> packet_feedbacks_; }; } // 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 5a3a460d80..887e096004 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/congestion_window.h @@ -12,17 +12,6 @@ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_CONGESTION_WINDOW_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_CONGESTION_WINDOW_H_ -#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 { namespace bwe { @@ -39,10 +28,6 @@ class CongestionWindow { // Ack was received by sender, meaning // packet is no longer inflight. void AckReceived(); - - // Returnes whether or not data inflight has been under - // fixed value for past x rounds and y ms. - bool DataInflightDecreased(); }; } // namespace bwe } // namespace testing 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 new file mode 100644 index 0000000000..91e99346bf --- /dev/null +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.cc @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + * + */ + +#include "webrtc/modules/remote_bitrate_estimator/test/estimators/max_bandwidth_filter.h" + +namespace webrtc { +namespace testing { +namespace bwe { +MaxBandwidthFilter::MaxBandwidthFilter() {} + +MaxBandwidthFilter::~MaxBandwidthFilter() {} + +bool MaxBandwidthFilter::FullBandwidthReached(float growth_target, + int max_rounds_without_growth) { + // Minimal bandwidth necessary to assume that better bandwidth can still be + // found and full bandwidth is not reached. + int64_t minimal_bandwidth = bandwidth_last_round_ * growth_target; + if (max_bandwidth_estimate_ >= minimal_bandwidth) { + bandwidth_last_round_ = max_bandwidth_estimate_; + rounds_without_growth_ = 0; + return false; + } + rounds_without_growth_++; + if (rounds_without_growth_ >= max_rounds_without_growth) + return true; + return false; +} +} // namespace bwe +} // namespace testing +} // namespace webrtc 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 84fab2cc52..01c367cab7 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,16 +12,7 @@ #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 "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" +#include namespace webrtc { namespace testing { @@ -29,18 +20,24 @@ namespace bwe { class MaxBandwidthFilter { public: MaxBandwidthFilter(); + ~MaxBandwidthFilter(); - int64_t max_bandwidth_estimate(); + int64_t max_bandwidth_estimate() { return max_bandwidth_estimate_; } // Save bandwidth sample for the current round. // We save bandwidth samples for past 10 rounds to // provide better bandwidth estimate. - void AddBandwidthSample(int64_t round); + void AddBandwidthSample(int64_t sample, int64_t round); // Check if bandwidth has grown by certain multiplier for past x rounds, - // to decide whether or not delivery rate plateaued. - bool DeliveryRateGrows(); + // to decide whether or not full bandwidth was reached. + bool FullBandwidthReached(float growth_target, int max_rounds_without_growth); + + private: + int64_t bandwidth_last_round_; + int64_t max_bandwidth_estimate_; + int64_t rounds_without_growth_; }; } // namespace bwe } // namespace testing diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h index 9f9cfc8190..f41a4f0dad 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/min_rtt_filter.h @@ -12,16 +12,6 @@ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MIN_RTT_FILTER_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_ESTIMATORS_MIN_RTT_FILTER_H_ -#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 { namespace bwe { @@ -32,8 +22,8 @@ class MinRttFilter { int64_t min_rtt(); void UpdateMinRtt(int64_t min_rtt); - // Checks whether or last discovered min_rtt value - // is older than x seconds. + // Checks whether or not last discovered min_rtt value is older than x + // seconds. bool MinRttExpired(int64_t now); void set_min_rtt_discovery_time(int64_t discovery_time); }; diff --git a/webrtc/modules/remote_bitrate_estimator/test/packet.h b/webrtc/modules/remote_bitrate_estimator/test/packet.h index 223a50ba8f..525397c50d 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/packet.h +++ b/webrtc/modules/remote_bitrate_estimator/test/packet.h @@ -111,20 +111,18 @@ class FeedbackPacket : public Packet { class BbrBweFeedback : public FeedbackPacket { public: - BbrBweFeedback( - int flow_id, - int64_t send_time_us, - int64_t latest_send_time_ms, - const std::vector>& packet_feedback_vector); + BbrBweFeedback(int flow_id, + int64_t send_time_us, + int64_t latest_send_time_ms, + const std::vector& packet_feedback_vector); virtual ~BbrBweFeedback() {} - const std::vector>& packet_feedback_vector() - const { + const std::vector& packet_feedback_vector() const { return packet_feedback_vector_; } private: - const std::vector> packet_feedback_vector_; + const std::vector packet_feedback_vector_; }; class RembFeedback : public FeedbackPacket {