diff --git a/api/transport/goog_cc_factory.cc b/api/transport/goog_cc_factory.cc index 00f6a2e609..2187da36c2 100644 --- a/api/transport/goog_cc_factory.cc +++ b/api/transport/goog_cc_factory.cc @@ -10,7 +10,7 @@ #include "api/transport/goog_cc_factory.h" -#include +#include #include "absl/memory/memory.h" #include "modules/congestion_controller/goog_cc/goog_cc_network_control.h" @@ -18,21 +18,37 @@ namespace webrtc { GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( RtcEventLog* event_log) - : event_log_(event_log), network_state_predictor_factory_(nullptr) {} + : event_log_(event_log) {} GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( - RtcEventLog* event_log, - NetworkStatePredictorFactoryInterface* network_state_predictor_factory) - : event_log_(event_log), - network_state_predictor_factory_(network_state_predictor_factory) {} + NetworkStatePredictorFactoryInterface* network_state_predictor_factory) { + factory_config_.network_state_predictor_factory = + network_state_predictor_factory; +} + +GoogCcNetworkControllerFactory::GoogCcNetworkControllerFactory( + GoogCcFactoryConfig config) + : factory_config_(std::move(config)) {} std::unique_ptr GoogCcNetworkControllerFactory::Create(NetworkControllerConfig config) { - return absl::make_unique( - event_log_, config, false, - network_state_predictor_factory_ - ? network_state_predictor_factory_->CreateNetworkStatePredictor() - : nullptr); + if (event_log_) + config.event_log = event_log_; + GoogCcConfig goog_cc_config; + goog_cc_config.feedback_only = factory_config_.feedback_only; + if (factory_config_.network_state_estimator_factory) { + RTC_DCHECK(config.key_value_config); + goog_cc_config.network_state_estimator = + factory_config_.network_state_estimator_factory->Create( + config.key_value_config); + } + if (factory_config_.network_state_predictor_factory) { + goog_cc_config.network_state_predictor = + factory_config_.network_state_predictor_factory + ->CreateNetworkStatePredictor(); + } + return absl::make_unique(config, + std::move(goog_cc_config)); } TimeDelta GoogCcNetworkControllerFactory::GetProcessInterval() const { @@ -42,16 +58,8 @@ TimeDelta GoogCcNetworkControllerFactory::GetProcessInterval() const { GoogCcFeedbackNetworkControllerFactory::GoogCcFeedbackNetworkControllerFactory( RtcEventLog* event_log) - : event_log_(event_log) {} - -std::unique_ptr -GoogCcFeedbackNetworkControllerFactory::Create(NetworkControllerConfig config) { - return absl::make_unique(event_log_, config, true, - nullptr); + : GoogCcNetworkControllerFactory(event_log) { + factory_config_.feedback_only = true; } -TimeDelta GoogCcFeedbackNetworkControllerFactory::GetProcessInterval() const { - const int64_t kUpdateIntervalMs = 25; - return TimeDelta::ms(kUpdateIntervalMs); -} } // namespace webrtc diff --git a/api/transport/goog_cc_factory.h b/api/transport/goog_cc_factory.h index dbf4fe174e..fb85c78825 100644 --- a/api/transport/goog_cc_factory.h +++ b/api/transport/goog_cc_factory.h @@ -18,35 +18,39 @@ namespace webrtc { class RtcEventLog; +struct GoogCcFactoryConfig { + std::unique_ptr + network_state_estimator_factory = nullptr; + NetworkStatePredictorFactoryInterface* network_state_predictor_factory = + nullptr; + bool feedback_only = false; +}; + class GoogCcNetworkControllerFactory : public NetworkControllerFactoryInterface { public: explicit GoogCcNetworkControllerFactory(RtcEventLog* event_log); explicit GoogCcNetworkControllerFactory( - RtcEventLog* event_log, NetworkStatePredictorFactoryInterface* network_state_predictor_factory); + + explicit GoogCcNetworkControllerFactory(GoogCcFactoryConfig config); std::unique_ptr Create( NetworkControllerConfig config) override; TimeDelta GetProcessInterval() const override; - private: - RtcEventLog* const event_log_; - NetworkStatePredictorFactoryInterface* const network_state_predictor_factory_; + protected: + RtcEventLog* const event_log_ = nullptr; + GoogCcFactoryConfig factory_config_; }; // Factory to create packet feedback only GoogCC, this can be used for // connections providing packet receive time feedback but no other reports. class GoogCcFeedbackNetworkControllerFactory - : public NetworkControllerFactoryInterface { + : public GoogCcNetworkControllerFactory { public: explicit GoogCcFeedbackNetworkControllerFactory(RtcEventLog* event_log); - std::unique_ptr Create( - NetworkControllerConfig config) override; - TimeDelta GetProcessInterval() const override; - - private: - RtcEventLog* const event_log_; }; + } // namespace webrtc #endif // API_TRANSPORT_GOOG_CC_FACTORY_H_ diff --git a/api/transport/network_control.h b/api/transport/network_control.h index 53ac10ea07..99f1491f25 100644 --- a/api/transport/network_control.h +++ b/api/transport/network_control.h @@ -17,6 +17,8 @@ #include "api/transport/webrtc_key_value_config.h" namespace webrtc { +// TODO(srte): Remove this forward declaration when this is in api. +class RtcEventLog; class TargetTransferRateObserver { public: @@ -44,6 +46,8 @@ struct NetworkControllerConfig { // Optional override of configuration of WebRTC internals. Using nullptr here // indicates that the field trial API will be used. const WebRtcKeyValueConfig* key_value_config = nullptr; + // Optional override of event log. + RtcEventLog* event_log = nullptr; }; // NetworkControllerInterface is implemented by network controllers. A network @@ -94,6 +98,24 @@ class NetworkControllerFactoryInterface { // OnProcessInterval calls. virtual TimeDelta GetProcessInterval() const = 0; }; + +// Under development, subject to change without notice. +class NetworkStateEstimator { + public: + // Gets the current best estimate according to the estimator. + virtual absl::optional GetCurrentEstimate() = 0; + // Called with per packet feedback regarding receive time. + virtual void OnTransportPacketsFeedback(const TransportPacketsFeedback&) = 0; + // Called when the receiving or sending endpoint changes address. + virtual void OnRouteChange(const NetworkRouteChange&) = 0; + virtual ~NetworkStateEstimator() = default; +}; +class NetworkStateEstimatorFactory { + public: + virtual std::unique_ptr Create( + const WebRtcKeyValueConfig* key_value_config) = 0; + virtual ~NetworkStateEstimatorFactory() = default; +}; } // namespace webrtc #endif // API_TRANSPORT_NETWORK_CONTROL_H_ diff --git a/api/transport/network_types.h b/api/transport/network_types.h index 730e41b5cd..3e0615da58 100644 --- a/api/transport/network_types.h +++ b/api/transport/network_types.h @@ -212,6 +212,22 @@ struct ProcessInterval { Timestamp at_time = Timestamp::PlusInfinity(); absl::optional pacer_queue; }; + +// Under development, subject to change without notice. +struct NetworkStateEstimate { + Timestamp last_feed_time = Timestamp::MinusInfinity(); + Timestamp last_send_time = Timestamp::MinusInfinity(); + TimeDelta time_delta = TimeDelta::MinusInfinity(); + DataRate link_capacity = DataRate::MinusInfinity(); + DataRate link_capacity_std_dev = DataRate::MinusInfinity(); + DataRate link_capacity_min = DataRate::MinusInfinity(); + double cross_traffic_ratio; + TimeDelta pre_link_buffer_delay = TimeDelta::MinusInfinity(); + TimeDelta post_link_buffer_delay = TimeDelta::MinusInfinity(); + TimeDelta propagation_delay = TimeDelta::MinusInfinity(); + double cross_delay_rate; + double spike_delay_rate; +}; } // namespace webrtc #endif // API_TRANSPORT_NETWORK_TYPES_H_ diff --git a/call/rtp_transport_controller_send.cc b/call/rtp_transport_controller_send.cc index 11e35a99e1..203d41e751 100644 --- a/call/rtp_transport_controller_send.cc +++ b/call/rtp_transport_controller_send.cc @@ -70,8 +70,7 @@ RtpTransportControllerSend::RtpTransportControllerSend( observer_(nullptr), controller_factory_override_(controller_factory), controller_factory_fallback_( - absl::make_unique(event_log, - predictor_factory)), + absl::make_unique(predictor_factory)), process_interval_(controller_factory_fallback_->GetProcessInterval()), last_report_block_time_(Timestamp::ms(clock_->TimeInMilliseconds())), reset_feedback_on_route_change_( @@ -87,6 +86,8 @@ RtpTransportControllerSend::RtpTransportControllerSend( "rtp_send_controller", TaskQueueFactory::Priority::NORMAL)) { initial_config_.constraints = ConvertConstraints(bitrate_config, clock_); + initial_config_.event_log = event_log; + initial_config_.key_value_config = &trial_based_config_; RTC_DCHECK(bitrate_config.start_bitrate_bps > 0); pacer_.SetPacingRates(bitrate_config.start_bitrate_bps, 0); diff --git a/call/rtp_transport_controller_send.h b/call/rtp_transport_controller_send.h index 43dc1a0076..df4892ce64 100644 --- a/call/rtp_transport_controller_send.h +++ b/call/rtp_transport_controller_send.h @@ -132,6 +132,7 @@ class RtpTransportControllerSend final void UpdateControlState() RTC_RUN_ON(task_queue_); Clock* const clock_; + const FieldTrialBasedConfig trial_based_config_; PacketRouter packet_router_; std::vector> video_rtp_senders_; PacedSender pacer_; diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/modules/congestion_controller/goog_cc/delay_based_bwe.cc index f551ca58b4..450449f61d 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -14,9 +14,9 @@ #include #include #include +#include #include "absl/memory/memory.h" -#include "api/transport/network_types.h" // For PacedPacketInfo #include "logging/rtc_event_log/events/rtc_event.h" #include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h" #include "logging/rtc_event_log/rtc_event_log.h" @@ -117,6 +117,7 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( const std::vector& packet_feedback_vector, absl::optional acked_bitrate, absl::optional probe_bitrate, + absl::optional network_estimate, bool in_alr, Timestamp at_time) { RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), @@ -158,7 +159,9 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( // against building very large network queues. return Result(); } + rate_control_.SetNetworkStateEstimate(network_estimate); return MaybeUpdateEstimate(acked_bitrate, probe_bitrate, + std::move(network_estimate), recovered_from_overuse, in_alr, at_time); } @@ -202,6 +205,7 @@ void DelayBasedBwe::IncomingPacketFeedback( DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( absl::optional acked_bitrate, absl::optional probe_bitrate, + absl::optional state_estimate, bool recovered_from_overuse, bool in_alr, Timestamp at_time) { diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe.h b/modules/congestion_controller/goog_cc/delay_based_bwe.h index 34d356e847..efd5edb704 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -18,6 +18,7 @@ #include "absl/types/optional.h" #include "api/network_state_predictor.h" +#include "api/transport/network_types.h" #include "api/transport/webrtc_key_value_config.h" #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h" #include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h" @@ -53,6 +54,7 @@ class DelayBasedBwe { const std::vector& packet_feedback_vector, absl::optional acked_bitrate, absl::optional probe_bitrate, + absl::optional network_estimate, bool in_alr, Timestamp at_time); void OnRttUpdate(TimeDelta avg_rtt); @@ -66,11 +68,13 @@ class DelayBasedBwe { friend class GoogCcStatePrinter; void IncomingPacketFeedback(const PacketFeedback& packet_feedback, Timestamp at_time); - Result MaybeUpdateEstimate(absl::optional acked_bitrate, - absl::optional probe_bitrate, - bool recovered_from_overuse, - bool in_alr, - Timestamp at_time); + Result MaybeUpdateEstimate( + absl::optional acked_bitrate, + absl::optional probe_bitrate, + absl::optional state_estimate, + bool recovered_from_overuse, + bool in_alr, + Timestamp at_time); // Updates the current remote rate estimate and returns true if a valid // estimate exists. bool UpdateEstimate(Timestamp now, diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe_unittest.cc b/modules/congestion_controller/goog_cc/delay_based_bwe_unittest.cc index 98bb17af83..9a602c2391 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe_unittest.cc +++ b/modules/congestion_controller/goog_cc/delay_based_bwe_unittest.cc @@ -29,9 +29,10 @@ constexpr Timestamp kDummyTimestamp = Timestamp::Seconds<1000>(); TEST_F(DelayBasedBweTest, NoCrashEmptyFeedback) { std::vector packet_feedback_vector; - bitrate_estimator_->IncomingPacketFeedbackVector(packet_feedback_vector, - absl::nullopt, absl::nullopt, - false, kDummyTimestamp); + bitrate_estimator_->IncomingPacketFeedbackVector( + packet_feedback_vector, /*acked_bitrate*/ absl::nullopt, + /*probe_bitrate*/ absl::nullopt, /*network_estimate*/ absl::nullopt, + /*in_alr*/ false, kDummyTimestamp); } TEST_F(DelayBasedBweTest, NoCrashOnlyLostFeedback) { @@ -42,9 +43,10 @@ TEST_F(DelayBasedBweTest, NoCrashOnlyLostFeedback) { packet_feedback_vector.push_back(PacketFeedback(PacketFeedback::kNotReceived, PacketFeedback::kNoSendTime, 1, 1500, PacedPacketInfo())); - bitrate_estimator_->IncomingPacketFeedbackVector(packet_feedback_vector, - absl::nullopt, absl::nullopt, - false, kDummyTimestamp); + bitrate_estimator_->IncomingPacketFeedbackVector( + packet_feedback_vector, /*acked_bitrate*/ absl::nullopt, + /*probe_bitrate*/ absl::nullopt, /*network_estimate*/ absl::nullopt, + /*in_alr*/ false, kDummyTimestamp); } TEST_F(DelayBasedBweTest, ProbeDetection) { diff --git a/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc b/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc index 3611fee738..8baaf3d93b 100644 --- a/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc +++ b/modules/congestion_controller/goog_cc/delay_based_bwe_unittest_helper.cc @@ -211,7 +211,8 @@ void DelayBasedBweTest::IncomingFeedback(int64_t arrival_time_ms, DelayBasedBwe::Result result = bitrate_estimator_->IncomingPacketFeedbackVector( packets, acknowledged_bitrate_estimator_->bitrate(), - probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), false, + probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), + /*network_estimate*/ absl::nullopt, /*in_alr*/ false, Timestamp::ms(clock_.TimeInMilliseconds())); const uint32_t kDummySsrc = 0; if (result.updated) { @@ -252,7 +253,8 @@ bool DelayBasedBweTest::GenerateAndProcessFrame(uint32_t ssrc, DelayBasedBwe::Result result = bitrate_estimator_->IncomingPacketFeedbackVector( packets, acknowledged_bitrate_estimator_->bitrate(), - probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), false, + probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), + /*network_estimate*/ absl::nullopt, /*in_alr*/ false, Timestamp::ms(clock_.TimeInMilliseconds())); const uint32_t kDummySsrc = 0; if (result.updated) { diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 489f6a0f19..ca5728f68b 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -78,15 +78,12 @@ bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) { } } // namespace -GoogCcNetworkController::GoogCcNetworkController( - RtcEventLog* event_log, - NetworkControllerConfig config, - bool feedback_only, - std::unique_ptr network_state_predictor) +GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, + GoogCcConfig goog_cc_config) : key_value_config_(config.key_value_config ? config.key_value_config : &trial_based_config_), - event_log_(event_log), - packet_feedback_only_(feedback_only), + event_log_(config.event_log), + packet_feedback_only_(goog_cc_config.feedback_only), safe_reset_on_route_change_("Enabled"), safe_reset_acknowledged_rate_("ack"), use_stable_bandwidth_estimate_( @@ -97,7 +94,8 @@ GoogCcNetworkController::GoogCcNetworkController( IsNotDisabled(key_value_config_, "WebRTC-Bwe-MinAllocAsLowerBound")), rate_control_settings_( RateControlSettings::ParseFromKeyValueConfig(key_value_config_)), - probe_controller_(new ProbeController(key_value_config_, event_log)), + probe_controller_( + new ProbeController(key_value_config_, config.event_log)), congestion_window_pushback_controller_( rate_control_settings_.UseCongestionWindowPushback() ? absl::make_unique( @@ -106,10 +104,13 @@ GoogCcNetworkController::GoogCcNetworkController( bandwidth_estimation_( absl::make_unique(event_log_)), alr_detector_(absl::make_unique(key_value_config_)), - probe_bitrate_estimator_(new ProbeBitrateEstimator(event_log)), + probe_bitrate_estimator_(new ProbeBitrateEstimator(config.event_log)), + network_estimator_(std::move(goog_cc_config.network_state_estimator)), + network_state_predictor_( + std::move(goog_cc_config.network_state_predictor)), delay_based_bwe_(new DelayBasedBwe(key_value_config_, event_log_, - network_state_predictor.get())), + network_state_predictor_.get())), acknowledged_bitrate_estimator_( absl::make_unique(key_value_config_)), initial_config_(config), @@ -122,8 +123,7 @@ GoogCcNetworkController::GoogCcNetworkController( DataRate::Zero())), max_padding_rate_(config.stream_based_config.max_padding_rate.value_or( DataRate::Zero())), - max_total_allocated_bitrate_(DataRate::Zero()), - network_state_predictor_(std::move(network_state_predictor)) { + max_total_allocated_bitrate_(DataRate::Zero()) { RTC_DCHECK(config.constraints.at_time.IsFinite()); ParseFieldTrial( {&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_}, @@ -170,6 +170,8 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange( acknowledged_bitrate_estimator_.reset( new AcknowledgedBitrateEstimator(key_value_config_)); probe_bitrate_estimator_.reset(new ProbeBitrateEstimator(event_log_)); + if (network_estimator_) + network_estimator_->OnRouteChange(msg); delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, event_log_, network_state_predictor_.get())); bandwidth_estimation_->OnRouteChange(); @@ -472,14 +474,20 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( report.feedback_time); bandwidth_estimation_->IncomingPacketFeedbackVector(report); + if (network_estimator_) + network_estimator_->OnTransportPacketsFeedback(report); + NetworkControlUpdate update; bool recovered_from_overuse = false; bool backoff_in_alr = false; DelayBasedBwe::Result result; + absl::optional network_estimate = + network_estimator_ ? network_estimator_->GetCurrentEstimate() + : absl::nullopt; result = delay_based_bwe_->IncomingPacketFeedbackVector( received_feedback_vector, acknowledged_bitrate, probe_bitrate, - alr_start_time.has_value(), report.feedback_time); + network_estimate, alr_start_time.has_value(), report.feedback_time); if (result.updated) { if (result.probe) { diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/modules/congestion_controller/goog_cc/goog_cc_network_control.h index c4e8409b54..de1ea4f220 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -37,15 +37,16 @@ #include "rtc_base/experiments/rate_control_settings.h" namespace webrtc { - +struct GoogCcConfig { + std::unique_ptr network_state_estimator = nullptr; + std::unique_ptr network_state_predictor = nullptr; + bool feedback_only = false; +}; class GoogCcNetworkController : public NetworkControllerInterface { public: - GoogCcNetworkController( - RtcEventLog* event_log, - NetworkControllerConfig config, - bool feedback_only, - std::unique_ptr network_state_predictor); + GoogCcNetworkController(NetworkControllerConfig config, + GoogCcConfig goog_cc_config); ~GoogCcNetworkController() override; // NetworkControllerInterface @@ -91,6 +92,8 @@ class GoogCcNetworkController : public NetworkControllerInterface { std::unique_ptr bandwidth_estimation_; std::unique_ptr alr_detector_; std::unique_ptr probe_bitrate_estimator_; + std::unique_ptr network_estimator_; + std::unique_ptr network_state_predictor_; std::unique_ptr delay_based_bwe_; std::unique_ptr acknowledged_bitrate_estimator_; @@ -124,7 +127,6 @@ class GoogCcNetworkController : public NetworkControllerInterface { absl::optional current_data_window_; - std::unique_ptr network_state_predictor_; RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GoogCcNetworkController); }; diff --git a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc index 1e53d48f87..8f7b4f1aa2 100644 --- a/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc +++ b/modules/congestion_controller/goog_cc/goog_cc_network_control_unittest.cc @@ -107,7 +107,7 @@ void UpdatesTargetRateBasedOnLinkCapacity(std::string test_name = "") { class GoogCcNetworkControllerTest : public ::testing::Test { protected: GoogCcNetworkControllerTest() - : current_time_(Timestamp::ms(123456)), factory_(&event_log_, nullptr) {} + : current_time_(Timestamp::ms(123456)), factory_(&event_log_) {} ~GoogCcNetworkControllerTest() override {} void SetUp() override { diff --git a/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc b/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc index 51ff387892..aba3cec62c 100644 --- a/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc +++ b/modules/congestion_controller/goog_cc/test/goog_cc_printer.cc @@ -60,7 +60,7 @@ NetworkControlUpdate GoogCcStatePrinter::GetState(Timestamp at_time) const { GoogCcDebugFactory::GoogCcDebugFactory(RtcEventLog* event_log, GoogCcStatePrinter* printer) - : GoogCcNetworkControllerFactory(event_log, nullptr), printer_(printer) {} + : GoogCcNetworkControllerFactory(event_log), printer_(printer) {} std::unique_ptr GoogCcDebugFactory::Create( NetworkControllerConfig config) { diff --git a/modules/congestion_controller/send_side_congestion_controller.cc b/modules/congestion_controller/send_side_congestion_controller.cc index cf5b7a2934..1fbc63da39 100644 --- a/modules/congestion_controller/send_side_congestion_controller.cc +++ b/modules/congestion_controller/send_side_congestion_controller.cc @@ -410,7 +410,8 @@ void DEPRECATED_SendSideCongestionController::OnTransportFeedback( result = delay_based_bwe_->IncomingPacketFeedbackVector( feedback_vector, acknowledged_bitrate_estimator_->bitrate(), probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), - currently_in_alr, Timestamp::ms(clock_->TimeInMilliseconds())); + absl::nullopt, currently_in_alr, + Timestamp::ms(clock_->TimeInMilliseconds())); } if (result.updated) { bitrate_controller_->OnDelayBasedBweResult(result); diff --git a/modules/remote_bitrate_estimator/BUILD.gn b/modules/remote_bitrate_estimator/BUILD.gn index 3094e8c21d..7ce7cbaaff 100644 --- a/modules/remote_bitrate_estimator/BUILD.gn +++ b/modules/remote_bitrate_estimator/BUILD.gn @@ -43,6 +43,7 @@ rtc_static_library("remote_bitrate_estimator") { "../..:webrtc_common", "../../api:network_state_predictor_api", "../../api:rtp_headers", + "../../api/transport:network_control", "../../api/units:data_rate", "../../api/units:timestamp", "../../modules:module_api", diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.cc b/modules/remote_bitrate_estimator/aimd_rate_control.cc index 16b6ac7691..688b3b8b4e 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -17,6 +17,7 @@ #include #include +#include "api/transport/network_types.h" #include "api/units/data_rate.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "modules/remote_bitrate_estimator/overuse_detector.h" @@ -71,7 +72,10 @@ AimdRateControl::AimdRateControl() smoothing_experiment_( webrtc::field_trial::IsEnabled("WebRTC-Audio-BandwidthSmoothing")), initial_backoff_interval_("initial_backoff_interval"), - low_throughput_threshold_("low_throughput", DataRate::Zero()) { + low_throughput_threshold_("low_throughput", DataRate::Zero()), + capacity_deviation_ratio_threshold_("cap_thr", 0.2), + cross_traffic_factor_("cross", 1.0), + capacity_limit_deviation_factor_("cap_lim", 1) { // E.g // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms, // low_throughput:50kbps/ @@ -82,6 +86,10 @@ AimdRateControl::AimdRateControl() << " " << ToString(*initial_backoff_interval_) << "."; } RTC_LOG(LS_INFO) << "Using aimd rate control with back off factor " << beta_; + ParseFieldTrial( + {&capacity_deviation_ratio_threshold_, &cross_traffic_factor_, + &capacity_limit_deviation_factor_}, + field_trial::FindFullName("WebRTC-Bwe-AimdRateControl-NetworkState")); } AimdRateControl::~AimdRateControl() {} @@ -186,6 +194,11 @@ void AimdRateControl::SetEstimate(DataRate bitrate, Timestamp at_time) { } } +void AimdRateControl::SetNetworkStateEstimate( + const absl::optional& estimate) { + network_estimate_ = estimate; +} + double AimdRateControl::GetNearMaxIncreaseRateBpsPerSecond() const { RTC_DCHECK(!current_bitrate_.IsZero()); const TimeDelta kFrameInterval = TimeDelta::seconds(1) / 30; @@ -263,6 +276,21 @@ DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, break; case kRcDecrease: + if (network_estimate_ && capacity_deviation_ratio_threshold_) { + // If we have a low variance network estimate, we use it over the + // acknowledged rate to avoid dropping the bitrate too far. This avoids + // overcompensating when the send rate is lower than the capacity. + double deviation_ratio = network_estimate_->link_capacity_std_dev / + network_estimate_->link_capacity; + if (deviation_ratio < *capacity_deviation_ratio_threshold_) { + double available_ratio = + std::max(0.0, 1.0 - network_estimate_->cross_traffic_ratio * + cross_traffic_factor_); + DataRate available_rate = + network_estimate_->link_capacity * available_ratio; + estimated_throughput = std::max(available_rate, estimated_throughput); + } + } if (estimated_throughput > low_throughput_threshold_) { // Set bit rate to something slightly lower than the measured throughput // to get rid of any self-induced delay. @@ -323,6 +351,12 @@ DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate, if (new_bitrate > current_bitrate_ && new_bitrate > max_bitrate) { new_bitrate = std::max(current_bitrate_, max_bitrate); } + if (network_estimate_ && capacity_limit_deviation_factor_) { + DataRate upper_bound = network_estimate_->link_capacity + + network_estimate_->link_capacity_std_dev * + capacity_limit_deviation_factor_.Value(); + new_bitrate = std::min(new_bitrate, upper_bound); + } new_bitrate = std::max(new_bitrate, min_configured_bitrate_); return new_bitrate; } diff --git a/modules/remote_bitrate_estimator/aimd_rate_control.h b/modules/remote_bitrate_estimator/aimd_rate_control.h index 4d7bc7e1c7..dfefc485bf 100644 --- a/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -14,6 +14,7 @@ #include #include "absl/types/optional.h" +#include "api/transport/network_types.h" #include "api/units/data_rate.h" #include "api/units/timestamp.h" #include "modules/congestion_controller/goog_cc/link_capacity_estimator.h" @@ -52,6 +53,8 @@ class AimdRateControl { void SetRtt(TimeDelta rtt); DataRate Update(const RateControlInput* input, Timestamp at_time); void SetEstimate(DataRate bitrate, Timestamp at_time); + void SetNetworkStateEstimate( + const absl::optional& estimate); // Returns the increase rate when used bandwidth is near the link capacity. double GetNearMaxIncreaseRateBpsPerSecond() const; @@ -87,6 +90,7 @@ class AimdRateControl { DataRate current_bitrate_; DataRate latest_estimated_throughput_; LinkCapacityEstimator link_capacity_; + absl::optional network_estimate_; RateControlState rate_control_state_; Timestamp time_last_bitrate_change_; Timestamp time_last_bitrate_decrease_; @@ -99,6 +103,9 @@ class AimdRateControl { absl::optional last_decrease_; FieldTrialOptional initial_backoff_interval_; FieldTrialParameter low_throughput_threshold_; + FieldTrialOptional capacity_deviation_ratio_threshold_; + FieldTrialParameter cross_traffic_factor_; + FieldTrialOptional capacity_limit_deviation_factor_; }; } // namespace webrtc diff --git a/modules/remote_bitrate_estimator/test/estimators/send_side.cc b/modules/remote_bitrate_estimator/test/estimators/send_side.cc index c4b81c7fd1..bd701cfffb 100644 --- a/modules/remote_bitrate_estimator/test/estimators/send_side.cc +++ b/modules/remote_bitrate_estimator/test/estimators/send_side.cc @@ -92,8 +92,8 @@ void SendSideBweSender::GiveFeedback(const FeedbackPacket& feedback) { } DelayBasedBwe::Result result = bwe_->IncomingPacketFeedbackVector( packet_feedback_vector, acknowledged_bitrate_estimator_->bitrate(), - probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), false, - Timestamp::ms(clock_->TimeInMilliseconds())); + probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(), + absl::nullopt, false, Timestamp::ms(clock_->TimeInMilliseconds())); if (result.updated) bitrate_controller_->OnDelayBasedBweResult(result);