From fa104372af1d46995f7be48b98d25b5f013639df Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 10 Oct 2022 10:47:45 +0300 Subject: [PATCH 01/70] Initial commit, backport main component. --- .../libwebrtc/api/transport/network_control.h | 10 +- .../libwebrtc/api/transport/network_types.cc | 9 +- .../libwebrtc/api/transport/network_types.h | 31 +- .../loss_based_bandwidth_estimation.cc | 69 +- .../loss_based_bandwidth_estimation.h | 31 +- .../bitrate_controller/loss_based_bwe_v2.cc | 996 ++++++++++++++++++ .../bitrate_controller/loss_based_bwe_v2.h | 178 ++++ .../send_side_bandwidth_estimation.cc | 441 ++++---- .../send_side_bandwidth_estimation.h | 86 +- .../goog_cc/acknowledged_bitrate_estimator.h | 16 +- ...cknowledged_bitrate_estimator_interface.cc | 93 ++ ...acknowledged_bitrate_estimator_interface.h | 87 ++ .../goog_cc/alr_detector.cc | 64 +- .../goog_cc/alr_detector.h | 34 +- .../goog_cc/delay_based_bwe.cc | 164 +-- .../goog_cc/delay_based_bwe.h | 57 +- .../delay_increase_detector_interface.h | 9 +- .../goog_cc/goog_cc_network_control.cc | 256 +++-- .../goog_cc/goog_cc_network_control.h | 38 +- .../goog_cc/inter_arrival_delta.cc | 139 +++ .../goog_cc/inter_arrival_delta.h | 90 ++ .../goog_cc/probe_controller.cc | 433 ++++---- .../goog_cc/probe_controller.h | 116 +- .../goog_cc/robust_throughput_estimator.cc | 189 ++++ .../goog_cc/robust_throughput_estimator.h | 50 + .../goog_cc/trendline_estimator.cc | 227 ++-- .../goog_cc/trendline_estimator.h | 56 +- .../include/bwe_defines.h | 2 + .../rtc_base/experiments/field_trial_list.cc | 59 ++ .../rtc_base/experiments/field_trial_list.h | 237 +++++ .../experiments/field_trial_parser.cc | 51 +- .../rtc_base/experiments/field_trial_parser.h | 40 + .../rtc_base/experiments/field_trial_units.cc | 16 + .../experiments/rate_control_settings.cc | 134 ++- .../experiments/rate_control_settings.h | 53 +- .../experiments/struct_parameters_parser.cc | 160 +++ .../experiments/struct_parameters_parser.h | 109 ++ 37 files changed, 3931 insertions(+), 899 deletions(-) create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.h create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.h create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.h diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h index f1ea92db8e..ec1549e13e 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h @@ -72,7 +72,11 @@ class NetworkControllerInterface { // Called round trip time has been calculated by protocol specific mechanisms. virtual NetworkControlUpdate OnRoundTripTimeUpdate(RoundTripTimeUpdate) = 0; // Called when a packet is sent on the network. - virtual NetworkControlUpdate OnSentPacket(SentPacket) = 0; + virtual NetworkControlUpdate OnSentPacket( + SentPacket) = 0; + // Called when a packet is received from the remote client. + virtual NetworkControlUpdate OnReceivedPacket( + ReceivedPacket) = 0; // Called when the stream specific configuration has been updated. virtual NetworkControlUpdate OnStreamsConfig(StreamsConfig) = 0; // Called when target transfer rate constraints has been changed. @@ -108,7 +112,11 @@ class NetworkStateEstimator { // Gets the current best estimate according to the estimator. virtual absl::optional GetCurrentEstimate() = 0; // Called with per packet feedback regarding receive time. + // Used when the NetworkStateEstimator runs in the sending endpoint. virtual void OnTransportPacketsFeedback(const TransportPacketsFeedback&) = 0; + // Called with per packet feedback regarding receive time. + // Used when the NetworkStateEstimator runs in the receiving endpoint. + virtual void OnReceivedPacket(const PacketResult&) {} // Called when the receiving or sending endpoint changes address. virtual void OnRouteChange(const NetworkRouteChange&) = 0; virtual ~NetworkStateEstimator() = default; diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc index d0a0c4a05f..7451940151 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc @@ -13,8 +13,7 @@ #include namespace webrtc { -// TODO(srte): Revert to using default after removing union member. -StreamsConfig::StreamsConfig() {} +StreamsConfig::StreamsConfig() = default; StreamsConfig::StreamsConfig(const StreamsConfig&) = default; StreamsConfig::~StreamsConfig() = default; @@ -49,7 +48,7 @@ std::vector TransportPacketsFeedback::ReceivedWithSendInfo() const { std::vector res; for (const PacketResult& fb : packet_feedbacks) { - if (fb.receive_time.IsFinite()) { + if (fb.IsReceived()) { res.push_back(fb); } } @@ -59,7 +58,7 @@ std::vector TransportPacketsFeedback::ReceivedWithSendInfo() std::vector TransportPacketsFeedback::LostWithSendInfo() const { std::vector res; for (const PacketResult& fb : packet_feedbacks) { - if (fb.receive_time.IsPlusInfinity()) { + if (!fb.IsReceived()) { res.push_back(fb); } } @@ -75,7 +74,7 @@ std::vector TransportPacketsFeedback::SortedByReceiveTime() const { std::vector res; for (const PacketResult& fb : packet_feedbacks) { - if (fb.receive_time.IsFinite()) { + if (fb.IsReceived()) { res.push_back(fb); } } diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index 20ab6aaba7..bd76166aa9 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -24,6 +24,19 @@ namespace webrtc { // Configuration +// Represents constraints and rates related to the currently enabled streams. +// This is used as input to the congestion controller via the StreamsConfig +// struct. +struct BitrateAllocationLimits { + // The total minimum send bitrate required by all sending streams. + DataRate min_allocatable_rate = DataRate::Zero(); + // The total maximum allocatable bitrate for all currently available streams. + DataRate max_allocatable_rate = DataRate::Zero(); + // The max bitrate to use for padding. The sum of the per-stream max padding + // rate. + DataRate max_padding_rate = DataRate::Zero(); +}; + // Use StreamsConfig for information about streams that is required for specific // adjustments to the algorithms in network controllers. Especially useful // for experiments. @@ -34,9 +47,9 @@ struct StreamsConfig { Timestamp at_time = Timestamp::PlusInfinity(); absl::optional requests_alr_probing; absl::optional pacing_factor; - union { - absl::optional min_total_allocated_bitrate = absl::nullopt; - }; + + // TODO(srte): Use BitrateAllocationLimits here. + absl::optional min_total_allocated_bitrate; absl::optional max_padding_rate; absl::optional max_total_allocated_bitrate; }; @@ -84,13 +97,20 @@ struct PacedPacketInfo { int probe_cluster_id = kNotAProbe; int probe_cluster_min_probes = -1; int probe_cluster_min_bytes = -1; + int probe_cluster_bytes_sent = 0; }; struct SentPacket { Timestamp send_time = Timestamp::PlusInfinity(); + // Size of packet with overhead up to IP layer. DataSize size = DataSize::Zero(); + // Size of preceeding packets that are not part of feedback. DataSize prior_unacked_data = DataSize::Zero(); + // Probe cluster id and parameters including bitrate, number of packets and + // number of bytes. PacedPacketInfo pacing_info; + // True if the packet is an audio packet, false for video, padding, RTX etc. + bool audio = false; // Transport independent sequence number, any tracked packet should have a // sequence number that is unique over the whole call and increasing by 1 for // each packet. @@ -138,6 +158,8 @@ struct PacketResult { PacketResult(const PacketResult&); ~PacketResult(); + inline bool IsReceived() const { return !receive_time.IsPlusInfinity(); } + SentPacket sent_packet; Timestamp receive_time = Timestamp::PlusInfinity(); }; @@ -166,6 +188,7 @@ struct TransportPacketsFeedback { struct NetworkEstimate { Timestamp at_time = Timestamp::PlusInfinity(); + // Deprecated, use TargetTransferRate::target_rate instead. DataRate bandwidth = DataRate::Infinity(); TimeDelta round_trip_time = TimeDelta::PlusInfinity(); TimeDelta bwe_period = TimeDelta::PlusInfinity(); @@ -199,6 +222,8 @@ struct TargetTransferRate { // The estimate on which the target rate is based on. NetworkEstimate network_estimate; DataRate target_rate = DataRate::Zero(); + DataRate stable_target_rate = DataRate::Zero(); + double cwnd_reduce_ratio = 0; }; // Contains updates of network controller comand state. Using optionals to diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.cc index b434510b99..988ce204cf 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.cc @@ -8,10 +8,11 @@ * be found in the AUTHORS file in the root of the source tree. */ +#include "absl/strings/match.h" #include "modules/bitrate_controller/loss_based_bandwidth_estimation.h" +#include "api/transport/webrtc_key_value_config.h" #include "api/units/data_rate.h" #include "api/units/time_delta.h" -#include "system_wrappers/source/field_trial.h" #include #include @@ -21,6 +22,10 @@ namespace webrtc { namespace { const char kBweLossBasedControl[] = "WebRTC-Bwe-LossBasedControl"; +// Expecting RTCP feedback to be sent with roughly 1s intervals, a 5s gap +// indicates a channel outage. +constexpr TimeDelta kMaxRtcpFeedbackInterval = TimeDelta::Millis<5000>(); + // Increase slower when RTT is high. double GetIncreaseFactor(const LossBasedControlConfig& config, TimeDelta rtt) { // Clamp the RTT @@ -70,10 +75,16 @@ double ExponentialUpdate(TimeDelta window, TimeDelta interval) { return 1.0f - exp(interval / window * -1.0); } +bool IsEnabled(const WebRtcKeyValueConfig* key_value_config, + absl::string_view name) { + return key_value_config->Lookup(name).find("Enabled") == 0; +} + } // namespace -LossBasedControlConfig::LossBasedControlConfig() - : enabled(field_trial::IsEnabled(kBweLossBasedControl)), +LossBasedControlConfig::LossBasedControlConfig( + const WebRtcKeyValueConfig* key_value_config) + : enabled(IsEnabled(key_value_config, kBweLossBasedControl)), min_increase_factor("min_incr", 1.02), max_increase_factor("max_incr", 1.08), increase_low_rtt("incr_low_rtt", TimeDelta::ms(200)), @@ -85,26 +96,27 @@ LossBasedControlConfig::LossBasedControlConfig() increase_offset("incr_offset", DataRate::bps(1000)), loss_bandwidth_balance_increase("balance_incr", DataRate::kbps(0.5)), loss_bandwidth_balance_decrease("balance_decr", DataRate::kbps(4)), + loss_bandwidth_balance_reset("balance_reset", DataRate::kbps(0.1)), loss_bandwidth_balance_exponent("exponent", 0.5), allow_resets("resets", false), decrease_interval("decr_intvl", TimeDelta::ms(300)), loss_report_timeout("timeout", TimeDelta::ms(6000)) { - std::string trial_string = field_trial::FindFullName(kBweLossBasedControl); ParseFieldTrial( {&min_increase_factor, &max_increase_factor, &increase_low_rtt, &increase_high_rtt, &decrease_factor, &loss_window, &loss_max_window, &acknowledged_rate_max_window, &increase_offset, &loss_bandwidth_balance_increase, &loss_bandwidth_balance_decrease, - &loss_bandwidth_balance_exponent, &allow_resets, &decrease_interval, - &loss_report_timeout}, - trial_string); + &loss_bandwidth_balance_reset, &loss_bandwidth_balance_exponent, + &allow_resets, &decrease_interval, &loss_report_timeout}, + key_value_config->Lookup(kBweLossBasedControl)); } LossBasedControlConfig::LossBasedControlConfig(const LossBasedControlConfig&) = default; LossBasedControlConfig::~LossBasedControlConfig() = default; -LossBasedBandwidthEstimation::LossBasedBandwidthEstimation() - : config_(LossBasedControlConfig()), +LossBasedBandwidthEstimation::LossBasedBandwidthEstimation( + const WebRtcKeyValueConfig* key_value_config) + : config_(key_value_config), average_loss_(0), average_loss_max_(0), loss_based_bitrate_(DataRate::Zero()), @@ -161,9 +173,14 @@ void LossBasedBandwidthEstimation::UpdateAcknowledgedBitrate( } } -void LossBasedBandwidthEstimation::Update(Timestamp at_time, - DataRate min_bitrate, - TimeDelta last_round_trip_time) { +DataRate LossBasedBandwidthEstimation::Update(Timestamp at_time, + DataRate min_bitrate, + DataRate wanted_bitrate, + TimeDelta last_round_trip_time) { + if (loss_based_bitrate_.IsZero()) { + loss_based_bitrate_ = wanted_bitrate; + } + // Only increase if loss has been low for some time. const double loss_estimate_for_increase = average_loss_max_; // Avoid multiple decreases from averaging over one loss spike. @@ -173,8 +190,15 @@ void LossBasedBandwidthEstimation::Update(Timestamp at_time, !has_decreased_since_last_loss_report_ && (at_time - time_last_decrease_ >= last_round_trip_time + config_.decrease_interval); + // If packet lost reports are too old, dont increase bitrate. + const bool loss_report_valid = + at_time - last_loss_packet_report_ < 1.2 * kMaxRtcpFeedbackInterval; - if (loss_estimate_for_increase < loss_increase_threshold()) { + if (loss_report_valid && config_.allow_resets && + loss_estimate_for_increase < loss_reset_threshold()) { + loss_based_bitrate_ = wanted_bitrate; + } else if (loss_report_valid && + loss_estimate_for_increase < loss_increase_threshold()) { // Increase bitrate by RTT-adaptive ratio. DataRate new_increased_bitrate = min_bitrate * GetIncreaseFactor(config_, last_round_trip_time) + @@ -200,14 +224,21 @@ void LossBasedBandwidthEstimation::Update(Timestamp at_time, loss_based_bitrate_ = new_decreased_bitrate; } } + return loss_based_bitrate_; } -void LossBasedBandwidthEstimation::Reset(DataRate bitrate) { +void LossBasedBandwidthEstimation::Initialize(DataRate bitrate) { loss_based_bitrate_ = bitrate; average_loss_ = 0; average_loss_max_ = 0; } +double LossBasedBandwidthEstimation::loss_reset_threshold() const { + return LossFromBitrate(loss_based_bitrate_, + config_.loss_bandwidth_balance_reset, + config_.loss_bandwidth_balance_exponent); +} + double LossBasedBandwidthEstimation::loss_increase_threshold() const { return LossFromBitrate(loss_based_bitrate_, config_.loss_bandwidth_balance_increase, @@ -223,14 +254,4 @@ double LossBasedBandwidthEstimation::loss_decrease_threshold() const { DataRate LossBasedBandwidthEstimation::decreased_bitrate() const { return config_.decrease_factor * acknowledged_bitrate_max_; } - -void LossBasedBandwidthEstimation::MaybeReset(DataRate bitrate) { - if (config_.allow_resets) - Reset(bitrate); -} - -void LossBasedBandwidthEstimation::SetInitialBitrate(DataRate bitrate) { - Reset(bitrate); -} - } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.h index 015c74505c..06948d4e38 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.h @@ -16,13 +16,15 @@ #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "rtc_base/experiments/field_trial_parser.h" +#include "api/transport/webrtc_key_value_config.h" + #include namespace webrtc { struct LossBasedControlConfig { - LossBasedControlConfig(); + explicit LossBasedControlConfig(const WebRtcKeyValueConfig* key_value_config); LossBasedControlConfig(const LossBasedControlConfig&); LossBasedControlConfig& operator=(const LossBasedControlConfig&) = default; ~LossBasedControlConfig(); @@ -38,23 +40,34 @@ struct LossBasedControlConfig { FieldTrialParameter increase_offset; FieldTrialParameter loss_bandwidth_balance_increase; FieldTrialParameter loss_bandwidth_balance_decrease; + FieldTrialParameter loss_bandwidth_balance_reset; FieldTrialParameter loss_bandwidth_balance_exponent; FieldTrialParameter allow_resets; FieldTrialParameter decrease_interval; FieldTrialParameter loss_report_timeout; }; +// Estimates an upper BWE limit based on loss. +// It requires knowledge about lost packets and acknowledged bitrate. +// Ie, this class require transport feedback. class LossBasedBandwidthEstimation { public: - LossBasedBandwidthEstimation(); - void Update(Timestamp at_time, - DataRate min_bitrate, - TimeDelta last_round_trip_time); + explicit LossBasedBandwidthEstimation( + const WebRtcKeyValueConfig* key_value_config); + // Returns the new estimate. + DataRate Update(Timestamp at_time, + DataRate min_bitrate, + DataRate wanted_bitrate, + TimeDelta last_round_trip_time); void UpdateAcknowledgedBitrate(DataRate acknowledged_bitrate, Timestamp at_time); - void MaybeReset(DataRate bitrate); - void SetInitialBitrate(DataRate bitrate); + void Initialize(DataRate bitrate); bool Enabled() const { return config_.enabled; } + // Returns true if LossBasedBandwidthEstimation is enabled and have + // received loss statistics. Ie, this class require transport feedback. + bool InUse() const { + return Enabled() && last_loss_packet_report_.IsFinite(); + } void UpdateLossStatistics(const std::vector& packet_results, Timestamp at_time); DataRate GetEstimate() const { return loss_based_bitrate_; } @@ -64,9 +77,11 @@ class LossBasedBandwidthEstimation { void Reset(DataRate bitrate); double loss_increase_threshold() const; double loss_decrease_threshold() const; + double loss_reset_threshold() const; + DataRate decreased_bitrate() const; - LossBasedControlConfig config_; + const LossBasedControlConfig config_; double average_loss_; double average_loss_max_; DataRate loss_based_bitrate_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc new file mode 100644 index 0000000000..6b5bc79632 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -0,0 +1,996 @@ +/* + * Copyright 2021 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. + */ +#define MS_CLASS "webrtc::LossBasedBweV2" + +#include "modules/bitrate_controller/loss_based_bwe_v2.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/algorithm/container.h" +#include "absl/types/optional.h" +// #include "api/field_trials_view.h" +#include "api/network_state_predictor.h" +#include "api/transport/network_types.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "modules/remote_bitrate_estimator/include/bwe_defines.h" +#include "rtc_base/experiments/field_trial_list.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "Logger.hpp" + +namespace webrtc { + +namespace { + +bool IsValid(DataRate datarate) { + return datarate.IsFinite(); +} + +bool IsValid(Timestamp timestamp) { + return timestamp.IsFinite(); +} + +struct PacketResultsSummary { + int num_packets = 0; + int num_lost_packets = 0; + DataSize total_size = DataSize::Zero(); + Timestamp first_send_time = Timestamp::PlusInfinity(); + Timestamp last_send_time = Timestamp::MinusInfinity(); +}; + +// Returns a `PacketResultsSummary` where `first_send_time` is `PlusInfinity, +// and `last_send_time` is `MinusInfinity`, if `packet_results` is empty. +PacketResultsSummary GetPacketResultsSummary( + std::vector packet_results) { + PacketResultsSummary packet_results_summary; + + packet_results_summary.num_packets = packet_results.size(); + for (const PacketResult& packet : packet_results) { + if (!packet.IsReceived()) { + packet_results_summary.num_lost_packets++; + } + packet_results_summary.total_size += packet.sent_packet.size; + packet_results_summary.first_send_time = std::min( + packet_results_summary.first_send_time, packet.sent_packet.send_time); + packet_results_summary.last_send_time = std::max( + packet_results_summary.last_send_time, packet.sent_packet.send_time); + } + + return packet_results_summary; +} + +double GetLossProbability(double inherent_loss, + DataRate loss_limited_bandwidth, + DataRate sending_rate) { + if (inherent_loss < 0.0 || inherent_loss > 1.0) { + /*MS_WARN_TAG(bwe, "Terent loss must be in [0,1]: %", inherent_loss);*/ + inherent_loss = std::min(std::max(inherent_loss, 0.0), 1.0); + } + if (!sending_rate.IsFinite()) { + //MS_WARN_TAG(bwe, "The sending rate must be finite: %s", sending_rate); + } + if (!loss_limited_bandwidth.IsFinite()) { + /*RTC_LOG(LS_WARNING) << "The loss limited bandwidth must be finite: " + << ToString(loss_limited_bandwidth);*/ + } + + double loss_probability = inherent_loss; + if (IsValid(sending_rate) && IsValid(loss_limited_bandwidth) && + (sending_rate > loss_limited_bandwidth)) { + loss_probability += (1 - inherent_loss) * + (sending_rate - loss_limited_bandwidth) / sending_rate; + } + return std::min(std::max(loss_probability, 1.0e-6), 1.0 - 1.0e-6); +} + +} // namespace + +LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) + : config_(CreateConfig(key_value_config)) { + if (!config_.has_value()) { +/* RTC_LOG(LS_VERBOSE) << "The configuration does not specify that the " + "estimator should be enabled, disabling it.";*/ + return; + } + if (!IsConfigValid()) { +/* RTC_LOG(LS_WARNING) + << "The configuration is not valid, disabling the estimator.";*/ + config_.reset(); + return; + } + + current_estimate_.inherent_loss = config_->initial_inherent_loss_estimate; + observations_.resize(config_->observation_window_size); + temporal_weights_.resize(config_->observation_window_size); + instant_upper_bound_temporal_weights_.resize( + config_->observation_window_size); + CalculateTemporalWeights(); +} + +bool LossBasedBweV2::IsEnabled() const { + return config_.has_value(); +} + +bool LossBasedBweV2::IsReady() const { + return IsEnabled() && IsValid(current_estimate_.loss_limited_bandwidth) && + num_observations_ > 0; +} + +DataRate LossBasedBweV2::GetBandwidthEstimate( + DataRate delay_based_limit) const { + if (!IsReady()) { +/* if (!IsEnabled()) { + RTC_LOG(LS_WARNING) + << "The estimator must be enabled before it can be used."; + } else { + if (!IsValid(current_estimate_.loss_limited_bandwidth)) { + RTC_LOG(LS_WARNING) + << "The estimator must be initialized before it can be used."; + } + if (num_observations_ <= 0) { + RTC_LOG(LS_WARNING) << "The estimator must receive enough loss " + "statistics before it can be used."; + } + }*/ + return IsValid(delay_based_limit) ? delay_based_limit + : DataRate::PlusInfinity(); + } + + if (delay_based_limit.IsFinite()) { + return std::min({current_estimate_.loss_limited_bandwidth, + GetInstantUpperBound(), delay_based_limit}); + } else { + return std::min(current_estimate_.loss_limited_bandwidth, + GetInstantUpperBound()); + } +} + +void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) { + if (IsValid(acknowledged_bitrate)) { + acknowledged_bitrate_ = acknowledged_bitrate; + } else { +/* RTC_LOG(LS_WARNING) << "The acknowledged bitrate must be finite: " + << ToString(acknowledged_bitrate);*/ + } +} + +void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) { + if (IsValid(bandwidth_estimate)) { + current_estimate_.loss_limited_bandwidth = bandwidth_estimate; + } else { +/* RTC_LOG(LS_WARNING) << "The bandwidth estimate must be finite: " + << ToString(bandwidth_estimate);*/ + } +} + +void LossBasedBweV2::SetMinBitrate(DataRate min_bitrate) { + if (IsValid(min_bitrate)) { + min_bitrate_ = min_bitrate; + } else { +/* RTC_LOG(LS_WARNING) << "The min bitrate must be finite: " + << ToString(min_bitrate);*/ + } +} + +void LossBasedBweV2::UpdateBandwidthEstimate( + std::vector packet_results, + DataRate delay_based_estimate, + BandwidthUsage delay_detector_state) { + if (!IsEnabled()) { +/* RTC_LOG(LS_WARNING) + << "The estimator must be enabled before it can be used.";*/ + return; + } + if (packet_results.empty()) { +/* RTC_LOG(LS_VERBOSE) + << "The estimate cannot be updated without any loss statistics.";*/ + return; + } + + if (!PushBackObservation(packet_results, delay_detector_state)) { + return; + } + + if (!IsValid(current_estimate_.loss_limited_bandwidth)) { +/* RTC_LOG(LS_VERBOSE) + << "The estimator must be initialized before it can be used.";*/ + return; + } + + ChannelParameters best_candidate = current_estimate_; + double objective_max = std::numeric_limits::lowest(); + for (ChannelParameters candidate : GetCandidates(delay_based_estimate)) { + NewtonsMethodUpdate(candidate); + + const double candidate_objective = GetObjective(candidate); + if (candidate_objective > objective_max) { + objective_max = candidate_objective; + best_candidate = candidate; + } + } + if (best_candidate.loss_limited_bandwidth < + current_estimate_.loss_limited_bandwidth) { + last_time_estimate_reduced_ = last_send_time_most_recent_observation_; + } + + // Do not increase the estimate if the average loss is greater than current + // inherent loss. + if (GetAverageReportedLossRatio() > best_candidate.inherent_loss && + config_->not_increase_if_inherent_loss_less_than_average_loss && + current_estimate_.loss_limited_bandwidth < + best_candidate.loss_limited_bandwidth) { + best_candidate.loss_limited_bandwidth = + current_estimate_.loss_limited_bandwidth; + } + + // Bound the estimate increase if: + // 1. The estimate is limited due to loss, and + // 2. The estimate has been increased for less than `delayed_increase_window` + // ago, and + // 3. The best candidate is greater than bandwidth_limit_in_current_window. + if (limited_due_to_loss_candidate_ && + recovering_after_loss_timestamp_.IsFinite() && + recovering_after_loss_timestamp_ + config_->delayed_increase_window > + last_send_time_most_recent_observation_ && + best_candidate.loss_limited_bandwidth > + bandwidth_limit_in_current_window_) { + best_candidate.loss_limited_bandwidth = bandwidth_limit_in_current_window_; + } + limited_due_to_loss_candidate_ = + delay_based_estimate.IsFinite() && + best_candidate.loss_limited_bandwidth < delay_based_estimate; + + if (limited_due_to_loss_candidate_ && + (recovering_after_loss_timestamp_.IsInfinite() || + recovering_after_loss_timestamp_ + config_->delayed_increase_window < + last_send_time_most_recent_observation_)) { + bandwidth_limit_in_current_window_ = std::max( + kCongestionControllerMinBitrate, + best_candidate.loss_limited_bandwidth * config_->max_increase_factor); + recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_; + } + + current_estimate_ = best_candidate; +} + +// Returns a `LossBasedBweV2::Config` iff the `key_value_config` specifies a +// configuration for the `LossBasedBweV2` which is explicitly enabled. +absl::optional LossBasedBweV2::CreateConfig( + const WebRtcKeyValueConfig* key_value_config) { + FieldTrialParameter enabled("Enabled", false); + FieldTrialParameter bandwidth_rampup_upper_bound_factor( + "BwRampupUpperBoundFactor", 1.1); + FieldTrialParameter rampup_acceleration_max_factor( + "BwRampupAccelMaxFactor", 0.0); + FieldTrialParameter rampup_acceleration_maxout_time( + "BwRampupAccelMaxoutTime", TimeDelta::seconds(60)); + FieldTrialList candidate_factors("CandidateFactors", + {1.05, 1.0, 0.95}); + FieldTrialParameter higher_bandwidth_bias_factor("HigherBwBiasFactor", + 0.00001); + FieldTrialParameter higher_log_bandwidth_bias_factor( + "HigherLogBwBiasFactor", 0.001); + FieldTrialParameter inherent_loss_lower_bound( + "InherentLossLowerBound", 1.0e-3); + FieldTrialParameter loss_threshold_of_high_bandwidth_preference( + "LossThresholdOfHighBandwidthPreference", 0.99); + FieldTrialParameter bandwidth_preference_smoothing_factor( + "BandwidthPreferenceSmoothingFactor", 0.002); + FieldTrialParameter inherent_loss_upper_bound_bandwidth_balance( + "InherentLossUpperBoundBwBalance", DataRate::kbps(15.0)); + FieldTrialParameter inherent_loss_upper_bound_offset( + "InherentLossUpperBoundOffset", 0.05); + FieldTrialParameter initial_inherent_loss_estimate( + "InitialInherentLossEstimate", 0.01); + FieldTrialParameter newton_iterations("NewtonIterations", 1); + FieldTrialParameter newton_step_size("NewtonStepSize", 0.5); + FieldTrialParameter append_acknowledged_rate_candidate( + "AckedRateCandidate", true); + FieldTrialParameter append_delay_based_estimate_candidate( + "DelayBasedCandidate", false); + FieldTrialParameter observation_duration_lower_bound( + "ObservationDurationLowerBound", TimeDelta::seconds(1)); + FieldTrialParameter observation_window_size("ObservationWindowSize", 20); + FieldTrialParameter sending_rate_smoothing_factor( + "SendingRateSmoothingFactor", 0.0); + FieldTrialParameter instant_upper_bound_temporal_weight_factor( + "InstantUpperBoundTemporalWeightFactor", 0.99); + FieldTrialParameter instant_upper_bound_bandwidth_balance( + "InstantUpperBoundBwBalance", DataRate::kbps(15.0)); + FieldTrialParameter instant_upper_bound_loss_offset( + "InstantUpperBoundLossOffset", 0.05); + FieldTrialParameter temporal_weight_factor("TemporalWeightFactor", + 0.99); + FieldTrialParameter bandwidth_backoff_lower_bound_factor( + "BwBackoffLowerBoundFactor", 1.0); + FieldTrialParameter trendline_integration_enabled( + "TrendlineIntegrationEnabled", false); + FieldTrialParameter trendline_observations_window_size( + "TrendlineObservationsWindowSize", 20); + FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1000.0); + FieldTrialParameter delayed_increase_window( + "DelayedIncreaseWindow", TimeDelta::ms(300)); + FieldTrialParameter use_acked_bitrate_only_when_overusing( + "UseAckedBitrateOnlyWhenOverusing", false); + FieldTrialParameter + not_increase_if_inherent_loss_less_than_average_loss( + "NotIncreaseIfInherentLossLessThanAverageLoss", false); + FieldTrialParameter high_loss_rate_threshold("HighLossRateThreshold", + 1.0); + FieldTrialParameter bandwidth_cap_at_high_loss_rate( + "BandwidthCapAtHighLossRate", DataRate::kbps(500.0)); + FieldTrialParameter slope_of_bwe_high_loss_func( + "SlopeOfBweHighLossFunc", 1000); + if (key_value_config) { + ParseFieldTrial({&enabled, + &bandwidth_rampup_upper_bound_factor, + &rampup_acceleration_max_factor, + &rampup_acceleration_maxout_time, + &candidate_factors, + &higher_bandwidth_bias_factor, + &higher_log_bandwidth_bias_factor, + &inherent_loss_lower_bound, + &loss_threshold_of_high_bandwidth_preference, + &bandwidth_preference_smoothing_factor, + &inherent_loss_upper_bound_bandwidth_balance, + &inherent_loss_upper_bound_offset, + &initial_inherent_loss_estimate, + &newton_iterations, + &newton_step_size, + &append_acknowledged_rate_candidate, + &append_delay_based_estimate_candidate, + &observation_duration_lower_bound, + &observation_window_size, + &sending_rate_smoothing_factor, + &instant_upper_bound_temporal_weight_factor, + &instant_upper_bound_bandwidth_balance, + &instant_upper_bound_loss_offset, + &temporal_weight_factor, + &bandwidth_backoff_lower_bound_factor, + &trendline_integration_enabled, + &trendline_observations_window_size, + &max_increase_factor, + &delayed_increase_window, + &use_acked_bitrate_only_when_overusing, + ¬_increase_if_inherent_loss_less_than_average_loss, + &high_loss_rate_threshold, + &bandwidth_cap_at_high_loss_rate, + &slope_of_bwe_high_loss_func}, + key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2")); + } + + absl::optional config; + if (!enabled.Get()) { + return config; + } + config.emplace(); + config->bandwidth_rampup_upper_bound_factor = + bandwidth_rampup_upper_bound_factor.Get(); + config->rampup_acceleration_max_factor = rampup_acceleration_max_factor.Get(); + config->rampup_acceleration_maxout_time = + rampup_acceleration_maxout_time.Get(); + config->candidate_factors = candidate_factors.Get(); + config->higher_bandwidth_bias_factor = higher_bandwidth_bias_factor.Get(); + config->higher_log_bandwidth_bias_factor = + higher_log_bandwidth_bias_factor.Get(); + config->inherent_loss_lower_bound = inherent_loss_lower_bound.Get(); + config->loss_threshold_of_high_bandwidth_preference = + loss_threshold_of_high_bandwidth_preference.Get(); + config->bandwidth_preference_smoothing_factor = + bandwidth_preference_smoothing_factor.Get(); + config->inherent_loss_upper_bound_bandwidth_balance = + inherent_loss_upper_bound_bandwidth_balance.Get(); + config->inherent_loss_upper_bound_offset = + inherent_loss_upper_bound_offset.Get(); + config->initial_inherent_loss_estimate = initial_inherent_loss_estimate.Get(); + config->newton_iterations = newton_iterations.Get(); + config->newton_step_size = newton_step_size.Get(); + config->append_acknowledged_rate_candidate = + append_acknowledged_rate_candidate.Get(); + config->append_delay_based_estimate_candidate = + append_delay_based_estimate_candidate.Get(); + config->observation_duration_lower_bound = + observation_duration_lower_bound.Get(); + config->observation_window_size = observation_window_size.Get(); + config->sending_rate_smoothing_factor = sending_rate_smoothing_factor.Get(); + config->instant_upper_bound_temporal_weight_factor = + instant_upper_bound_temporal_weight_factor.Get(); + config->instant_upper_bound_bandwidth_balance = + instant_upper_bound_bandwidth_balance.Get(); + config->instant_upper_bound_loss_offset = + instant_upper_bound_loss_offset.Get(); + config->temporal_weight_factor = temporal_weight_factor.Get(); + config->bandwidth_backoff_lower_bound_factor = + bandwidth_backoff_lower_bound_factor.Get(); + config->trendline_integration_enabled = trendline_integration_enabled.Get(); + config->trendline_observations_window_size = + trendline_observations_window_size.Get(); + config->max_increase_factor = max_increase_factor.Get(); + config->delayed_increase_window = delayed_increase_window.Get(); + config->use_acked_bitrate_only_when_overusing = + use_acked_bitrate_only_when_overusing.Get(); + config->not_increase_if_inherent_loss_less_than_average_loss = + not_increase_if_inherent_loss_less_than_average_loss.Get(); + config->high_loss_rate_threshold = high_loss_rate_threshold.Get(); + config->bandwidth_cap_at_high_loss_rate = + bandwidth_cap_at_high_loss_rate.Get(); + config->slope_of_bwe_high_loss_func = slope_of_bwe_high_loss_func.Get(); + return config; +} + +bool LossBasedBweV2::IsConfigValid() const { + if (!config_.has_value()) { + return false; + } + + bool valid = true; + + if (config_->bandwidth_rampup_upper_bound_factor <= 1.0) { +/* RTC_LOG(LS_WARNING) + << "The bandwidth rampup upper bound factor must be greater than 1: " + << config_->bandwidth_rampup_upper_bound_factor;*/ + valid = false; + } + if (config_->rampup_acceleration_max_factor < 0.0) { +/* RTC_LOG(LS_WARNING) + << "The rampup acceleration max factor must be non-negative.: " + << config_->rampup_acceleration_max_factor;*/ + valid = false; + } + if (config_->rampup_acceleration_maxout_time <= TimeDelta::Zero()) { +/* RTC_LOG(LS_WARNING) + << "The rampup acceleration maxout time must be above zero: " + << config_->rampup_acceleration_maxout_time.seconds();*/ + valid = false; + } + for (double candidate_factor : config_->candidate_factors) { + if (candidate_factor <= 0.0) { + /* RTC_LOG(LS_WARNING) << "All candidate factors must be greater than zero: " + << candidate_factor;*/ + valid = false; + } + } + + // Ensure that the configuration allows generation of at least one candidate + // other than the current estimate. + if (!config_->append_acknowledged_rate_candidate && + !config_->append_delay_based_estimate_candidate && + !absl::c_any_of(config_->candidate_factors, + [](double cf) { return cf != 1.0; })) { +/* RTC_LOG(LS_WARNING) + << "The configuration does not allow generating candidates. Specify " + "a candidate factor other than 1.0, allow the acknowledged rate " + "to be a candidate, and/or allow the delay based estimate to be a " + "candidate.";*/ + valid = false; + } + + if (config_->higher_bandwidth_bias_factor < 0.0) { +/* RTC_LOG(LS_WARNING) + << "The higher bandwidth bias factor must be non-negative: " + << config_->higher_bandwidth_bias_factor;*/ + valid = false; + } + if (config_->inherent_loss_lower_bound < 0.0 || + config_->inherent_loss_lower_bound >= 1.0) { +/* RTC_LOG(LS_WARNING) << "The inherent loss lower bound must be in [0, 1): " + << config_->inherent_loss_lower_bound;*/ + valid = false; + } + if (config_->loss_threshold_of_high_bandwidth_preference < 0.0 || + config_->loss_threshold_of_high_bandwidth_preference >= 1.0) { +/* RTC_LOG(LS_WARNING) + << "The loss threshold of high bandwidth preference must be in [0, 1): " + << config_->loss_threshold_of_high_bandwidth_preference;*/ + valid = false; + } + if (config_->bandwidth_preference_smoothing_factor <= 0.0 || + config_->bandwidth_preference_smoothing_factor > 1.0) { +/* RTC_LOG(LS_WARNING) + << "The bandwidth preference smoothing factor must be in (0, 1]: " + << config_->bandwidth_preference_smoothing_factor;*/ + valid = false; + } + if (config_->inherent_loss_upper_bound_bandwidth_balance <= + DataRate::Zero()) { +/* RTC_LOG(LS_WARNING) + << "The inherent loss upper bound bandwidth balance " + "must be positive: " + << ToString(config_->inherent_loss_upper_bound_bandwidth_balance);*/ + valid = false; + } + if (config_->inherent_loss_upper_bound_offset < + config_->inherent_loss_lower_bound || + config_->inherent_loss_upper_bound_offset >= 1.0) { +/* RTC_LOG(LS_WARNING) << "The inherent loss upper bound must be greater " + "than or equal to the inherent " + "loss lower bound, which is " + << config_->inherent_loss_lower_bound + << ", and less than 1: " + << config_->inherent_loss_upper_bound_offset;*/ + valid = false; + } + if (config_->initial_inherent_loss_estimate < 0.0 || + config_->initial_inherent_loss_estimate >= 1.0) { +/* RTC_LOG(LS_WARNING) + << "The initial inherent loss estimate must be in [0, 1): " + << config_->initial_inherent_loss_estimate;*/ + valid = false; + } + if (config_->newton_iterations <= 0) { +/* RTC_LOG(LS_WARNING) << "The number of Newton iterations must be positive: " + << config_->newton_iterations;*/ + valid = false; + } + if (config_->newton_step_size <= 0.0) { +/* RTC_LOG(LS_WARNING) << "The Newton step size must be positive: " + << config_->newton_step_size;*/ + valid = false; + } + if (config_->observation_duration_lower_bound <= TimeDelta::Zero()) { +/* RTC_LOG(LS_WARNING) + << "The observation duration lower bound must be positive: " + << ToString(config_->observation_duration_lower_bound);*/ + valid = false; + } + if (config_->observation_window_size < 2) { +/* RTC_LOG(LS_WARNING) << "The observation window size must be at least 2: " + << config_->observation_window_size;*/ + valid = false; + } + if (config_->sending_rate_smoothing_factor < 0.0 || + config_->sending_rate_smoothing_factor >= 1.0) { +/* RTC_LOG(LS_WARNING) + << "The sending rate smoothing factor must be in [0, 1): " + << config_->sending_rate_smoothing_factor;*/ + valid = false; + } + if (config_->instant_upper_bound_temporal_weight_factor <= 0.0 || + config_->instant_upper_bound_temporal_weight_factor > 1.0) { +/* RTC_LOG(LS_WARNING) + << "The instant upper bound temporal weight factor must be in (0, 1]" + << config_->instant_upper_bound_temporal_weight_factor;*/ + valid = false; + } + if (config_->instant_upper_bound_bandwidth_balance <= DataRate::Zero()) { +/* RTC_LOG(LS_WARNING) + << "The instant upper bound bandwidth balance must be positive: " + << ToString(config_->instant_upper_bound_bandwidth_balance);*/ + valid = false; + } + if (config_->instant_upper_bound_loss_offset < 0.0 || + config_->instant_upper_bound_loss_offset >= 1.0) { +/* RTC_LOG(LS_WARNING) + << "The instant upper bound loss offset must be in [0, 1): " + << config_->instant_upper_bound_loss_offset;*/ + valid = false; + } + if (config_->temporal_weight_factor <= 0.0 || + config_->temporal_weight_factor > 1.0) { +/* RTC_LOG(LS_WARNING) << "The temporal weight factor must be in (0, 1]: " + << config_->temporal_weight_factor;*/ + valid = false; + } + if (config_->bandwidth_backoff_lower_bound_factor > 1.0) { +/* RTC_LOG(LS_WARNING) + << "The bandwidth backoff lower bound factor must not be greater than " + "1: " + << config_->bandwidth_backoff_lower_bound_factor;*/ + valid = false; + } + if (config_->trendline_observations_window_size < 1) { +/* RTC_LOG(LS_WARNING) << "The trendline window size must be at least 1: " + << config_->trendline_observations_window_size;*/ + valid = false; + } + if (config_->max_increase_factor <= 0.0) { +/* RTC_LOG(LS_WARNING) << "The maximum increase factor must be positive: " + << config_->max_increase_factor;*/ + valid = false; + } + if (config_->delayed_increase_window <= TimeDelta::Zero()) { +/* RTC_LOG(LS_WARNING) << "The delayed increase window must be positive: " + << config_->delayed_increase_window.ms();*/ + valid = false; + } + if (config_->high_loss_rate_threshold <= 0.0 || + config_->high_loss_rate_threshold > 1.0) { +/* RTC_LOG(LS_WARNING) << "The high loss rate threshold must be in (0, 1]: " + << config_->high_loss_rate_threshold;*/ + valid = false; + } + return valid; +} + +double LossBasedBweV2::GetAverageReportedLossRatio() const { + if (num_observations_ <= 0) { + return 0.0; + } + + double num_packets = 0; + double num_lost_packets = 0; + for (const Observation& observation : observations_) { + if (!observation.IsInitialized()) { + continue; + } + + double instant_temporal_weight = + instant_upper_bound_temporal_weights_[(num_observations_ - 1) - + observation.id]; + num_packets += instant_temporal_weight * observation.num_packets; + num_lost_packets += instant_temporal_weight * observation.num_lost_packets; + } + + return num_lost_packets / num_packets; +} + +DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound( + DataRate delay_based_estimate) const { + DataRate candidate_bandwidth_upper_bound = DataRate::PlusInfinity(); + if (limited_due_to_loss_candidate_) { + candidate_bandwidth_upper_bound = bandwidth_limit_in_current_window_; + } + + if (config_->trendline_integration_enabled) { + candidate_bandwidth_upper_bound = + std::min(GetInstantUpperBound(), candidate_bandwidth_upper_bound); + if (IsValid(delay_based_estimate)) { + candidate_bandwidth_upper_bound = + std::min(delay_based_estimate, candidate_bandwidth_upper_bound); + } + } + + if (!acknowledged_bitrate_.has_value()) + return candidate_bandwidth_upper_bound; + + candidate_bandwidth_upper_bound = + IsValid(candidate_bandwidth_upper_bound) + ? std::min(candidate_bandwidth_upper_bound, + config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_)) + : config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_); + + if (config_->rampup_acceleration_max_factor > 0.0) { + const TimeDelta time_since_bandwidth_reduced = std::min( + config_->rampup_acceleration_maxout_time, + std::max(TimeDelta::Zero(), last_send_time_most_recent_observation_ - + last_time_estimate_reduced_)); + const double rampup_acceleration = config_->rampup_acceleration_max_factor * + time_since_bandwidth_reduced / + config_->rampup_acceleration_maxout_time; + + candidate_bandwidth_upper_bound += + rampup_acceleration * (*acknowledged_bitrate_); + } + return candidate_bandwidth_upper_bound; +} + +std::vector LossBasedBweV2::GetCandidates( + DataRate delay_based_estimate) const { + std::vector bandwidths; + bool can_increase_bitrate = TrendlineEsimateAllowBitrateIncrease(); + for (double candidate_factor : config_->candidate_factors) { + if (!can_increase_bitrate && candidate_factor > 1.0) { + continue; + } + bandwidths.push_back(candidate_factor * + current_estimate_.loss_limited_bandwidth); + } + + if (acknowledged_bitrate_.has_value() && + config_->append_acknowledged_rate_candidate && + TrendlineEsimateAllowEmergencyBackoff()) { + bandwidths.push_back(*acknowledged_bitrate_ * + config_->bandwidth_backoff_lower_bound_factor); + } + + if (IsValid(delay_based_estimate) && + config_->append_delay_based_estimate_candidate) { + if (can_increase_bitrate && + delay_based_estimate > current_estimate_.loss_limited_bandwidth) { + bandwidths.push_back(delay_based_estimate); + } + } + + const DataRate candidate_bandwidth_upper_bound = + GetCandidateBandwidthUpperBound(delay_based_estimate); + + std::vector candidates; + candidates.resize(bandwidths.size()); + for (size_t i = 0; i < bandwidths.size(); ++i) { + ChannelParameters candidate = current_estimate_; + if (config_->trendline_integration_enabled) { + candidate.loss_limited_bandwidth = + std::min(bandwidths[i], candidate_bandwidth_upper_bound); + } else { + candidate.loss_limited_bandwidth = std::min( + bandwidths[i], std::max(current_estimate_.loss_limited_bandwidth, + candidate_bandwidth_upper_bound)); + } + candidate.inherent_loss = GetFeasibleInherentLoss(candidate); + candidates[i] = candidate; + } + return candidates; +} + +LossBasedBweV2::Derivatives LossBasedBweV2::GetDerivatives( + const ChannelParameters& channel_parameters) const { + Derivatives derivatives; + + for (const Observation& observation : observations_) { + if (!observation.IsInitialized()) { + continue; + } + + double loss_probability = GetLossProbability( + channel_parameters.inherent_loss, + channel_parameters.loss_limited_bandwidth, observation.sending_rate); + + double temporal_weight = + temporal_weights_[(num_observations_ - 1) - observation.id]; + + derivatives.first += + temporal_weight * + ((observation.num_lost_packets / loss_probability) - + (observation.num_received_packets / (1.0 - loss_probability))); + derivatives.second -= + temporal_weight * + ((observation.num_lost_packets / std::pow(loss_probability, 2)) + + (observation.num_received_packets / + std::pow(1.0 - loss_probability, 2))); + } + + if (derivatives.second >= 0.0) { +/* RTC_LOG(LS_ERROR) << "The second derivative is mathematically guaranteed " + "to be negative but is " + << derivatives.second << ".";*/ + derivatives.second = -1.0e-6; + } + + return derivatives; +} + +double LossBasedBweV2::GetFeasibleInherentLoss( + const ChannelParameters& channel_parameters) const { + return std::min( + std::max(channel_parameters.inherent_loss, + config_->inherent_loss_lower_bound), + GetInherentLossUpperBound(channel_parameters.loss_limited_bandwidth)); +} + +double LossBasedBweV2::GetInherentLossUpperBound(DataRate bandwidth) const { + if (bandwidth.IsZero()) { + return 1.0; + } + + double inherent_loss_upper_bound = + config_->inherent_loss_upper_bound_offset + + config_->inherent_loss_upper_bound_bandwidth_balance / bandwidth; + return std::min(inherent_loss_upper_bound, 1.0); +} + +double LossBasedBweV2::AdjustBiasFactor(double loss_rate, + double bias_factor) const { + return bias_factor * + (config_->loss_threshold_of_high_bandwidth_preference - loss_rate) / + (config_->bandwidth_preference_smoothing_factor + + std::abs(config_->loss_threshold_of_high_bandwidth_preference - + loss_rate)); +} + +double LossBasedBweV2::GetHighBandwidthBias(DataRate bandwidth) const { + if (IsValid(bandwidth)) { + const double average_reported_loss_ratio = GetAverageReportedLossRatio(); + return AdjustBiasFactor(average_reported_loss_ratio, + config_->higher_bandwidth_bias_factor) * + bandwidth.kbps() + + AdjustBiasFactor(average_reported_loss_ratio, + config_->higher_log_bandwidth_bias_factor) * + std::log(1.0 + bandwidth.kbps()); + } + return 0.0; +} + +double LossBasedBweV2::GetObjective( + const ChannelParameters& channel_parameters) const { + double objective = 0.0; + + const double high_bandwidth_bias = + GetHighBandwidthBias(channel_parameters.loss_limited_bandwidth); + + for (const Observation& observation : observations_) { + if (!observation.IsInitialized()) { + continue; + } + + double loss_probability = GetLossProbability( + channel_parameters.inherent_loss, + channel_parameters.loss_limited_bandwidth, observation.sending_rate); + + double temporal_weight = + temporal_weights_[(num_observations_ - 1) - observation.id]; + + objective += + temporal_weight * + ((observation.num_lost_packets * std::log(loss_probability)) + + (observation.num_received_packets * std::log(1.0 - loss_probability))); + objective += + temporal_weight * high_bandwidth_bias * observation.num_packets; + } + + return objective; +} + +DataRate LossBasedBweV2::GetSendingRate( + DataRate instantaneous_sending_rate) const { + if (num_observations_ <= 0) { + return instantaneous_sending_rate; + } + + const int most_recent_observation_idx = + (num_observations_ - 1) % config_->observation_window_size; + const Observation& most_recent_observation = + observations_[most_recent_observation_idx]; + DataRate sending_rate_previous_observation = + most_recent_observation.sending_rate; + + return config_->sending_rate_smoothing_factor * + sending_rate_previous_observation + + (1.0 - config_->sending_rate_smoothing_factor) * + instantaneous_sending_rate; +} + +DataRate LossBasedBweV2::GetInstantUpperBound() const { + return cached_instant_upper_bound_.value_or(DataRate::PlusInfinity()); +} + +void LossBasedBweV2::CalculateInstantUpperBound() { + DataRate instant_limit = DataRate::PlusInfinity(); + const double average_reported_loss_ratio = GetAverageReportedLossRatio(); + if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { + instant_limit = config_->instant_upper_bound_bandwidth_balance / + (average_reported_loss_ratio - + config_->instant_upper_bound_loss_offset); + if (average_reported_loss_ratio > config_->high_loss_rate_threshold) { + instant_limit = std::min( + instant_limit, DataRate::kbps(std::max( + static_cast(min_bitrate_.kbps()), + config_->bandwidth_cap_at_high_loss_rate.kbps() - + config_->slope_of_bwe_high_loss_func * + average_reported_loss_ratio))); + } + } + + cached_instant_upper_bound_ = instant_limit; +} + +void LossBasedBweV2::CalculateTemporalWeights() { + for (int i = 0; i < config_->observation_window_size; ++i) { + temporal_weights_[i] = std::pow(config_->temporal_weight_factor, i); + instant_upper_bound_temporal_weights_[i] = + std::pow(config_->instant_upper_bound_temporal_weight_factor, i); + } +} + +void LossBasedBweV2::NewtonsMethodUpdate( + ChannelParameters& channel_parameters) const { + if (num_observations_ <= 0) { + return; + } + + for (int i = 0; i < config_->newton_iterations; ++i) { + const Derivatives derivatives = GetDerivatives(channel_parameters); + channel_parameters.inherent_loss -= + config_->newton_step_size * derivatives.first / derivatives.second; + channel_parameters.inherent_loss = + GetFeasibleInherentLoss(channel_parameters); + } +} + +bool LossBasedBweV2::TrendlineEsimateAllowBitrateIncrease() const { + if (!config_->trendline_integration_enabled) { + return true; + } + + for (const auto& detector_state : delay_detector_states_) { + if (detector_state == BandwidthUsage::kBwOverusing || + detector_state == BandwidthUsage::kBwUnderusing) { + return false; + } + } + return true; +} + +bool LossBasedBweV2::TrendlineEsimateAllowEmergencyBackoff() const { + if (!config_->trendline_integration_enabled) { + return true; + } + + if (!config_->use_acked_bitrate_only_when_overusing) { + return true; + } + + for (const auto& detector_state : delay_detector_states_) { + if (detector_state == BandwidthUsage::kBwOverusing) { + return true; + } + } + + return false; +} + +bool LossBasedBweV2::PushBackObservation( + std::vector packet_results, + BandwidthUsage delay_detector_state) { + delay_detector_states_.push_front(delay_detector_state); + if (static_cast(delay_detector_states_.size()) > + config_->trendline_observations_window_size) { + delay_detector_states_.pop_back(); + } + + if (packet_results.empty()) { + return false; + } + + PacketResultsSummary packet_results_summary = + GetPacketResultsSummary(packet_results); + + partial_observation_.num_packets += packet_results_summary.num_packets; + partial_observation_.num_lost_packets += + packet_results_summary.num_lost_packets; + partial_observation_.size += packet_results_summary.total_size; + + // This is the first packet report we have received. + if (!IsValid(last_send_time_most_recent_observation_)) { + last_send_time_most_recent_observation_ = + packet_results_summary.first_send_time; + } + + const Timestamp last_send_time = packet_results_summary.last_send_time; + const TimeDelta observation_duration = + last_send_time - last_send_time_most_recent_observation_; + // Too small to be meaningful. + if (observation_duration <= TimeDelta::Zero() || + (observation_duration < config_->observation_duration_lower_bound && + (delay_detector_state != BandwidthUsage::kBwOverusing || + !config_->trendline_integration_enabled))) { + return false; + } + + last_send_time_most_recent_observation_ = last_send_time; + + Observation observation; + observation.num_packets = partial_observation_.num_packets; + observation.num_lost_packets = partial_observation_.num_lost_packets; + observation.num_received_packets = + observation.num_packets - observation.num_lost_packets; + observation.sending_rate = + GetSendingRate(partial_observation_.size / observation_duration); + observation.id = num_observations_++; + observations_[observation.id % config_->observation_window_size] = + observation; + + partial_observation_ = PartialObservation(); + + CalculateInstantUpperBound(); + return true; +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h new file mode 100644 index 0000000000..9dc2215395 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -0,0 +1,178 @@ +/* + * Copyright 2021 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. + */ + +#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_LOSS_BASED_BWE_V2_H_ +#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_LOSS_BASED_BWE_V2_H_ + +#include +#include +#include + +#include "absl/types/optional.h" +#include "api/network_state_predictor.h" +#include "api/transport/network_types.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "api/transport/webrtc_key_value_config.h" + +namespace webrtc { + +class LossBasedBweV2 { + public: + // Creates a disabled `LossBasedBweV2` if the + // `key_value_config` is not valid. + explicit LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config); + + LossBasedBweV2(const LossBasedBweV2&) = delete; + LossBasedBweV2& operator=(const LossBasedBweV2&) = delete; + + ~LossBasedBweV2() = default; + + bool IsEnabled() const; + // Returns true iff a BWE can be calculated, i.e., the estimator has been + // initialized with a BWE and then has received enough `PacketResult`s. + bool IsReady() const; + + // Returns `DataRate::PlusInfinity` if no BWE can be calculated. + DataRate GetBandwidthEstimate(DataRate delay_based_limit) const; + + void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); + void SetBandwidthEstimate(DataRate bandwidth_estimate); + void SetMinBitrate(DataRate min_bitrate); + void UpdateBandwidthEstimate( + std::vector packet_results, + DataRate delay_based_estimate, + BandwidthUsage delay_detector_state); + + private: + struct ChannelParameters { + double inherent_loss = 0.0; + DataRate loss_limited_bandwidth = DataRate::MinusInfinity(); + }; + + struct Config { + double bandwidth_rampup_upper_bound_factor = 0.0; + double rampup_acceleration_max_factor = 0.0; + TimeDelta rampup_acceleration_maxout_time = TimeDelta::Zero(); + std::vector candidate_factors; + double higher_bandwidth_bias_factor = 0.0; + double higher_log_bandwidth_bias_factor = 0.0; + double inherent_loss_lower_bound = 0.0; + double loss_threshold_of_high_bandwidth_preference = 0.0; + double bandwidth_preference_smoothing_factor = 0.0; + DataRate inherent_loss_upper_bound_bandwidth_balance = + DataRate::MinusInfinity(); + double inherent_loss_upper_bound_offset = 0.0; + double initial_inherent_loss_estimate = 0.0; + int newton_iterations = 0; + double newton_step_size = 0.0; + bool append_acknowledged_rate_candidate = true; + bool append_delay_based_estimate_candidate = false; + TimeDelta observation_duration_lower_bound = TimeDelta::Zero(); + int observation_window_size = 0; + double sending_rate_smoothing_factor = 0.0; + double instant_upper_bound_temporal_weight_factor = 0.0; + DataRate instant_upper_bound_bandwidth_balance = DataRate::MinusInfinity(); + double instant_upper_bound_loss_offset = 0.0; + double temporal_weight_factor = 0.0; + double bandwidth_backoff_lower_bound_factor = 0.0; + bool trendline_integration_enabled = false; + int trendline_observations_window_size = 0; + double max_increase_factor = 0.0; + TimeDelta delayed_increase_window = TimeDelta::Zero(); + bool use_acked_bitrate_only_when_overusing = false; + bool not_increase_if_inherent_loss_less_than_average_loss = false; + double high_loss_rate_threshold = 1.0; + DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity(); + double slope_of_bwe_high_loss_func = 1000.0; + }; + + struct Derivatives { + double first = 0.0; + double second = 0.0; + }; + + struct Observation { + bool IsInitialized() const { return id != -1; } + + int num_packets = 0; + int num_lost_packets = 0; + int num_received_packets = 0; + DataRate sending_rate = DataRate::MinusInfinity(); + int id = -1; + }; + + struct PartialObservation { + int num_packets = 0; + int num_lost_packets = 0; + DataSize size = DataSize::Zero(); + }; + + static absl::optional CreateConfig( + const WebRtcKeyValueConfig* key_value_config); + bool IsConfigValid() const; + + // Returns `0.0` if not enough loss statistics have been received. + double GetAverageReportedLossRatio() const; + std::vector GetCandidates( + DataRate delay_based_estimate) const; + DataRate GetCandidateBandwidthUpperBound(DataRate delay_based_estimate) const; + Derivatives GetDerivatives(const ChannelParameters& channel_parameters) const; + double GetFeasibleInherentLoss( + const ChannelParameters& channel_parameters) const; + double GetInherentLossUpperBound(DataRate bandwidth) const; + double AdjustBiasFactor(double loss_rate, double bias_factor) const; + double GetHighBandwidthBias(DataRate bandwidth) const; + double GetObjective(const ChannelParameters& channel_parameters) const; + DataRate GetSendingRate(DataRate instantaneous_sending_rate) const; + DataRate GetInstantUpperBound() const; + void CalculateInstantUpperBound(); + + void CalculateTemporalWeights(); + void NewtonsMethodUpdate(ChannelParameters& channel_parameters) const; + + // Returns false if there exists a kBwOverusing or kBwUnderusing in the + // window. + bool TrendlineEsimateAllowBitrateIncrease() const; + + // Returns true if there exists an overusing state in the window. + bool TrendlineEsimateAllowEmergencyBackoff() const; + + // Returns false if no observation was created. + bool PushBackObservation(std::vector packet_results, + BandwidthUsage delay_detector_state); + void UpdateTrendlineEstimator( + const std::vector packet_feedbacks, + Timestamp at_time); + void UpdateDelayDetector(BandwidthUsage delay_detector_state); + + absl::optional acknowledged_bitrate_; + absl::optional config_; + ChannelParameters current_estimate_; + int num_observations_ = 0; + std::vector observations_; + PartialObservation partial_observation_; + Timestamp last_send_time_most_recent_observation_ = Timestamp::PlusInfinity(); + Timestamp last_time_estimate_reduced_ = Timestamp::MinusInfinity(); + absl::optional cached_instant_upper_bound_; + std::vector instant_upper_bound_temporal_weights_; + std::vector temporal_weights_; + std::deque delay_detector_states_; + Timestamp recovering_after_loss_timestamp_ = Timestamp::MinusInfinity(); + DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); + bool limited_due_to_loss_candidate_ = false; + DataRate min_bitrate_ = DataRate::kbps(1); +}; + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_LOSS_BASED_BWE_V2_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index b6461789aa..3bfa2ca740 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -13,8 +13,10 @@ #include "modules/bitrate_controller/send_side_bandwidth_estimation.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" +#include "api/transport/webrtc_key_value_config.h" #include "system_wrappers/source/field_trial.h" + #include "Logger.hpp" #include @@ -35,8 +37,6 @@ constexpr TimeDelta kLowBitrateLogPeriod = TimeDelta::Millis<10000>(); constexpr TimeDelta kRtcEventLogPeriod = TimeDelta::Millis<5000>(); // Expecting that RTCP feedback is sent uniformly within [0.5, 1.5]s intervals. constexpr TimeDelta kMaxRtcpFeedbackInterval = TimeDelta::Millis<5000>(); -constexpr int kFeedbackTimeoutIntervals = 3; -constexpr TimeDelta kTimeoutInterval = TimeDelta::Millis<1000>(); constexpr float kDefaultLowLossThreshold = 0.02f; constexpr float kDefaultHighLossThreshold = 0.1f; @@ -106,16 +106,20 @@ bool ReadBweLossExperimentParameters(float* low_loss_threshold, LinkCapacityTracker::LinkCapacityTracker() : tracking_rate("rate", TimeDelta::seconds(10)) { ParseFieldTrial({&tracking_rate}, - field_trial::FindFullName("WebRTC-Bwe-LinkCapacity")); + webrtc::field_trial::FindFullName("WebRTC-Bwe-LinkCapacity")); } LinkCapacityTracker::~LinkCapacityTracker() {} -void LinkCapacityTracker::OnOveruse(DataRate acknowledged_rate, - Timestamp at_time) { - capacity_estimate_bps_ = - std::min(capacity_estimate_bps_, acknowledged_rate.bps()); - last_link_capacity_update_ = at_time; +void LinkCapacityTracker::UpdateDelayBasedEstimate( + Timestamp at_time, + DataRate delay_based_bitrate) { + if (delay_based_bitrate < last_delay_based_estimate_) { + capacity_estimate_bps_ = + std::min(capacity_estimate_bps_, delay_based_bitrate.bps()); + last_link_capacity_update_ = at_time; + } + last_delay_based_estimate_ = delay_based_bitrate; } void LinkCapacityTracker::OnStartingRate(DataRate start_rate) { @@ -123,13 +127,17 @@ void LinkCapacityTracker::OnStartingRate(DataRate start_rate) { capacity_estimate_bps_ = start_rate.bps(); } -void LinkCapacityTracker::OnRateUpdate(DataRate acknowledged, +void LinkCapacityTracker::OnRateUpdate(absl::optional acknowledged, + DataRate target, Timestamp at_time) { - if (acknowledged.bps() > capacity_estimate_bps_) { + if (!acknowledged) + return; + DataRate acknowledged_target = std::min(*acknowledged, target); + if (acknowledged_target.bps() > capacity_estimate_bps_) { TimeDelta delta = at_time - last_link_capacity_update_; double alpha = delta.IsFinite() ? exp(-(delta / tracking_rate.Get())) : 0; capacity_estimate_bps_ = alpha * capacity_estimate_bps_ + - (1 - alpha) * acknowledged.bps(); + (1 - alpha) * acknowledged_target.bps(); } last_link_capacity_update_ = at_time; } @@ -145,28 +153,23 @@ DataRate LinkCapacityTracker::estimate() const { return DataRate::bps(capacity_estimate_bps_); } -RttBasedBackoff::RttBasedBackoff() - : rtt_limit_("limit", TimeDelta::PlusInfinity()), - drop_fraction_("fraction", 0.5), - drop_interval_("interval", TimeDelta::ms(300)), - persist_on_route_change_("persist"), - safe_timeout_("safe_timeout", true), +RttBasedBackoff::RttBasedBackoff(const WebRtcKeyValueConfig* key_value_config) + : disabled_("Disabled"), + configured_limit_("limit", TimeDelta::seconds(3)), + drop_fraction_("fraction", 0.8), + drop_interval_("interval", TimeDelta::seconds(1)), bandwidth_floor_("floor", DataRate::kbps(5)), + rtt_limit_(TimeDelta::PlusInfinity()), // By initializing this to plus infinity, we make sure that we never // trigger rtt backoff unless packet feedback is enabled. last_propagation_rtt_update_(Timestamp::PlusInfinity()), last_propagation_rtt_(TimeDelta::Zero()), last_packet_sent_(Timestamp::MinusInfinity()) { - ParseFieldTrial( - {&rtt_limit_, &drop_fraction_, &drop_interval_, &persist_on_route_change_, - &safe_timeout_, &bandwidth_floor_}, - field_trial::FindFullName("WebRTC-Bwe-MaxRttLimit")); -} - -void RttBasedBackoff::OnRouteChange() { - if (!persist_on_route_change_) { - last_propagation_rtt_update_ = Timestamp::PlusInfinity(); - last_propagation_rtt_ = TimeDelta::Zero(); + ParseFieldTrial({&disabled_, &configured_limit_, &drop_fraction_, + &drop_interval_, &bandwidth_floor_}, + key_value_config->Lookup("WebRTC-Bwe-MaxRttLimit")); + if (!disabled_) { + rtt_limit_ = configured_limit_.Get(); } } @@ -179,34 +182,33 @@ void RttBasedBackoff::UpdatePropagationRtt(Timestamp at_time, TimeDelta RttBasedBackoff::CorrectedRtt(Timestamp at_time) const { TimeDelta time_since_rtt = at_time - last_propagation_rtt_update_; TimeDelta timeout_correction = time_since_rtt; - if (safe_timeout_) { - // Avoid timeout when no packets are being sent. - TimeDelta time_since_packet_sent = at_time - last_packet_sent_; - timeout_correction = - std::max(time_since_rtt - time_since_packet_sent, TimeDelta::Zero()); - } + // Avoid timeout when no packets are being sent. + TimeDelta time_since_packet_sent = at_time - last_packet_sent_; + timeout_correction = + std::max(time_since_rtt - time_since_packet_sent, TimeDelta::Zero()); return timeout_correction + last_propagation_rtt_; } RttBasedBackoff::~RttBasedBackoff() = default; -SendSideBandwidthEstimation::SendSideBandwidthEstimation() - : lost_packets_since_last_loss_update_(0), +SendSideBandwidthEstimation::SendSideBandwidthEstimation( + const WebRtcKeyValueConfig* key_value_config) + : rtt_backoff_(key_value_config), + lost_packets_since_last_loss_update_(0), expected_packets_since_last_loss_update_(0), - current_bitrate_(DataRate::Zero()), - min_bitrate_configured_( - DataRate::bps(congestion_controller::GetMinBitrateBps())), + current_target_(DataRate::Zero()), + last_logged_target_(DataRate::Zero()), + min_bitrate_configured_(kCongestionControllerMinBitrate), max_bitrate_configured_(kDefaultMaxBitrate), last_low_bitrate_log_(Timestamp::MinusInfinity()), has_decreased_since_last_fraction_loss_(false), last_loss_feedback_(Timestamp::MinusInfinity()), last_loss_packet_report_(Timestamp::MinusInfinity()), - last_timeout_(Timestamp::MinusInfinity()), last_fraction_loss_(0), last_logged_fraction_loss_(0), last_round_trip_time_(TimeDelta::Zero()), - bwe_incoming_(DataRate::Zero()), - delay_based_bitrate_(DataRate::Zero()), + receiver_limit_(DataRate::PlusInfinity()), + delay_based_limit_(DataRate::PlusInfinity()), time_last_decrease_(Timestamp::MinusInfinity()), first_report_time_(Timestamp::MinusInfinity()), initially_lost_packets_(0), @@ -215,12 +217,13 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation() uma_rtt_state_(kNoUpdate), rampup_uma_stats_updated_(kNumUmaRampupMetrics, false), last_rtc_event_log_(Timestamp::MinusInfinity()), - in_timeout_experiment_( - webrtc::field_trial::IsEnabled("WebRTC-FeedbackTimeout")), low_loss_threshold_(kDefaultLowLossThreshold), high_loss_threshold_(kDefaultHighLossThreshold), - bitrate_threshold_(kDefaultBitrateThreshold) { - // RTC_DCHECK(event_log); + bitrate_threshold_(kDefaultBitrateThreshold), + loss_based_bandwidth_estimator_v1_(key_value_config), + loss_based_bandwidth_estimator_v2_(key_value_config), + disable_receiver_limit_caps_only_("Disabled") { + if (BweLossExperimentIsEnabled()) { uint32_t bitrate_threshold_kbps; if (ReadBweLossExperimentParameters(&low_loss_threshold_, @@ -232,6 +235,11 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation() bitrate_threshold_ = DataRate::kbps(bitrate_threshold_kbps); } } + ParseFieldTrial({&disable_receiver_limit_caps_only_}, + key_value_config->Lookup("WebRTC-Bwe-ReceiverLimitCapsOnly")); + if (LossBasedBandwidthEstimatorV2Enabled()) { + loss_based_bandwidth_estimator_v2_.SetMinBitrate(min_bitrate_configured_); + } } SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} @@ -239,20 +247,18 @@ SendSideBandwidthEstimation::~SendSideBandwidthEstimation() {} void SendSideBandwidthEstimation::OnRouteChange() { lost_packets_since_last_loss_update_ = 0; expected_packets_since_last_loss_update_ = 0; - current_bitrate_ = DataRate::Zero(); - min_bitrate_configured_ = - DataRate::bps(congestion_controller::GetMinBitrateBps()); + current_target_ = DataRate::Zero(); + min_bitrate_configured_ = kCongestionControllerMinBitrate; max_bitrate_configured_ = kDefaultMaxBitrate; last_low_bitrate_log_ = Timestamp::MinusInfinity(); has_decreased_since_last_fraction_loss_ = false; last_loss_feedback_ = Timestamp::MinusInfinity(); last_loss_packet_report_ = Timestamp::MinusInfinity(); - last_timeout_ = Timestamp::MinusInfinity(); last_fraction_loss_ = 0; last_logged_fraction_loss_ = 0; last_round_trip_time_ = TimeDelta::Zero(); - bwe_incoming_ = DataRate::Zero(); - delay_based_bitrate_ = DataRate::Zero(); + receiver_limit_ = DataRate::PlusInfinity(); + delay_based_limit_ = DataRate::PlusInfinity(); time_last_decrease_ = Timestamp::MinusInfinity(); first_report_time_ = Timestamp::MinusInfinity(); initially_lost_packets_ = 0; @@ -260,8 +266,6 @@ void SendSideBandwidthEstimation::OnRouteChange() { uma_update_state_ = kNoUpdate; uma_rtt_state_ = kNoUpdate; last_rtc_event_log_ = Timestamp::MinusInfinity(); - - rtt_backoff_.OnRouteChange(); } void SendSideBandwidthEstimation::SetBitrates( @@ -282,11 +286,8 @@ void SendSideBandwidthEstimation::SetSendBitrate(DataRate bitrate, // RTC_DCHECK_GT(bitrate, DataRate::Zero()); // Reset to avoid being capped by the estimate. - delay_based_bitrate_ = DataRate::Zero(); - if (loss_based_bandwidth_estimation_.Enabled()) { - loss_based_bandwidth_estimation_.MaybeReset(bitrate); - } - CapBitrateToThresholds(at_time, bitrate); + delay_based_limit_ = DataRate::PlusInfinity(); + UpdateTargetBitrate(bitrate, at_time); // Clear last sent bitrate history so the new value can be used directly // and not capped. min_bitrate_history_.clear(); @@ -295,7 +296,7 @@ void SendSideBandwidthEstimation::SetSendBitrate(DataRate bitrate, void SendSideBandwidthEstimation::SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate) { min_bitrate_configured_ = - std::max(min_bitrate, congestion_controller::GetMinBitrate()); + std::max(min_bitrate, kCongestionControllerMinBitrate); if (max_bitrate > DataRate::Zero() && max_bitrate.IsFinite()) { max_bitrate_configured_ = std::max(min_bitrate_configured_, max_bitrate); } else { @@ -307,19 +308,15 @@ int SendSideBandwidthEstimation::GetMinBitrate() const { return min_bitrate_configured_.bps(); } -void SendSideBandwidthEstimation::CurrentEstimate(int* bitrate, - uint8_t* loss, - int64_t* rtt) const { - *bitrate = std::max(current_bitrate_.bps(), GetMinBitrate()); - *loss = last_fraction_loss_; - *rtt = last_round_trip_time_.ms(); +DataRate SendSideBandwidthEstimation::target_rate() const { + DataRate target = current_target_; + if (!disable_receiver_limit_caps_only_) + target = std::min(target, receiver_limit_); + return std::max(min_bitrate_configured_, target); +} - MS_DEBUG_DEV("bitrate:%d (current_bitrate_:%" PRIi64 ", GetMinBitrate():%d), loss:%d, rtt:%" PRIi64, - *bitrate, - current_bitrate_.bps(), - GetMinBitrate(), - *loss, - *rtt); +DataRate SendSideBandwidthEstimation::delay_based_limit() const { + return delay_based_limit_; } DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const { @@ -328,53 +325,54 @@ DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const { void SendSideBandwidthEstimation::UpdateReceiverEstimate(Timestamp at_time, DataRate bandwidth) { - bwe_incoming_ = bandwidth; - CapBitrateToThresholds(at_time, current_bitrate_); + // TODO(srte): Ensure caller passes PlusInfinity, not zero, to represent no + // limitation. + receiver_limit_ = bandwidth.IsZero() ? DataRate::PlusInfinity() : bandwidth; + ApplyTargetLimits(at_time); } void SendSideBandwidthEstimation::UpdateDelayBasedEstimate(Timestamp at_time, DataRate bitrate) { - if (acknowledged_rate_) { - if (bitrate < delay_based_bitrate_) { - link_capacity_.OnOveruse(*acknowledged_rate_, at_time); - } - } - delay_based_bitrate_ = bitrate; - CapBitrateToThresholds(at_time, current_bitrate_); + link_capacity_.UpdateDelayBasedEstimate(at_time, bitrate); + // TODO(srte): Ensure caller passes PlusInfinity, not zero, to represent no + // limitation. + delay_based_limit_ = bitrate.IsZero() ? DataRate::PlusInfinity() : bitrate; + ApplyTargetLimits(at_time); } void SendSideBandwidthEstimation::SetAcknowledgedRate( absl::optional acknowledged_rate, Timestamp at_time) { acknowledged_rate_ = acknowledged_rate; - if (acknowledged_rate && loss_based_bandwidth_estimation_.Enabled()) { - loss_based_bandwidth_estimation_.UpdateAcknowledgedBitrate( + if (!acknowledged_rate.has_value()) { + return; + } + if (LossBasedBandwidthEstimatorV1Enabled()) { + loss_based_bandwidth_estimator_v1_.UpdateAcknowledgedBitrate( *acknowledged_rate, at_time); } + if (LossBasedBandwidthEstimatorV2Enabled()) { + loss_based_bandwidth_estimator_v2_.SetAcknowledgedBitrate( + *acknowledged_rate); + } } -void SendSideBandwidthEstimation::IncomingPacketFeedbackVector( - const TransportPacketsFeedback& report) { - if (loss_based_bandwidth_estimation_.Enabled()) { - loss_based_bandwidth_estimation_.UpdateLossStatistics( +void SendSideBandwidthEstimation::UpdateLossBasedEstimator( + const TransportPacketsFeedback& report, + BandwidthUsage delay_detector_state) { + if (LossBasedBandwidthEstimatorV1Enabled()) { + loss_based_bandwidth_estimator_v1_.UpdateLossStatistics( report.packet_feedbacks, report.feedback_time); } + if (LossBasedBandwidthEstimatorV2Enabled()) { + loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( + report.packet_feedbacks, delay_based_limit_, delay_detector_state); + UpdateEstimate(report.feedback_time); + } } -void SendSideBandwidthEstimation::UpdateReceiverBlock(uint8_t fraction_loss, - TimeDelta rtt, - int number_of_packets, - Timestamp at_time) { - const int kRoundingConstant = 128; - int packets_lost = (static_cast(fraction_loss) * number_of_packets + - kRoundingConstant) >> - 8; - UpdatePacketsLost(packets_lost, number_of_packets, at_time); - UpdateRtt(rtt, at_time); -} - -void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost, - int number_of_packets, +void SendSideBandwidthEstimation::UpdatePacketsLost(int64_t packets_lost, + int64_t number_of_packets, Timestamp at_time) { last_loss_feedback_ = at_time; if (first_report_time_.IsInfinite()) @@ -382,32 +380,38 @@ void SendSideBandwidthEstimation::UpdatePacketsLost(int packets_lost, // Check sequence number diff and weight loss report if (number_of_packets > 0) { - // Accumulate reports. - lost_packets_since_last_loss_update_ += packets_lost; - expected_packets_since_last_loss_update_ += number_of_packets; + int64_t expected = + expected_packets_since_last_loss_update_ + number_of_packets; // Don't generate a loss rate until it can be based on enough packets. - if (expected_packets_since_last_loss_update_ < kLimitNumPackets) + if (expected < kLimitNumPackets) { + // Accumulate reports. + expected_packets_since_last_loss_update_ = expected; + lost_packets_since_last_loss_update_ += packets_lost; return; + } has_decreased_since_last_fraction_loss_ = false; - int64_t lost_q8 = lost_packets_since_last_loss_update_ << 8; - int64_t expected = expected_packets_since_last_loss_update_; + int64_t lost_q8 = + std::max(lost_packets_since_last_loss_update_ + packets_lost, + 0) + << 8; last_fraction_loss_ = std::min(lost_q8 / expected, 255); // Reset accumulators. - lost_packets_since_last_loss_update_ = 0; expected_packets_since_last_loss_update_ = 0; last_loss_packet_report_ = at_time; UpdateEstimate(at_time); } + UpdateUmaStatsPacketsLost(at_time, packets_lost); } void SendSideBandwidthEstimation::UpdateUmaStatsPacketsLost(Timestamp at_time, int packets_lost) { - DataRate bitrate_kbps = DataRate::kbps((current_bitrate_.bps() + 500) / 1000); + DataRate bitrate_kbps = + DataRate::kbps((current_target_.bps() + 500) / 1000); for (size_t i = 0; i < kNumUmaRampupMetrics; ++i) { if (!rampup_uma_stats_updated_[i] && bitrate_kbps.kbps() >= kUmaRampupMetrics[i].bitrate_kbps) { @@ -448,64 +452,83 @@ void SendSideBandwidthEstimation::UpdateRtt(TimeDelta rtt, Timestamp at_time) { } void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) { - DataRate new_bitrate = current_bitrate_; if (rtt_backoff_.CorrectedRtt(at_time) > rtt_backoff_.rtt_limit_) { if (at_time - time_last_decrease_ >= rtt_backoff_.drop_interval_ && - current_bitrate_ > rtt_backoff_.bandwidth_floor_) { + current_target_ > rtt_backoff_.bandwidth_floor_) { time_last_decrease_ = at_time; - new_bitrate = std::max(current_bitrate_ * rtt_backoff_.drop_fraction_, - rtt_backoff_.bandwidth_floor_.Get()); + DataRate new_bitrate = + std::max(current_target_ * rtt_backoff_.drop_fraction_, + rtt_backoff_.bandwidth_floor_.Get()); link_capacity_.OnRttBackoff(new_bitrate, at_time); + UpdateTargetBitrate(new_bitrate, at_time); + return; } - CapBitrateToThresholds(at_time, new_bitrate); + // TODO(srte): This is likely redundant in most cases. + ApplyTargetLimits(at_time); return; } // We trust the REMB and/or delay-based estimate during the first 2 seconds if // we haven't had any packet loss reported, to allow startup bitrate probing. if (last_fraction_loss_ == 0 && IsInStartPhase(at_time)) { - new_bitrate = std::max(bwe_incoming_, new_bitrate); - new_bitrate = std::max(delay_based_bitrate_, new_bitrate); - if (loss_based_bandwidth_estimation_.Enabled()) { - loss_based_bandwidth_estimation_.SetInitialBitrate(new_bitrate); + DataRate new_bitrate = current_target_; + // TODO(srte): We should not allow the new_bitrate to be larger than the + // receiver limit here. + if (receiver_limit_.IsFinite()) + new_bitrate = std::max(receiver_limit_, new_bitrate); + if (delay_based_limit_.IsFinite()) + new_bitrate = std::max(delay_based_limit_, new_bitrate); + if (LossBasedBandwidthEstimatorV1Enabled()) { + loss_based_bandwidth_estimator_v1_.Initialize(new_bitrate); + } + if (LossBasedBandwidthEstimatorV2Enabled()) { + loss_based_bandwidth_estimator_v2_.SetBandwidthEstimate(new_bitrate); } - if (new_bitrate != current_bitrate_) { + if (new_bitrate != current_target_) { min_bitrate_history_.clear(); - if (loss_based_bandwidth_estimation_.Enabled()) { + if (LossBasedBandwidthEstimatorV1Enabled()) { min_bitrate_history_.push_back(std::make_pair(at_time, new_bitrate)); } else { min_bitrate_history_.push_back( - std::make_pair(at_time, current_bitrate_)); + std::make_pair(at_time, current_target_)); } - CapBitrateToThresholds(at_time, new_bitrate); + UpdateTargetBitrate(new_bitrate, at_time); return; } } UpdateMinHistory(at_time); if (last_loss_packet_report_.IsInfinite()) { // No feedback received. - CapBitrateToThresholds(at_time, current_bitrate_); + // TODO(srte): This is likely redundant in most cases. + ApplyTargetLimits(at_time); return; } - if (loss_based_bandwidth_estimation_.Enabled()) { - loss_based_bandwidth_estimation_.Update( - at_time, min_bitrate_history_.front().second, last_round_trip_time_); - new_bitrate = MaybeRampupOrBackoff(new_bitrate, at_time); - CapBitrateToThresholds(at_time, new_bitrate); + if (LossBasedBandwidthEstimatorV1ReadyForUse()) { + DataRate new_bitrate = loss_based_bandwidth_estimator_v1_.Update( + at_time, min_bitrate_history_.front().second, delay_based_limit_, + last_round_trip_time_); + UpdateTargetBitrate(new_bitrate, at_time); + return; + } + + if (LossBasedBandwidthEstimatorV2ReadyForUse()) { + DataRate new_bitrate = + loss_based_bandwidth_estimator_v2_.GetBandwidthEstimate( + delay_based_limit_); + UpdateTargetBitrate(new_bitrate, at_time); return; } TimeDelta time_since_loss_packet_report = at_time - last_loss_packet_report_; - TimeDelta time_since_loss_feedback = at_time - last_loss_feedback_; if (time_since_loss_packet_report < 1.2 * kMaxRtcpFeedbackInterval) { // We only care about loss above a given bitrate threshold. float loss = last_fraction_loss_ / 256.0f; // We only make decisions based on loss when the bitrate is above a // threshold. This is a crude way of handling loss which is uncorrelated // to congestion. - if (current_bitrate_ < bitrate_threshold_ || loss <= low_loss_threshold_) { + if (current_target_ < bitrate_threshold_ || loss <= low_loss_threshold_) { // Loss < 2%: Increase rate by 8% of the min bitrate in the last // kBweIncreaseInterval. // Note that by remembering the bitrate over the last second one can @@ -516,14 +539,16 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) { // If instead one would do: current_bitrate_ *= 1.08^(delta time), // it would take over one second since the lower packet loss to achieve // 108kbps. - new_bitrate = - DataRate::bps(min_bitrate_history_.front().second.bps() * 1.08 + 0.5); + DataRate new_bitrate = DataRate::bps( + min_bitrate_history_.front().second.bps() * 1.08 + 0.5); // Add 1 kbps extra, just to make sure that we do not get stuck // (gives a little extra increase at low rates, negligible at higher // rates). new_bitrate += DataRate::bps(1000); - } else if (current_bitrate_ > bitrate_threshold_) { + UpdateTargetBitrate(new_bitrate, at_time); + return; + } else if (current_target_ > bitrate_threshold_) { if (loss <= high_loss_threshold_) { // Loss between 2% - 10%: Do nothing. } else { @@ -537,31 +562,19 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) { // Reduce rate: // newRate = rate * (1 - 0.5*lossRate); // where packetLoss = 256*lossRate; - new_bitrate = - DataRate::bps((current_bitrate_.bps() * - static_cast(512 - last_fraction_loss_)) / - 512.0); + DataRate new_bitrate = DataRate::bps( + (current_target_.bps() * + static_cast(512 - last_fraction_loss_)) / + 512.0); has_decreased_since_last_fraction_loss_ = true; + UpdateTargetBitrate(new_bitrate, at_time); + return; } } } - } else if (time_since_loss_feedback > - kFeedbackTimeoutIntervals * kMaxRtcpFeedbackInterval && - (last_timeout_.IsInfinite() || - at_time - last_timeout_ > kTimeoutInterval)) { - if (in_timeout_experiment_) { - MS_WARN_TAG(bwe, "Feedback timed out (%s), reducint bitrate", - ToString(time_since_loss_feedback).c_str()); - new_bitrate = new_bitrate * 0.8; - // Reset accumulators since we've already acted on missing feedback and - // shouldn't to act again on these old lost packets. - lost_packets_since_last_loss_update_ = 0; - expected_packets_since_last_loss_update_ = 0; - last_timeout_ = at_time; - } } - - CapBitrateToThresholds(at_time, new_bitrate); + // TODO(srte): This is likely redundant in most cases. + ApplyTargetLimits(at_time); } void SendSideBandwidthEstimation::UpdatePropagationRtt( @@ -593,86 +606,78 @@ void SendSideBandwidthEstimation::UpdateMinHistory(Timestamp at_time) { // Typical minimum sliding-window algorithm: Pop values higher than current // bitrate before pushing it. while (!min_bitrate_history_.empty() && - current_bitrate_ <= min_bitrate_history_.back().second) { + current_target_ <= min_bitrate_history_.back().second) { min_bitrate_history_.pop_back(); } - min_bitrate_history_.push_back(std::make_pair(at_time, current_bitrate_)); + min_bitrate_history_.push_back(std::make_pair(at_time, current_target_)); } -DataRate SendSideBandwidthEstimation::MaybeRampupOrBackoff(DataRate new_bitrate, - Timestamp at_time) { - // TODO(crodbro): reuse this code in UpdateEstimate instead of current - // inlining of very similar functionality. - const TimeDelta time_since_loss_packet_report = - at_time - last_loss_packet_report_; - const TimeDelta time_since_loss_feedback = at_time - last_loss_feedback_; - if (time_since_loss_packet_report < 1.2 * kMaxRtcpFeedbackInterval) { - new_bitrate = min_bitrate_history_.front().second * 1.08; - new_bitrate += DataRate::bps(1000); - } else if (time_since_loss_feedback > - kFeedbackTimeoutIntervals * kMaxRtcpFeedbackInterval && - (last_timeout_.IsInfinite() || - at_time - last_timeout_ > kTimeoutInterval)) { - if (in_timeout_experiment_) { - MS_WARN_TAG(bwe,"Feedback timed out (%s), reducint bitrate", - ToString(time_since_loss_feedback).c_str()); - new_bitrate = new_bitrate * 0.8; - // Reset accumulators since we've already acted on missing feedback and - // shouldn't to act again on these old lost packets. - lost_packets_since_last_loss_update_ = 0; - expected_packets_since_last_loss_update_ = 0; - last_timeout_ = at_time; - } - } - return new_bitrate; +DataRate SendSideBandwidthEstimation::GetUpperLimit() const { + DataRate upper_limit = delay_based_limit_; + if (disable_receiver_limit_caps_only_) + upper_limit = std::min(upper_limit, receiver_limit_); + return std::min(upper_limit, max_bitrate_configured_); } -void SendSideBandwidthEstimation::CapBitrateToThresholds(Timestamp at_time, - DataRate bitrate) { - if (bwe_incoming_ > DataRate::Zero() && bitrate > bwe_incoming_) { - MS_DEBUG_DEV("bwe_incoming_:%lld", bwe_incoming_.bps()); - bitrate = bwe_incoming_; - } - if (delay_based_bitrate_ > DataRate::Zero() && - bitrate > delay_based_bitrate_) { - MS_DEBUG_DEV("delay_based_bitrate_:%lld", delay_based_bitrate_.bps()); - bitrate = delay_based_bitrate_; - } - if (loss_based_bandwidth_estimation_.Enabled() && - loss_based_bandwidth_estimation_.GetEstimate() > DataRate::Zero()) { - MS_DEBUG_DEV("loss_based_bandwidth_estimation_.GetEstimate():%lld", loss_based_bandwidth_estimation_.GetEstimate().bps()); - bitrate = std::min(bitrate, loss_based_bandwidth_estimation_.GetEstimate()); - } - if (bitrate > max_bitrate_configured_) { - MS_DEBUG_DEV("bitrate > max_bitrate_configured_, setting bitrate to max_bitrate_configured_"); - bitrate = max_bitrate_configured_; - } - if (bitrate < min_bitrate_configured_) { - MS_DEBUG_DEV("bitrate < min_bitrate_configured_"); - if (last_low_bitrate_log_.IsInfinite() || - at_time - last_low_bitrate_log_ > kLowBitrateLogPeriod) { - MS_WARN_TAG(bwe, "Estimated available bandwidth %s" - " is below configured min bitrate %s", - ToString(bitrate).c_str(), - ToString(min_bitrate_configured_).c_str()); - last_low_bitrate_log_ = at_time; - } - bitrate = min_bitrate_configured_; +void SendSideBandwidthEstimation::MaybeLogLowBitrateWarning(DataRate bitrate, + Timestamp at_time) { + if (at_time - last_low_bitrate_log_ > kLowBitrateLogPeriod) { +/* MS_WARN_TAG(bwe, "Estimated available bandwidth %s is below configured min bitrate %s.", + ToString(bitrate), + ToString(min_bitrate_configured_); */ + last_low_bitrate_log_ = at_time; } +} - if (bitrate != current_bitrate_ || +void SendSideBandwidthEstimation::MaybeLogLossBasedEvent(Timestamp at_time) { +/* if (current_target_ != last_logged_target_ || last_fraction_loss_ != last_logged_fraction_loss_ || at_time - last_rtc_event_log_ > kRtcEventLogPeriod) { + event_log_->Log(std::make_unique( + current_target_.bps(), last_fraction_loss_, + expected_packets_since_last_loss_update_)); last_logged_fraction_loss_ = last_fraction_loss_; + last_logged_target_ = current_target_; last_rtc_event_log_ = at_time; - } - MS_DEBUG_DEV("current_bitrate_:%lld", current_bitrate_.bps()); - current_bitrate_ = bitrate; + }*/ +} - if (acknowledged_rate_) { - link_capacity_.OnRateUpdate(std::min(current_bitrate_, *acknowledged_rate_), - at_time); +void SendSideBandwidthEstimation::UpdateTargetBitrate(DataRate new_bitrate, + Timestamp at_time) { + new_bitrate = std::min(new_bitrate, GetUpperLimit()); + if (new_bitrate < min_bitrate_configured_) { + MaybeLogLowBitrateWarning(new_bitrate, at_time); + new_bitrate = min_bitrate_configured_; } + current_target_ = new_bitrate; + MaybeLogLossBasedEvent(at_time); + link_capacity_.OnRateUpdate(acknowledged_rate_, current_target_, at_time); +} + +void SendSideBandwidthEstimation::ApplyTargetLimits(Timestamp at_time) { + UpdateTargetBitrate(current_target_, at_time); +} + +bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV1Enabled() const { + return loss_based_bandwidth_estimator_v1_.Enabled() && + !LossBasedBandwidthEstimatorV2Enabled(); } + +bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV1ReadyForUse() + const { + return LossBasedBandwidthEstimatorV1Enabled() && + loss_based_bandwidth_estimator_v1_.InUse(); +} + +bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV2Enabled() const { + return loss_based_bandwidth_estimator_v2_.IsEnabled(); +} + +bool SendSideBandwidthEstimation::LossBasedBandwidthEstimatorV2ReadyForUse() + const { + return LossBasedBandwidthEstimatorV2Enabled() && + loss_based_bandwidth_estimator_v2_.IsReady(); +} + } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 8c4d217d52..00cfd71724 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -18,6 +18,7 @@ #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "modules/bitrate_controller/loss_based_bandwidth_estimation.h" +#include "modules/bitrate_controller/loss_based_bwe_v2.h" #include "rtc_base/experiments/field_trial_parser.h" #include @@ -32,9 +33,13 @@ class LinkCapacityTracker { public: LinkCapacityTracker(); ~LinkCapacityTracker(); - void OnOveruse(DataRate acknowledged_rate, Timestamp at_time); + // Call when a new delay-based estimate is available. + void UpdateDelayBasedEstimate(Timestamp at_time, + DataRate delay_based_bitrate); void OnStartingRate(DataRate start_rate); - void OnRateUpdate(DataRate acknowledged, Timestamp at_time); + void OnRateUpdate(absl::optional acknowledged, + DataRate target, + Timestamp at_time); void OnRttBackoff(DataRate backoff_rate, Timestamp at_time); DataRate estimate() const; @@ -42,24 +47,24 @@ class LinkCapacityTracker { FieldTrialParameter tracking_rate; double capacity_estimate_bps_ = 0; Timestamp last_link_capacity_update_ = Timestamp::MinusInfinity(); + DataRate last_delay_based_estimate_ = DataRate::PlusInfinity(); }; class RttBasedBackoff { public: - RttBasedBackoff(); + explicit RttBasedBackoff(const WebRtcKeyValueConfig* key_value_config); ~RttBasedBackoff(); - void OnRouteChange(); void UpdatePropagationRtt(Timestamp at_time, TimeDelta propagation_rtt); TimeDelta CorrectedRtt(Timestamp at_time) const; - FieldTrialParameter rtt_limit_; + FieldTrialFlag disabled_; + FieldTrialParameter configured_limit_; FieldTrialParameter drop_fraction_; FieldTrialParameter drop_interval_; - FieldTrialFlag persist_on_route_change_; - FieldTrialParameter safe_timeout_; FieldTrialParameter bandwidth_floor_; public: + TimeDelta rtt_limit_; Timestamp last_propagation_rtt_update_; TimeDelta last_propagation_rtt_; Timestamp last_packet_sent_; @@ -67,11 +72,17 @@ class RttBasedBackoff { class SendSideBandwidthEstimation { public: - SendSideBandwidthEstimation(); + SendSideBandwidthEstimation() = delete; + SendSideBandwidthEstimation(const WebRtcKeyValueConfig* key_value_config); ~SendSideBandwidthEstimation(); void OnRouteChange(); - void CurrentEstimate(int* bitrate, uint8_t* loss, int64_t* rtt) const; + + DataRate target_rate() const; + DataRate delay_based_limit() const; + uint8_t fraction_loss() const { return last_fraction_loss_; } + TimeDelta round_trip_time() const { return last_round_trip_time_; } + DataRate GetEstimatedLinkCapacity() const; // Call periodically to update estimate. void UpdateEstimate(Timestamp at_time); @@ -85,14 +96,8 @@ class SendSideBandwidthEstimation { void UpdateDelayBasedEstimate(Timestamp at_time, DataRate bitrate); // Call when we receive a RTCP message with a ReceiveBlock. - void UpdateReceiverBlock(uint8_t fraction_loss, - TimeDelta rtt_ms, - int number_of_packets, - Timestamp at_time); - - // Call when we receive a RTCP message with a ReceiveBlock. - void UpdatePacketsLost(int packets_lost, - int number_of_packets, + void UpdatePacketsLost(int64_t packets_lost, + int64_t number_of_packets, Timestamp at_time); // Call when we receive a RTCP message with a ReceiveBlock. @@ -107,7 +112,8 @@ class SendSideBandwidthEstimation { int GetMinBitrate() const; void SetAcknowledgedRate(absl::optional acknowledged_rate, Timestamp at_time); - void IncomingPacketFeedbackVector(const TransportPacketsFeedback& report); + void UpdateLossBasedEstimator(const TransportPacketsFeedback& report, + BandwidthUsage delay_detector_state); private: friend class GoogCcStatePrinter; @@ -123,11 +129,29 @@ class SendSideBandwidthEstimation { // min bitrate used during last kBweIncreaseIntervalMs. void UpdateMinHistory(Timestamp at_time); - DataRate MaybeRampupOrBackoff(DataRate new_bitrate, Timestamp at_time); - - // Cap |bitrate| to [min_bitrate_configured_, max_bitrate_configured_] and - // set |current_bitrate_| to the capped value and updates the event log. - void CapBitrateToThresholds(Timestamp at_time, DataRate bitrate); + // Gets the upper limit for the target bitrate. This is the minimum of the + // delay based limit, the receiver limit and the loss based controller limit. + DataRate GetUpperLimit() const; + // Prints a warning if `bitrate` if sufficiently long time has past since last + // warning. + void MaybeLogLowBitrateWarning(DataRate bitrate, Timestamp at_time); + // Stores an update to the event log if the loss rate has changed, the target + // has changed, or sufficient time has passed since last stored event. + void MaybeLogLossBasedEvent(Timestamp at_time); + + // Cap `bitrate` to [min_bitrate_configured_, max_bitrate_configured_] and + // set `current_bitrate_` to the capped value and updates the event log. + void UpdateTargetBitrate(DataRate bitrate, Timestamp at_time); + // Applies lower and upper bounds to the current target rate. + // TODO(srte): This seems to be called even when limits haven't changed, that + // should be cleaned up. + void ApplyTargetLimits(Timestamp at_time); + + bool LossBasedBandwidthEstimatorV1Enabled() const; + bool LossBasedBandwidthEstimatorV2Enabled() const; + + bool LossBasedBandwidthEstimatorV1ReadyForUse() const; + bool LossBasedBandwidthEstimatorV2ReadyForUse() const; RttBasedBackoff rtt_backoff_; LinkCapacityTracker link_capacity_; @@ -139,7 +163,8 @@ class SendSideBandwidthEstimation { int expected_packets_since_last_loss_update_; absl::optional acknowledged_rate_; - DataRate current_bitrate_; + DataRate current_target_; + DataRate last_logged_target_; DataRate min_bitrate_configured_; DataRate max_bitrate_configured_; Timestamp last_low_bitrate_log_; @@ -147,13 +172,15 @@ class SendSideBandwidthEstimation { bool has_decreased_since_last_fraction_loss_; Timestamp last_loss_feedback_; Timestamp last_loss_packet_report_; - Timestamp last_timeout_; uint8_t last_fraction_loss_; uint8_t last_logged_fraction_loss_; TimeDelta last_round_trip_time_; - DataRate bwe_incoming_; - DataRate delay_based_bitrate_; + // The max bitrate as set by the receiver in the call. This is typically + // signalled using the REMB RTCP message and is used when we don't have any + // send side delay based estimate. + DataRate receiver_limit_; + DataRate delay_based_limit_; Timestamp time_last_decrease_; Timestamp first_report_time_; int initially_lost_packets_; @@ -162,11 +189,12 @@ class SendSideBandwidthEstimation { UmaState uma_rtt_state_; std::vector rampup_uma_stats_updated_; Timestamp last_rtc_event_log_; - bool in_timeout_experiment_; float low_loss_threshold_; float high_loss_threshold_; DataRate bitrate_threshold_; - LossBasedBandwidthEstimation loss_based_bandwidth_estimation_; + LossBasedBandwidthEstimation loss_based_bandwidth_estimator_v1_; + LossBasedBweV2 loss_based_bandwidth_estimator_v2_; + FieldTrialFlag disable_receiver_limit_caps_only_; }; } // namespace webrtc #endif // MODULES_BITRATE_CONTROLLER_SEND_SIDE_BANDWIDTH_ESTIMATION_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h index dcfebf2649..95755697ef 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h @@ -14,6 +14,7 @@ #include "api/transport/network_types.h" #include "api/transport/webrtc_key_value_config.h" #include "api/units/data_rate.h" +#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h" #include "modules/congestion_controller/goog_cc/bitrate_estimator.h" #include @@ -22,7 +23,8 @@ namespace webrtc { -class AcknowledgedBitrateEstimator { +class AcknowledgedBitrateEstimator + : public AcknowledgedBitrateEstimatorInterface { public: AcknowledgedBitrateEstimator( const WebRtcKeyValueConfig* key_value_config, @@ -30,14 +32,14 @@ class AcknowledgedBitrateEstimator { explicit AcknowledgedBitrateEstimator( const WebRtcKeyValueConfig* key_value_config); - ~AcknowledgedBitrateEstimator(); + ~AcknowledgedBitrateEstimator() override; void IncomingPacketFeedbackVector( - const std::vector& packet_feedback_vector); - absl::optional bitrate() const; - absl::optional PeekRate() const; - void SetAlr(bool in_alr); - void SetAlrEndedTime(Timestamp alr_ended_time); + const std::vector& packet_feedback_vector) override; + absl::optional bitrate() const override; + absl::optional PeekRate() const override; + void SetAlr(bool in_alr) override; + void SetAlrEndedTime(Timestamp alr_ended_time) override; private: absl::optional alr_ended_time_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc new file mode 100644 index 0000000000..6bfd1c81cb --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2019 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. + */ +#define MS_CLASS "webrtc::AcknowledgedBitrateEstimator" + +#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h" + +#include + +#include "api/units/time_delta.h" +#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h" +#include "modules/congestion_controller/goog_cc/robust_throughput_estimator.h" +#include "api/transport/webrtc_key_value_config.h" +#include "Logger.hpp" +// #include "rtc_base/logging.h" + +namespace webrtc { + +constexpr char RobustThroughputEstimatorSettings::kKey[]; + +RobustThroughputEstimatorSettings::RobustThroughputEstimatorSettings( + const WebRtcKeyValueConfig* key_value_config) { + Parser()->Parse( + key_value_config->Lookup(RobustThroughputEstimatorSettings::kKey)); + if (window_packets < 10 || 1000 < window_packets) { + MS_WARN_TAG(bwe, "Window size must be between 10 and 1000 packets"); + window_packets = 20; + } + if (max_window_packets < 10 || 1000 < max_window_packets) { + MS_WARN_TAG(bwe, "Max window size must be between 10 and 1000 packets"); + max_window_packets = 500; + } + max_window_packets = std::max(max_window_packets, window_packets); + + if (required_packets < 10 || 1000 < required_packets) { + MS_WARN_TAG(bwe, "Required number of initial packets must be between " + "10 and 1000 packets"); + required_packets = 10; + } + required_packets = std::min(required_packets, window_packets); + + if (min_window_duration < TimeDelta::Millis<100>() || + TimeDelta::Millis<3000>() < min_window_duration) { + MS_WARN_TAG(bwe, "Window duration must be between 100 and 3000 ms"); + min_window_duration = TimeDelta::Millis<750>(); + } + if (max_window_duration < TimeDelta::Seconds<1>() || + TimeDelta::Seconds<15>() < max_window_duration) { + MS_WARN_TAG(bwe, "Max window duration must be between 1 and 15 s"); + max_window_duration = TimeDelta::Seconds<5>(); + } + min_window_duration = std::min(min_window_duration, max_window_duration); + + if (unacked_weight < 0.0 || 1.0 < unacked_weight) { + MS_WARN_TAG(bwe, "Weight for prior unacked size must be between 0 and 1."); + unacked_weight = 1.0; + } +} + +std::unique_ptr +RobustThroughputEstimatorSettings::Parser() { + return StructParametersParser::Create( + "enabled", &enabled, // + "window_packets", &window_packets, // + "max_window_packets", &max_window_packets, // + "window_duration", &min_window_duration, // + "max_window_duration", &max_window_duration, // + "required_packets", &required_packets, // + "unacked_weight", &unacked_weight); +} + +AcknowledgedBitrateEstimatorInterface:: + ~AcknowledgedBitrateEstimatorInterface() {} + +std::unique_ptr +AcknowledgedBitrateEstimatorInterface::Create( + const WebRtcKeyValueConfig* key_value_config) { + RobustThroughputEstimatorSettings simplified_estimator_settings( + key_value_config); + if (simplified_estimator_settings.enabled) { + return absl::make_unique( + simplified_estimator_settings); + } + return absl::make_unique(key_value_config); +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h new file mode 100644 index 0000000000..38354707e9 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2019 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. + */ + +#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_INTERFACE_H_ +#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_INTERFACE_H_ + +#include + +#include +#include + +#include "absl/types/optional.h" +// #include "api/field_trials_view.h" +#include "api/transport/network_types.h" +#include "api/units/data_rate.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "rtc_base/experiments/struct_parameters_parser.h" +#include "api/transport/webrtc_key_value_config.h" + + +namespace webrtc { + +struct RobustThroughputEstimatorSettings { + static constexpr char kKey[] = "WebRTC-Bwe-RobustThroughputEstimatorSettings"; + + RobustThroughputEstimatorSettings() = delete; + explicit RobustThroughputEstimatorSettings( + const WebRtcKeyValueConfig* key_value_config); + + bool enabled = false; // Set to true to use RobustThroughputEstimator. + + // The estimator keeps the smallest window containing at least + // `window_packets` and at least the packets received during the last + // `min_window_duration` milliseconds. + // (This means that it may store more than `window_packets` at high bitrates, + // and a longer duration than `min_window_duration` at low bitrates.) + // However, if will never store more than kMaxPackets (for performance + // reasons), and never longer than max_window_duration (to avoid very old + // packets influencing the estimate for example when sending is paused). + unsigned window_packets = 20; + unsigned max_window_packets = 500; + TimeDelta min_window_duration = TimeDelta::Seconds<1>(); + TimeDelta max_window_duration = TimeDelta::Seconds<5>(); + + // The estimator window requires at least `required_packets` packets + // to produce an estimate. + unsigned required_packets = 10; + + // If audio packets aren't included in allocation (i.e. the + // estimated available bandwidth is divided only among the video + // streams), then `unacked_weight` should be set to 0. + // If audio packets are included in allocation, but not in bandwidth + // estimation (i.e. they don't have transport-wide sequence numbers, + // but we nevertheless divide the estimated available bandwidth among + // both audio and video streams), then `unacked_weight` should be set to 1. + // If all packets have transport-wide sequence numbers, then the value + // of `unacked_weight` doesn't matter. + double unacked_weight = 1.0; + + std::unique_ptr Parser(); +}; + +class AcknowledgedBitrateEstimatorInterface { + public: + static std::unique_ptr Create( + const WebRtcKeyValueConfig* key_value_config); + virtual ~AcknowledgedBitrateEstimatorInterface(); + + virtual void IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector) = 0; + virtual absl::optional bitrate() const = 0; + virtual absl::optional PeekRate() const = 0; + virtual void SetAlr(bool in_alr) = 0; + virtual void SetAlrEndedTime(Timestamp alr_ended_time) = 0; +}; + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_ACKNOWLEDGED_BITRATE_ESTIMATOR_INTERFACE_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 95a000d346..0bc5c2d67b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -24,7 +24,7 @@ namespace webrtc { namespace { -absl::optional GetExperimentSettings( +AlrDetectorConfig GetExperimentSettings( const WebRtcKeyValueConfig* key_value_config) { // RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled(*key_value_config)); absl::optional experiment_settings = @@ -36,38 +36,34 @@ absl::optional GetExperimentSettings( *key_value_config, AlrExperimentSettings::kStrictPacingAndProbingExperimentName); } - return experiment_settings; + AlrDetectorConfig conf; + if (experiment_settings) { + conf.bandwidth_usage_ratio = + experiment_settings->alr_bandwidth_usage_percent / 100.0; + conf.start_budget_level_ratio = + experiment_settings->alr_start_budget_level_percent / 100.0; + conf.stop_budget_level_ratio = + experiment_settings->alr_stop_budget_level_percent / 100.0; + } + conf.Parser()->Parse( + key_value_config->Lookup("WebRTC-AlrDetectorParameters")); + return conf; } } // namespace -AlrDetector::AlrDetector(const WebRtcKeyValueConfig* key_value_config) - : AlrDetector(key_value_config, - GetExperimentSettings(key_value_config)) {} - -AlrDetector::AlrDetector( - const WebRtcKeyValueConfig* key_value_config, - absl::optional experiment_settings) - : bandwidth_usage_ratio_( - "bw_usage", - experiment_settings - ? experiment_settings->alr_bandwidth_usage_percent / 100.0 - : kDefaultBandwidthUsageRatio), - start_budget_level_ratio_( - "start", - experiment_settings - ? experiment_settings->alr_start_budget_level_percent / 100.0 - : kDefaultStartBudgetLevelRatio), - stop_budget_level_ratio_( - "stop", - experiment_settings - ? experiment_settings->alr_stop_budget_level_percent / 100.0 - : kDefaultStopBudgetLevelRatio), - alr_budget_(0, true) { - ParseFieldTrial({&bandwidth_usage_ratio_, &start_budget_level_ratio_, - &stop_budget_level_ratio_}, - key_value_config->Lookup("WebRTC-AlrDetectorParameters")); +std::unique_ptr AlrDetectorConfig::Parser() { + return StructParametersParser::Create( // + "bw_usage", &bandwidth_usage_ratio, // + "start", &start_budget_level_ratio, // + "stop", &stop_budget_level_ratio); } +AlrDetector::AlrDetector(AlrDetectorConfig config) + : conf_(config), alr_budget_(0, true) {} + +AlrDetector::AlrDetector(const WebRtcKeyValueConfig* key_value_config) + : AlrDetector(GetExperimentSettings(key_value_config)) {} + AlrDetector::~AlrDetector() {} void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { @@ -83,24 +79,24 @@ void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { alr_budget_.UseBudget(bytes_sent); alr_budget_.IncreaseBudget(delta_time_ms); bool state_changed = false; - if (alr_budget_.budget_ratio() > start_budget_level_ratio_ && + if (alr_budget_.budget_ratio() > conf_.start_budget_level_ratio && !alr_started_time_ms_) { alr_started_time_ms_.emplace(DepLibUV::GetTimeMsInt64()); state_changed = true; - } else if (alr_budget_.budget_ratio() < stop_budget_level_ratio_ && + } else if (alr_budget_.budget_ratio() < conf_.stop_budget_level_ratio && alr_started_time_ms_) { state_changed = true; alr_started_time_ms_.reset(); } - - if (state_changed) - MS_DEBUG_DEV("state changed"); + if (state_changed) { + MS_DEBUG_TAG(bwe, "ALR State change"); + } } void AlrDetector::SetEstimatedBitrate(int bitrate_bps) { //RTC_DCHECK(bitrate_bps); int target_rate_kbps = - static_cast(bitrate_bps) * bandwidth_usage_ratio_ / 1000; + static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; alr_budget_.set_target_rate_kbps(target_rate_kbps); } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h index e1fbb74525..42fc574150 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h @@ -15,6 +15,7 @@ #include "modules/pacing/interval_budget.h" #include "rtc_base/experiments/alr_experiment.h" #include "rtc_base/experiments/field_trial_units.h" +#include "rtc_base/experiments/struct_parameters_parser.h" #include #include @@ -23,6 +24,19 @@ namespace webrtc { +class RtcEventLog; + +struct AlrDetectorConfig { + // Sent traffic ratio as a function of network capacity used to determine + // application-limited region. ALR region start when bandwidth usage drops + // below kAlrStartUsageRatio and ends when it raises above + // kAlrEndUsageRatio. NOTE: This is intentionally conservative at the moment + // until BW adjustments of application limited region is fine tuned. + double bandwidth_usage_ratio = 0.65; + double start_budget_level_ratio = 0.80; + double stop_budget_level_ratio = 0.50; + std::unique_ptr Parser(); +}; // Application limited region detector is a class that utilizes signals of // elapsed time and bytes sent to estimate whether network traffic is // currently limited by the application's ability to generate traffic. @@ -32,6 +46,7 @@ namespace webrtc { // Note: This class is not thread-safe. class AlrDetector { public: + AlrDetector(AlrDetectorConfig config); explicit AlrDetector(const WebRtcKeyValueConfig* key_value_config); ~AlrDetector(); @@ -44,26 +59,9 @@ class AlrDetector { // started or empty result if the sender is currently not application-limited. absl::optional GetApplicationLimitedRegionStartTime() const; - void UpdateBudgetWithElapsedTime(int64_t delta_time_ms); - void UpdateBudgetWithBytesSent(size_t bytes_sent); - private: - // Sent traffic ratio as a function of network capacity used to determine - // application-limited region. ALR region start when bandwidth usage drops - // below kAlrStartUsageRatio and ends when it raises above - // kAlrEndUsageRatio. NOTE: This is intentionally conservative at the moment - // until BW adjustments of application limited region is fine tuned. - static constexpr double kDefaultBandwidthUsageRatio = 0.65; - static constexpr double kDefaultStartBudgetLevelRatio = 0.80; - static constexpr double kDefaultStopBudgetLevelRatio = 0.50; - - AlrDetector(const WebRtcKeyValueConfig* key_value_config, - absl::optional experiment_settings); - friend class GoogCcStatePrinter; - FieldTrialParameter bandwidth_usage_ratio_; - FieldTrialParameter start_budget_level_ratio_; - FieldTrialParameter stop_budget_level_ratio_; + const AlrDetectorConfig conf_; absl::optional last_send_time_ms_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc index 6cdf95a48b..413cbab96f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -26,50 +26,53 @@ namespace webrtc { namespace { constexpr TimeDelta kStreamTimeOut = TimeDelta::Seconds<2>(); -constexpr int kTimestampGroupLengthMs = 5; -constexpr int kAbsSendTimeFraction = 18; -constexpr int kAbsSendTimeInterArrivalUpshift = 8; -constexpr int kInterArrivalShift = - kAbsSendTimeFraction + kAbsSendTimeInterArrivalUpshift; -constexpr double kTimestampToMs = - 1000.0 / static_cast(1 << kInterArrivalShift); +constexpr TimeDelta kSendTimeGroupLength = TimeDelta::Millis<5>(); + // This ssrc is used to fulfill the current API but will be removed // after the API has been changed. constexpr uint32_t kFixedSsrc = 0; - } // namespace +constexpr char BweSeparateAudioPacketsSettings::kKey[]; + +BweSeparateAudioPacketsSettings::BweSeparateAudioPacketsSettings( + const WebRtcKeyValueConfig* key_value_config) { + Parser()->Parse( + key_value_config->Lookup(BweSeparateAudioPacketsSettings::kKey)); +} + +std::unique_ptr +BweSeparateAudioPacketsSettings::Parser() { + return StructParametersParser::Create( // + "enabled", &enabled, // + "packet_threshold", &packet_threshold, // + "time_threshold", &time_threshold); +} + DelayBasedBwe::Result::Result() : updated(false), probe(false), target_bitrate(DataRate::Zero()), - recovered_from_overuse(false), - backoff_in_alr(false) {} - -DelayBasedBwe::Result::Result(bool probe, DataRate target_bitrate) - : updated(true), - probe(probe), - target_bitrate(target_bitrate), - recovered_from_overuse(false), - backoff_in_alr(false) {} - -DelayBasedBwe::Result::~Result() {} + recovered_from_overuse(false) {} DelayBasedBwe::DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config, NetworkStatePredictor* network_state_predictor) : key_value_config_(key_value_config), + separate_audio_(key_value_config), + audio_packets_since_last_video_(0), + last_video_packet_recv_time_(Timestamp::MinusInfinity()), network_state_predictor_(network_state_predictor), - inter_arrival_(), - delay_detector_( + video_delay_detector_( new TrendlineEstimator(key_value_config_, network_state_predictor_)), + audio_delay_detector_( + new TrendlineEstimator(key_value_config_, network_state_predictor_)), + active_delay_detector_(video_delay_detector_.get()), last_seen_packet_(Timestamp::MinusInfinity()), uma_recorded_(false), rate_control_(key_value_config, /*send_side=*/true), prev_bitrate_(DataRate::Zero()), - prev_state_(BandwidthUsage::kBwNormal), - alr_limited_backoff_enabled_( - key_value_config->Lookup("WebRTC-Bwe-AlrLimitedBackoff") - .find("Enabled") == 0) {} + prev_state_(BandwidthUsage::kBwNormal) { +} DelayBasedBwe::~DelayBasedBwe() {} @@ -95,15 +98,15 @@ DelayBasedBwe::Result DelayBasedBwe::IncomingPacketFeedbackVector( } bool delayed_feedback = true; bool recovered_from_overuse = false; - BandwidthUsage prev_detector_state = delay_detector_->State(); + BandwidthUsage prev_detector_state = active_delay_detector_->State(); for (const auto& packet_feedback : packet_feedback_vector) { delayed_feedback = false; IncomingPacketFeedback(packet_feedback, msg.feedback_time); if (prev_detector_state == BandwidthUsage::kBwUnderusing && - delay_detector_->State() == BandwidthUsage::kBwNormal) { + active_delay_detector_->State() == BandwidthUsage::kBwNormal) { recovered_from_overuse = true; } - prev_detector_state = delay_detector_->State(); + prev_detector_state = active_delay_detector_->State(); } if (delayed_feedback) { @@ -123,36 +126,58 @@ void DelayBasedBwe::IncomingPacketFeedback(const PacketResult& packet_feedback, // Reset if the stream has timed out. if (last_seen_packet_.IsInfinite() || at_time - last_seen_packet_ > kStreamTimeOut) { - inter_arrival_.reset( - new InterArrival((kTimestampGroupLengthMs << kInterArrivalShift) / 1000, - kTimestampToMs, true)); - delay_detector_.reset( + video_inter_arrival_delta_ = + absl::make_unique(kSendTimeGroupLength); + audio_inter_arrival_delta_ = + absl::make_unique(kSendTimeGroupLength); + + video_delay_detector_.reset( new TrendlineEstimator(key_value_config_, network_state_predictor_)); + audio_delay_detector_.reset( + new TrendlineEstimator(key_value_config_, network_state_predictor_)); + active_delay_detector_ = video_delay_detector_.get(); } last_seen_packet_ = at_time; - uint32_t send_time_24bits = - static_cast( - ((static_cast(packet_feedback.sent_packet.send_time.ms()) - << kAbsSendTimeFraction) + - 500) / - 1000) & - 0x00FFFFFF; - // Shift up send time to use the full 32 bits that inter_arrival works with, - // so wrapping works properly. - uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift; - - uint32_t ts_delta = 0; - int64_t t_delta = 0; + // As an alternative to ignoring small packets, we can separate audio and + // video packets for overuse detection. + DelayIncreaseDetectorInterface* delay_detector_for_packet = + video_delay_detector_.get(); + if (separate_audio_.enabled) { + if (packet_feedback.sent_packet.audio) { + delay_detector_for_packet = audio_delay_detector_.get(); + audio_packets_since_last_video_++; + if (audio_packets_since_last_video_ > separate_audio_.packet_threshold && + packet_feedback.receive_time - last_video_packet_recv_time_ > + separate_audio_.time_threshold) { + active_delay_detector_ = audio_delay_detector_.get(); + } + } else { + audio_packets_since_last_video_ = 0; + last_video_packet_recv_time_ = + std::max(last_video_packet_recv_time_, packet_feedback.receive_time); + active_delay_detector_ = video_delay_detector_.get(); + } + } + DataSize packet_size = packet_feedback.sent_packet.size; + + TimeDelta send_delta = TimeDelta::Zero(); + TimeDelta recv_delta = TimeDelta::Zero(); int size_delta = 0; - bool calculated_deltas = inter_arrival_->ComputeDeltas( - timestamp, packet_feedback.receive_time.ms(), at_time.ms(), - packet_feedback.sent_packet.size.bytes(), &ts_delta, &t_delta, - &size_delta); - double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift); - delay_detector_->Update(t_delta, ts_delta_ms, - packet_feedback.sent_packet.send_time.ms(), - packet_feedback.receive_time.ms(), calculated_deltas); + + InterArrivalDelta* inter_arrival_for_packet = + (separate_audio_.enabled && packet_feedback.sent_packet.audio) + ? audio_inter_arrival_delta_.get() + : video_inter_arrival_delta_.get(); + bool calculated_deltas = inter_arrival_for_packet->ComputeDeltas( + packet_feedback.sent_packet.send_time, packet_feedback.receive_time, + at_time, packet_size.bytes(), &send_delta, &recv_delta, &size_delta); + + delay_detector_for_packet->Update(recv_delta.ms(), + send_delta.ms(), + packet_feedback.sent_packet.send_time.ms(), + packet_feedback.receive_time.ms(), + packet_size.bytes(), calculated_deltas); } DataRate DelayBasedBwe::TriggerOveruse(Timestamp at_time, @@ -171,24 +196,9 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( Result result; // Currently overusing the bandwidth. - if (delay_detector_->State() == BandwidthUsage::kBwOverusing) { - MS_DEBUG_DEV("delay_detector_->State() == BandwidthUsage::kBwOverusing"); - MS_DEBUG_DEV("in_alr: %s", in_alr ? "true" : "false"); - if (in_alr && alr_limited_backoff_enabled_) { - if (rate_control_.TimeToReduceFurther(at_time, prev_bitrate_)) { - MS_DEBUG_DEV("alr_limited_backoff_enabled_ is true, prev_bitrate:%lld, result.target_bitrate:%lld", - prev_bitrate_.bps(), - result.target_bitrate.bps()); - - result.updated = - UpdateEstimate(at_time, prev_bitrate_, &result.target_bitrate); - result.backoff_in_alr = true; - } - } else if (acked_bitrate && - rate_control_.TimeToReduceFurther(at_time, *acked_bitrate)) { - MS_DEBUG_DEV("acked_bitrate:%lld, result.target_bitrate:%lld", - acked_bitrate.value().bps(), - result.target_bitrate.bps()); + if (active_delay_detector_->State() == BandwidthUsage::kBwOverusing) { + if (acked_bitrate && + rate_control_.TimeToReduceFurther(at_time, *acked_bitrate)) { result.updated = UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); } else if (!acked_bitrate && rate_control_.ValidEstimate() && @@ -208,15 +218,15 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( MS_DEBUG_DEV("probe bitrate: %lld", probe_bitrate.value().bps()); result.probe = true; result.updated = true; - result.target_bitrate = *probe_bitrate; rate_control_.SetEstimate(*probe_bitrate, at_time); + result.target_bitrate = rate_control_.LatestEstimate(); } else { result.updated = UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); result.recovered_from_overuse = recovered_from_overuse; } } - BandwidthUsage detector_state = delay_detector_->State(); + BandwidthUsage detector_state = active_delay_detector_->State(); if ((result.updated && prev_bitrate_ != result.target_bitrate) || detector_state != prev_state_) { DataRate bitrate = result.updated ? result.target_bitrate : prev_bitrate_; @@ -229,13 +239,15 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( prev_state_ = detector_state; } + + result.delay_detector_state = detector_state; return result; } bool DelayBasedBwe::UpdateEstimate(Timestamp at_time, absl::optional acked_bitrate, DataRate* target_rate) { - const RateControlInput input(delay_detector_->State(), acked_bitrate); + const RateControlInput input(active_delay_detector_->State(), acked_bitrate); *target_rate = rate_control_.Update(&input, at_time); return rate_control_.ValidEstimate(); } @@ -279,8 +291,4 @@ TimeDelta DelayBasedBwe::GetExpectedBwePeriod() const { return rate_control_.GetExpectedBandwidthPeriod(); } -void DelayBasedBwe::SetAlrLimitedBackoffExperiment(bool enabled) { - alr_limited_backoff_enabled_ = enabled; -} - } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h index e29340ec65..a6a2cf6936 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -19,7 +19,10 @@ #include "modules/remote_bitrate_estimator/aimd_rate_control.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "modules/remote_bitrate_estimator/inter_arrival.h" +#include "modules/congestion_controller/goog_cc/inter_arrival_delta.h" #include "rtc_base/constructor_magic.h" +#include "rtc_base/experiments/struct_parameters_parser.h" +// #include "rtc_base/race_checker.h" #include #include @@ -31,21 +34,39 @@ namespace webrtc { class RtcEventLog; +struct BweSeparateAudioPacketsSettings { + static constexpr char kKey[] = "WebRTC-Bwe-SeparateAudioPackets"; + + BweSeparateAudioPacketsSettings() = default; + explicit BweSeparateAudioPacketsSettings( + const WebRtcKeyValueConfig* key_value_config); + + bool enabled = false; + int packet_threshold = 10; + TimeDelta time_threshold = TimeDelta::Seconds<1>(); + + std::unique_ptr Parser(); +}; + class DelayBasedBwe { public: struct Result { Result(); - Result(bool probe, DataRate target_bitrate); - ~Result(); + ~Result() = default; bool updated; bool probe; DataRate target_bitrate = DataRate::Zero(); bool recovered_from_overuse; - bool backoff_in_alr; + BandwidthUsage delay_detector_state; }; explicit DelayBasedBwe(const WebRtcKeyValueConfig* key_value_config, NetworkStatePredictor* network_state_predictor); + + DelayBasedBwe() = delete; + DelayBasedBwe(const DelayBasedBwe&) = delete; + DelayBasedBwe& operator=(const DelayBasedBwe&) = delete; + virtual ~DelayBasedBwe(); Result IncomingPacketFeedbackVector( @@ -59,10 +80,9 @@ class DelayBasedBwe { void SetStartBitrate(DataRate start_bitrate); void SetMinBitrate(DataRate min_bitrate); TimeDelta GetExpectedBwePeriod() const; - void SetAlrLimitedBackoffExperiment(bool enabled); - DataRate TriggerOveruse(Timestamp at_time, absl::optional link_capacity); + DataRate last_estimate() const { return prev_bitrate_; } private: friend class GoogCcStatePrinter; @@ -77,22 +97,35 @@ class DelayBasedBwe { Timestamp at_time); // Updates the current remote rate estimate and returns true if a valid // estimate exists. - bool UpdateEstimate(Timestamp now, + bool UpdateEstimate(Timestamp at_time, absl::optional acked_bitrate, - DataRate* target_bitrate); + DataRate* target_rate); + // rtc::RaceChecker network_race_; + // RtcEventLog* const event_log_; const WebRtcKeyValueConfig* const key_value_config_; + + // Alternatively, run two separate overuse detectors for audio and video, + // and fall back to the audio one if we haven't seen a video packet in a + // while. + BweSeparateAudioPacketsSettings separate_audio_; + int64_t audio_packets_since_last_video_; + Timestamp last_video_packet_recv_time_; + NetworkStatePredictor* network_state_predictor_; - std::unique_ptr inter_arrival_; - std::unique_ptr delay_detector_; + std::unique_ptr video_inter_arrival_; + std::unique_ptr video_inter_arrival_delta_; + std::unique_ptr video_delay_detector_; + std::unique_ptr audio_inter_arrival_; + std::unique_ptr audio_inter_arrival_delta_; + std::unique_ptr audio_delay_detector_; + DelayIncreaseDetectorInterface* active_delay_detector_; + Timestamp last_seen_packet_; bool uma_recorded_; AimdRateControl rate_control_; DataRate prev_bitrate_; BandwidthUsage prev_state_; - bool alr_limited_backoff_enabled_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(DelayBasedBwe); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h index f730181ad3..af644f9271 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h @@ -11,7 +11,6 @@ #define MODULES_CONGESTION_CONTROLLER_GOOG_CC_DELAY_INCREASE_DETECTOR_INTERFACE_H_ #include "modules/remote_bitrate_estimator/include/bwe_defines.h" -#include "rtc_base/constructor_magic.h" #include @@ -22,17 +21,21 @@ class DelayIncreaseDetectorInterface { DelayIncreaseDetectorInterface() {} virtual ~DelayIncreaseDetectorInterface() {} + DelayIncreaseDetectorInterface(const DelayIncreaseDetectorInterface&) = + delete; + DelayIncreaseDetectorInterface& operator=( + const DelayIncreaseDetectorInterface&) = delete; + // Update the detector with a new sample. The deltas should represent deltas // between timestamp groups as defined by the InterArrival class. virtual void Update(double recv_delta_ms, double send_delta_ms, int64_t send_time_ms, int64_t arrival_time_ms, + size_t packet_size, bool calculated_deltas) = 0; virtual BandwidthUsage State() const = 0; - - RTC_DISALLOW_COPY_AND_ASSIGN(DelayIncreaseDetectorInterface); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index abc4320ee2..5436c81c3f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -41,7 +41,13 @@ constexpr TimeDelta kLossUpdateInterval = TimeDelta::Millis<1000>(); // the number of bytes that can be transmitted per interval. // Increasing this factor will result in lower delays in cases of bitrate // overshoots from the encoder. -const float kDefaultPaceMultiplier = 2.5f; +constexpr float kDefaultPaceMultiplier = 2.5f; + +// If the probe result is far below the current throughput estimate +// it's unlikely that the probe is accurate, so we don't want to drop too far. +// However, if we actually are overusing, we want to drop to something slightly +// below the current throughput estimate to drain the network queues. +constexpr double kProbeDropThroughputFraction = 0.85; int64_t GetBpsOrDefault(const absl::optional& rate, int64_t fallback_bps) { @@ -60,23 +66,29 @@ bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) { } // namespace GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, - GoogCcConfig congestion_controller_config) + GoogCcConfig goog_cc_config) : key_value_config_(config.key_value_config ? config.key_value_config : &trial_based_config_), - packet_feedback_only_(congestion_controller_config.feedback_only), + packet_feedback_only_(goog_cc_config.feedback_only), safe_reset_on_route_change_("Enabled"), safe_reset_acknowledged_rate_("ack"), - use_stable_bandwidth_estimate_( - IsEnabled(key_value_config_, "WebRTC-Bwe-StableBandwidthEstimate")), - use_downlink_delay_for_congestion_window_( - IsEnabled(key_value_config_, - "WebRTC-Bwe-CongestionWindowDownlinkDelay")), - fall_back_to_probe_rate_( - IsEnabled(key_value_config_, "WebRTC-Bwe-ProbeRateFallback")), use_min_allocatable_as_lower_bound_( IsNotDisabled(key_value_config_, "WebRTC-Bwe-MinAllocAsLowerBound")), + ignore_probes_lower_than_network_estimate_(IsNotDisabled( + key_value_config_, + "WebRTC-Bwe-IgnoreProbesLowerThanNetworkStateEstimate")), + limit_probes_lower_than_throughput_estimate_( + IsEnabled(key_value_config_, + "WebRTC-Bwe-LimitProbesLowerThanThroughputEstimate")), rate_control_settings_( RateControlSettings::ParseFromKeyValueConfig(key_value_config_)), + loss_based_stable_rate_( + IsEnabled(key_value_config_, "WebRTC-Bwe-LossBasedStableRate")), + pace_at_max_of_bwe_and_lower_link_capacity_( + IsEnabled(key_value_config_, + "WebRTC-Bwe-PaceAtMaxOfBweAndLowerLinkCapacity")), + pace_at_loss_based_bwe_when_loss_( + IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtLossBaseBweWhenLoss")), probe_controller_( new ProbeController(key_value_config_)), congestion_window_pushback_controller_( @@ -85,20 +97,21 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, key_value_config_) : nullptr), bandwidth_estimation_( - absl::make_unique()), + absl::make_unique(key_value_config_)), alr_detector_( absl::make_unique(key_value_config_)), probe_bitrate_estimator_(new ProbeBitrateEstimator()), - network_estimator_(std::move(congestion_controller_config.network_state_estimator)), + network_estimator_(std::move(goog_cc_config.network_state_estimator)), network_state_predictor_( - std::move(congestion_controller_config.network_state_predictor)), + std::move(goog_cc_config.network_state_predictor)), delay_based_bwe_(new DelayBasedBwe(key_value_config_, network_state_predictor_.get())), acknowledged_bitrate_estimator_( - absl::make_unique(key_value_config_)), + AcknowledgedBitrateEstimatorInterface::Create(key_value_config_)), initial_config_(config), - last_raw_target_rate_(*config.constraints.starting_rate), - last_pushback_target_rate_(last_raw_target_rate_), + last_loss_based_target_rate_(*config.constraints.starting_rate), + last_pushback_target_rate_(last_loss_based_target_rate_), + last_stable_target_rate_(last_loss_based_target_rate_), pacing_factor_(config.stream_based_config.pacing_factor.value_or( kDefaultPaceMultiplier)), min_total_allocated_bitrate_( @@ -133,12 +146,7 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange( if (!estimated_bitrate) estimated_bitrate = acknowledged_bitrate_estimator_->PeekRate(); } else { - int32_t target_bitrate_bps; - uint8_t fraction_loss; - int64_t rtt_ms; - bandwidth_estimation_->CurrentEstimate(&target_bitrate_bps, - &fraction_loss, &rtt_ms); - estimated_bitrate = DataRate::bps(target_bitrate_bps); + estimated_bitrate = bandwidth_estimation_->target_rate(); } if (estimated_bitrate) { if (msg.constraints.starting_rate) { @@ -150,15 +158,15 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange( } } - acknowledged_bitrate_estimator_.reset( - new AcknowledgedBitrateEstimator(key_value_config_)); + acknowledged_bitrate_estimator_ = + AcknowledgedBitrateEstimatorInterface::Create(key_value_config_); probe_bitrate_estimator_.reset(new ProbeBitrateEstimator()); if (network_estimator_) network_estimator_->OnRouteChange(msg); delay_based_bwe_.reset(new DelayBasedBwe(key_value_config_, network_state_predictor_.get())); bandwidth_estimation_->OnRouteChange(); - probe_controller_->Reset(msg.at_time.ms()); + probe_controller_->Reset(msg.at_time); NetworkControlUpdate update; update.probe_cluster_configs = ResetConstraints(msg.constraints); MaybeTriggerOnNetworkChanged(&update, msg.at_time); @@ -181,7 +189,7 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( initial_config_->stream_based_config.max_total_allocated_bitrate; if (total_bitrate) { auto probes = probe_controller_->OnMaxTotalAllocatedBitrate( - total_bitrate->bps(), msg.at_time.ms()); + *total_bitrate, msg.at_time); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); @@ -198,10 +206,14 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( alr_detector_->GetApplicationLimitedRegionStartTime(); probe_controller_->SetAlrStartTimeMs(start_time_ms); - auto probes = probe_controller_->Process(msg.at_time.ms()); + auto probes = probe_controller_->Process(msg.at_time); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); + if (rate_control_settings_.UseCongestionWindow() && + last_packet_received_time_.IsFinite() && !feedback_max_rtts_.empty()) { + UpdateCongestionWindowSize(); + } if (congestion_window_pushback_controller_ && current_data_window_) { congestion_window_pushback_controller_->SetDataWindow( *current_data_window_); @@ -251,14 +263,10 @@ NetworkControlUpdate GoogCcNetworkController::OnSentPacket( TimeDelta::Zero()); } bandwidth_estimation_->OnSentPacket(sent_packet); - bool network_changed = false; if (congestion_window_pushback_controller_) { congestion_window_pushback_controller_->UpdateOutstandingData( sent_packet.data_in_flight.bytes()); - network_changed = true; - } - if (network_changed) { NetworkControlUpdate update; MaybeTriggerOnNetworkChanged(&update, sent_packet.send_time); return update; @@ -267,6 +275,12 @@ NetworkControlUpdate GoogCcNetworkController::OnSentPacket( } } +NetworkControlUpdate GoogCcNetworkController::OnReceivedPacket( + ReceivedPacket received_packet) { + last_packet_received_time_ = received_packet.receive_time; + return NetworkControlUpdate(); +} + NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig( StreamsConfig msg) { NetworkControlUpdate update; @@ -278,9 +292,9 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig( if (rate_control_settings_.TriggerProbeOnMaxAllocatedBitrateChange()) { update.probe_cluster_configs = probe_controller_->OnMaxTotalAllocatedBitrate( - msg.max_total_allocated_bitrate->bps(), msg.at_time.ms()); + *msg.max_total_allocated_bitrate, msg.at_time); } else { - probe_controller_->SetMaxBitrate(msg.max_total_allocated_bitrate->bps()); + probe_controller_->SetMaxBitrate(*msg.max_total_allocated_bitrate); } max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate; } @@ -350,7 +364,7 @@ void GoogCcNetworkController::ClampConstraints() { std::vector GoogCcNetworkController::ResetConstraints( TargetRateConstraints new_constraints) { - min_data_rate_ = new_constraints.min_data_rate.value_or(DataRate::Zero()); + min_target_rate_ = new_constraints.min_data_rate.value_or(DataRate::Zero()); max_data_rate_ = new_constraints.max_data_rate.value_or(DataRate::PlusInfinity()); starting_rate_ = new_constraints.starting_rate; @@ -368,8 +382,8 @@ std::vector GoogCcNetworkController::ResetConstraints( delay_based_bwe_->SetMinBitrate(min_data_rate_); return probe_controller_->SetBitrates( - min_data_rate_.bps(), GetBpsOrDefault(starting_rate_, -1), - max_data_rate_.bps_or(-1), new_constraints.at_time.ms()); + min_data_rate_, starting_rate_.value_or(DataRate::Zero()), max_data_rate_, + new_constraints.at_time); } NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport( @@ -383,8 +397,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportLossReport( return NetworkControlUpdate(); } -void GoogCcNetworkController::UpdateCongestionWindowSize( - TimeDelta time_since_last_packet) { +void GoogCcNetworkController::UpdateCongestionWindowSize() { TimeDelta min_feedback_max_rtt = TimeDelta::ms( *std::min_element(feedback_max_rtts_.begin(), feedback_max_rtts_.end())); @@ -394,11 +407,7 @@ void GoogCcNetworkController::UpdateCongestionWindowSize( TimeDelta::ms( rate_control_settings_.GetCongestionWindowAdditionalTimeMs()); - if (use_downlink_delay_for_congestion_window_) { - time_window += time_since_last_packet; - } - - DataSize data_window = last_raw_target_rate_ * time_window; + DataSize data_window = last_loss_based_target_rate_ * time_window; if (current_data_window_) { data_window = std::max(kMinCwnd, (data_window + current_data_window_.value()) / 2); @@ -431,7 +440,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( for (const auto& feedback : feedbacks) { TimeDelta feedback_rtt = report.feedback_time - feedback.sent_packet.send_time; - TimeDelta min_pending_time = feedback.receive_time - max_recv_time; + TimeDelta min_pending_time = max_recv_time - feedback.receive_time; TimeDelta propagation_rtt = feedback_rtt - min_pending_time; max_feedback_rtt = std::max(max_feedback_rtt, feedback_rtt); min_propagation_rtt = std::min(min_propagation_rtt, propagation_rtt); @@ -448,8 +457,9 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( } if (packet_feedback_only_) { if (!feedback_max_rtts_.empty()) { - int64_t sum_rtt_ms = std::accumulate(feedback_max_rtts_.begin(), - feedback_max_rtts_.end(), 0); + int64_t sum_rtt_ms = + std::accumulate(feedback_max_rtts_.begin(), feedback_max_rtts_.end(), + static_cast(0)); int64_t mean_rtt_ms = sum_rtt_ms / feedback_max_rtts_.size(); if (delay_based_bwe_) delay_based_bwe_->OnRttUpdate(TimeDelta::ms(mean_rtt_ms)); @@ -470,7 +480,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( expected_packets_since_last_loss_update_ += report.PacketsWithFeedback().size(); for (const auto& packet_feedback : report.PacketsWithFeedback()) { - if (packet_feedback.receive_time.IsInfinite()) + if (!packet_feedback.IsReceived()) lost_packets_since_last_loss_update_ += 1; } if (report.feedback_time > next_loss_update_) { @@ -494,6 +504,8 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( acknowledged_bitrate_estimator_->IncomingPacketFeedbackVector( report.SortedByReceiveTime()); auto acknowledged_bitrate = acknowledged_bitrate_estimator_->bitrate(); + bandwidth_estimation_->SetAcknowledgedRate(acknowledged_bitrate, + report.feedback_time); for (const auto& feedback : report.SortedByReceiveTime()) { if (feedback.sent_packet.pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe) { @@ -501,22 +513,43 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( } } - absl::optional probe_bitrate = - probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(); - if (fall_back_to_probe_rate_ && !acknowledged_bitrate) - acknowledged_bitrate = probe_bitrate_estimator_->last_estimate(); - bandwidth_estimation_->SetAcknowledgedRate(acknowledged_bitrate, - report.feedback_time); - bandwidth_estimation_->IncomingPacketFeedbackVector(report); - if (network_estimator_) { network_estimator_->OnTransportPacketsFeedback(report); + auto prev_estimate = estimate_; estimate_ = network_estimator_->GetCurrentEstimate(); + // TODO(srte): Make OnTransportPacketsFeedback signal whether the state + // changed to avoid the need for this check. + if (estimate_ && (!prev_estimate || estimate_->last_feed_time != + prev_estimate->last_feed_time)) { +/* event_log_->Log(std::make_unique( + estimate_->link_capacity_lower, estimate_->link_capacity_upper));*/ + probe_controller_->SetNetworkStateEstimate(*estimate_); + } + } + absl::optional probe_bitrate = + probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(); + if (ignore_probes_lower_than_network_estimate_ && probe_bitrate && + estimate_ && *probe_bitrate < delay_based_bwe_->last_estimate() && + *probe_bitrate < estimate_->link_capacity_lower) { + probe_bitrate.reset(); + } + if (limit_probes_lower_than_throughput_estimate_ && probe_bitrate && + acknowledged_bitrate) { + // Limit the backoff to something slightly below the acknowledged + // bitrate. ("Slightly below" because we want to drain the queues + // if we are actually overusing.) + // The acknowledged bitrate shouldn't normally be higher than the delay + // based estimate, but it could happen e.g. due to packet bursts or + // encoder overshoot. We use std::min to ensure that a probe result + // below the current BWE never causes an increase. + DataRate limit = + std::min(delay_based_bwe_->last_estimate(), + *acknowledged_bitrate * kProbeDropThroughputFraction); + probe_bitrate = std::max(*probe_bitrate, limit); } NetworkControlUpdate update; bool recovered_from_overuse = false; - bool backoff_in_alr = false; DelayBasedBwe::Result result; result = delay_based_bwe_->IncomingPacketFeedbackVector( @@ -532,20 +565,19 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( // call UpdateDelayBasedEstimate after SetSendBitrate. bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time, result.target_bitrate); + } + bandwidth_estimation_->UpdateLossBasedEstimator(report, + result.delay_detector_state); + if (result.updated) { // Update the estimate in the ProbeController, in case we want to probe. MaybeTriggerOnNetworkChanged(&update, report.feedback_time); } + recovered_from_overuse = result.recovered_from_overuse; - backoff_in_alr = result.backoff_in_alr; if (recovered_from_overuse) { probe_controller_->SetAlrStartTimeMs(alr_start_time); - auto probes = probe_controller_->RequestProbe(report.feedback_time.ms()); - update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), - probes.begin(), probes.end()); - } else if (backoff_in_alr) { - // If we just backed off during ALR, request a new probe. - auto probes = probe_controller_->RequestProbe(report.feedback_time.ms()); + auto probes = probe_controller_->RequestProbe(report.feedback_time); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); } @@ -554,7 +586,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( // we don't try to limit the outstanding packets. if (rate_control_settings_.UseCongestionWindow() && max_feedback_rtt.IsFinite()) { - UpdateCongestionWindowSize(/*time_since_last_packet*/ TimeDelta::Zero()); + UpdateCongestionWindowSize(); } if (congestion_window_pushback_controller_ && current_data_window_) { congestion_window_pushback_controller_->SetDataWindow( @@ -574,22 +606,20 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkStateEstimate( NetworkControlUpdate GoogCcNetworkController::GetNetworkState( Timestamp at_time) const { - DataRate bandwidth = use_stable_bandwidth_estimate_ - ? bandwidth_estimation_->GetEstimatedLinkCapacity() - : last_raw_target_rate_; - TimeDelta rtt = TimeDelta::ms(last_estimated_rtt_ms_); NetworkControlUpdate update; update.target_rate = TargetTransferRate(); update.target_rate->network_estimate.at_time = at_time; - update.target_rate->network_estimate.bandwidth = bandwidth; update.target_rate->network_estimate.loss_rate_ratio = - last_estimated_fraction_loss_ / 255.0; - update.target_rate->network_estimate.round_trip_time = rtt; + last_estimated_fraction_loss_.value_or(0) / 255.0; + update.target_rate->network_estimate.round_trip_time = + last_estimated_round_trip_time_; update.target_rate->network_estimate.bwe_period = delay_based_bwe_->GetExpectedBwePeriod(); update.target_rate->at_time = at_time; - update.target_rate->target_rate = bandwidth; + update.target_rate->target_rate = last_pushback_target_rate_; + update.target_rate->stable_target_rate = + bandwidth_estimation_->GetEstimatedLinkCapacity(); update.pacer_config = GetPacingRates(at_time); update.congestion_window = current_data_window_; return update; @@ -598,11 +628,14 @@ NetworkControlUpdate GoogCcNetworkController::GetNetworkState( void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( NetworkControlUpdate* update, Timestamp at_time) { - int32_t estimated_bitrate_bps; - uint8_t fraction_loss; - int64_t rtt_ms; - bandwidth_estimation_->CurrentEstimate(&estimated_bitrate_bps, &fraction_loss, - &rtt_ms); + uint8_t fraction_loss = bandwidth_estimation_->fraction_loss(); + TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time(); + DataRate loss_based_target_rate = bandwidth_estimation_->target_rate(); + bool bwe_limited_due_to_packet_loss = + loss_based_target_rate.IsFinite() && + bandwidth_estimation_->delay_based_limit().IsFinite() && + loss_based_target_rate < bandwidth_estimation_->delay_based_limit(); + DataRate pushback_target_rate = loss_based_target_rate; // BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(), // (fraction_loss * 100) / 256); @@ -610,47 +643,61 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( // BWE_TEST_LOGGING_PLOT(1, "Target_bitrate_kbps", at_time.ms(), // estimated_bitrate_bps / 1000); - DataRate target_rate = DataRate::bps(estimated_bitrate_bps); + double cwnd_reduce_ratio = 0.0; if (congestion_window_pushback_controller_) { int64_t pushback_rate = congestion_window_pushback_controller_->UpdateTargetBitrate( - target_rate.bps()); + loss_based_target_rate.bps()); pushback_rate = std::max(bandwidth_estimation_->GetMinBitrate(), pushback_rate); - target_rate = DataRate::bps(pushback_rate); + pushback_target_rate = DataRate::bps(pushback_rate); + if (rate_control_settings_.UseCongestionWindowDropFrameOnly()) { + cwnd_reduce_ratio = static_cast(loss_based_target_rate.bps() - + pushback_target_rate.bps()) / + loss_based_target_rate.bps(); + } + } + DataRate stable_target_rate = + bandwidth_estimation_->GetEstimatedLinkCapacity(); + if (loss_based_stable_rate_) { + stable_target_rate = std::min(stable_target_rate, loss_based_target_rate); + } else { + stable_target_rate = std::min(stable_target_rate, pushback_target_rate); } - if ((estimated_bitrate_bps != last_estimated_bitrate_bps_) || + if ((loss_based_target_rate != last_loss_based_target_rate_) || (fraction_loss != last_estimated_fraction_loss_) || - (rtt_ms != last_estimated_rtt_ms_) || - (target_rate != last_pushback_target_rate_)) { - last_pushback_target_rate_ = target_rate; - last_estimated_bitrate_bps_ = estimated_bitrate_bps; + (round_trip_time != last_estimated_round_trip_time_) || + (pushback_target_rate != last_pushback_target_rate_) || + (stable_target_rate != last_stable_target_rate_)) { + last_loss_based_target_rate_ = loss_based_target_rate; + last_pushback_target_rate_ = pushback_target_rate; last_estimated_fraction_loss_ = fraction_loss; - last_estimated_rtt_ms_ = rtt_ms; - - alr_detector_->SetEstimatedBitrate(estimated_bitrate_bps); + last_estimated_round_trip_time_ = round_trip_time; + last_stable_target_rate_ = stable_target_rate; - last_raw_target_rate_ = DataRate::bps(estimated_bitrate_bps); - DataRate bandwidth = use_stable_bandwidth_estimate_ - ? bandwidth_estimation_->GetEstimatedLinkCapacity() - : last_raw_target_rate_; + alr_detector_->SetEstimatedBitrate(loss_based_target_rate.bps()); TimeDelta bwe_period = delay_based_bwe_->GetExpectedBwePeriod(); TargetTransferRate target_rate_msg; target_rate_msg.at_time = at_time; - target_rate_msg.target_rate = target_rate; + if (rate_control_settings_.UseCongestionWindowDropFrameOnly()) { + target_rate_msg.target_rate = loss_based_target_rate; + target_rate_msg.cwnd_reduce_ratio = cwnd_reduce_ratio; + } else { + target_rate_msg.target_rate = pushback_target_rate; + } + target_rate_msg.stable_target_rate = stable_target_rate; target_rate_msg.network_estimate.at_time = at_time; - target_rate_msg.network_estimate.round_trip_time = TimeDelta::ms(rtt_ms); - target_rate_msg.network_estimate.bandwidth = bandwidth; + target_rate_msg.network_estimate.round_trip_time = round_trip_time; target_rate_msg.network_estimate.loss_rate_ratio = fraction_loss / 255.0f; target_rate_msg.network_estimate.bwe_period = bwe_period; update->target_rate = target_rate_msg; auto probes = probe_controller_->SetEstimatedBitrate( - last_raw_target_rate_.bps(), at_time.ms()); + loss_based_target_rate, bwe_limited_due_to_packet_loss, at_time); update->probe_cluster_configs.insert(update->probe_cluster_configs.end(), probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); @@ -665,9 +712,20 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const { // Pacing rate is based on target rate before congestion window pushback, // because we don't want to build queues in the pacer when pushback occurs. - DataRate pacing_rate = - std::max(min_total_allocated_bitrate_, last_raw_target_rate_) * - pacing_factor_; + DataRate pacing_rate = DataRate::Zero(); + if ((pace_at_max_of_bwe_and_lower_link_capacity_ || + (pace_at_loss_based_bwe_when_loss_ && + last_loss_based_target_rate_ >= delay_based_bwe_->last_estimate())) && + estimate_) { + pacing_rate = + std::max({min_total_allocated_bitrate_, estimate_->link_capacity_lower, + last_loss_based_target_rate_}) * + pacing_factor_; + } else { + pacing_rate = + std::max(min_total_allocated_bitrate_, last_loss_based_target_rate_) * + pacing_factor_; + } DataRate padding_rate = std::min(max_padding_rate_, last_pushback_target_rate_); PacerConfig msg; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h index 200572a67b..4d32d09883 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -19,13 +19,12 @@ #include "api/units/data_rate.h" #include "api/units/data_size.h" #include "api/units/timestamp.h" -#include "modules/bitrate_controller/send_side_bandwidth_estimation.h" -#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.h" +#include "modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h" #include "modules/congestion_controller/goog_cc/alr_detector.h" #include "modules/congestion_controller/goog_cc/congestion_window_pushback_controller.h" #include "modules/congestion_controller/goog_cc/delay_based_bwe.h" #include "modules/congestion_controller/goog_cc/probe_controller.h" -#include "rtc_base/constructor_magic.h" +#include "modules/bitrate_controller/send_side_bandwidth_estimation.h" #include "rtc_base/experiments/field_trial_parser.h" #include "rtc_base/experiments/rate_control_settings.h" @@ -45,7 +44,12 @@ struct GoogCcConfig { class GoogCcNetworkController : public NetworkControllerInterface { public: GoogCcNetworkController(NetworkControllerConfig config, - GoogCcConfig congestion_controller_config); + GoogCcConfig goog_cc_config); + + GoogCcNetworkController() = delete; + GoogCcNetworkController(const GoogCcNetworkController&) = delete; + GoogCcNetworkController& operator=(const GoogCcNetworkController&) = delete; + ~GoogCcNetworkController() override; // NetworkControllerInterface @@ -55,6 +59,7 @@ class GoogCcNetworkController : public NetworkControllerInterface { NetworkControlUpdate OnRemoteBitrateReport(RemoteBitrateReport msg) override; NetworkControlUpdate OnRoundTripTimeUpdate(RoundTripTimeUpdate msg) override; NetworkControlUpdate OnSentPacket(SentPacket msg) override; + NetworkControlUpdate OnReceivedPacket(ReceivedPacket msg) override; NetworkControlUpdate OnStreamsConfig(StreamsConfig msg) override; NetworkControlUpdate OnTargetRateConstraints( TargetRateConstraints msg) override; @@ -73,7 +78,7 @@ class GoogCcNetworkController : public NetworkControllerInterface { void ClampConstraints(); void MaybeTriggerOnNetworkChanged(NetworkControlUpdate* update, Timestamp at_time); - void UpdateCongestionWindowSize(TimeDelta time_since_last_packet); + void UpdateCongestionWindowSize(); PacerConfig GetPacingRates(Timestamp at_time) const; const FieldTrialBasedConfig trial_based_config_; @@ -82,11 +87,13 @@ class GoogCcNetworkController : public NetworkControllerInterface { const bool packet_feedback_only_; FieldTrialFlag safe_reset_on_route_change_; FieldTrialFlag safe_reset_acknowledged_rate_; - const bool use_stable_bandwidth_estimate_; - const bool use_downlink_delay_for_congestion_window_; - const bool fall_back_to_probe_rate_; const bool use_min_allocatable_as_lower_bound_; + const bool ignore_probes_lower_than_network_estimate_; + const bool limit_probes_lower_than_throughput_estimate_; const RateControlSettings rate_control_settings_; + const bool loss_based_stable_rate_; + const bool pace_at_max_of_bwe_and_lower_link_capacity_; + const bool pace_at_loss_based_bwe_when_loss_; const std::unique_ptr probe_controller_; const std::unique_ptr @@ -98,10 +105,12 @@ class GoogCcNetworkController : public NetworkControllerInterface { std::unique_ptr network_estimator_; std::unique_ptr network_state_predictor_; std::unique_ptr delay_based_bwe_; - std::unique_ptr acknowledged_bitrate_estimator_; + std::unique_ptr + acknowledged_bitrate_estimator_; absl::optional initial_config_; + DataRate min_target_rate_ = DataRate::Zero(); DataRate min_data_rate_ = DataRate::Zero(); DataRate max_data_rate_ = DataRate::PlusInfinity(); absl::optional starting_rate_; @@ -116,12 +125,13 @@ class GoogCcNetworkController : public NetworkControllerInterface { std::deque feedback_max_rtts_; - DataRate last_raw_target_rate_; + DataRate last_loss_based_target_rate_; DataRate last_pushback_target_rate_; + DataRate last_stable_target_rate_; - int32_t last_estimated_bitrate_bps_ = 0; - uint8_t last_estimated_fraction_loss_ = 0; - int64_t last_estimated_rtt_ms_ = 0; + absl::optional last_estimated_fraction_loss_ = 0; + TimeDelta last_estimated_round_trip_time_ = TimeDelta::PlusInfinity(); + Timestamp last_packet_received_time_ = Timestamp::MinusInfinity(); double pacing_factor_; DataRate min_total_allocated_bitrate_; @@ -131,8 +141,6 @@ class GoogCcNetworkController : public NetworkControllerInterface { bool previously_in_alr_ = false; absl::optional current_data_window_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(GoogCcNetworkController); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc new file mode 100644 index 0000000000..75386bc704 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2020 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. + */ + +#define MS_CLASS "webrtc::InterArrivalDelta" + +#include "modules/congestion_controller/goog_cc/inter_arrival_delta.h" + +#include + +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "Logger.hpp" + +namespace webrtc { + +static constexpr TimeDelta kBurstDeltaThreshold = TimeDelta::Millis<5>(); +static constexpr TimeDelta kMaxBurstDuration = TimeDelta::Millis<100>(); +constexpr TimeDelta InterArrivalDelta::kArrivalTimeOffsetThreshold; + +InterArrivalDelta::InterArrivalDelta(TimeDelta send_time_group_length) + : send_time_group_length_(send_time_group_length), + current_timestamp_group_(), + prev_timestamp_group_(), + num_consecutive_reordered_packets_(0) {} + +bool InterArrivalDelta::ComputeDeltas(Timestamp send_time, + Timestamp arrival_time, + Timestamp system_time, + size_t packet_size, + TimeDelta* send_time_delta, + TimeDelta* arrival_time_delta, + int* packet_size_delta) { + bool calculated_deltas = false; + if (current_timestamp_group_.IsFirstPacket()) { + // We don't have enough data to update the filter, so we store it until we + // have two frames of data to process. + current_timestamp_group_.send_time = send_time; + current_timestamp_group_.first_send_time = send_time; + current_timestamp_group_.first_arrival = arrival_time; + } else if (current_timestamp_group_.first_send_time > send_time) { + // Reordered packet. + return false; + } else if (NewTimestampGroup(arrival_time, send_time)) { + // First packet of a later send burst, the previous packets sample is ready. + if (prev_timestamp_group_.complete_time.IsFinite()) { + *send_time_delta = + current_timestamp_group_.send_time - prev_timestamp_group_.send_time; + *arrival_time_delta = current_timestamp_group_.complete_time - + prev_timestamp_group_.complete_time; + + TimeDelta system_time_delta = current_timestamp_group_.last_system_time - + prev_timestamp_group_.last_system_time; + + if (*arrival_time_delta - system_time_delta >= + kArrivalTimeOffsetThreshold) { + MS_WARN_TAG(bwe, "The arrival time clock offset has changed (diff = %lld ms), resetting.", + arrival_time_delta->ms() - system_time_delta.ms()); + Reset(); + return false; + } + if (*arrival_time_delta < TimeDelta::Zero()) { + // The group of packets has been reordered since receiving its local + // arrival timestamp. + ++num_consecutive_reordered_packets_; + if (num_consecutive_reordered_packets_ >= kReorderedResetThreshold) { + MS_WARN_TAG(bwe, "Packets between send burst arrived out of order, resetting. arrival_time_delta %lld send time delta %lld", + arrival_time_delta->ms(), + send_time_delta->ms()); + Reset(); + } + return false; + } else { + num_consecutive_reordered_packets_ = 0; + } + *packet_size_delta = static_cast(current_timestamp_group_.size) - + static_cast(prev_timestamp_group_.size); + calculated_deltas = true; + } + prev_timestamp_group_ = current_timestamp_group_; + // The new timestamp is now the current frame. + current_timestamp_group_.first_send_time = send_time; + current_timestamp_group_.send_time = send_time; + current_timestamp_group_.first_arrival = arrival_time; + current_timestamp_group_.size = 0; + } else { + current_timestamp_group_.send_time = + std::max(current_timestamp_group_.send_time, send_time); + } + // Accumulate the frame size. + current_timestamp_group_.size += packet_size; + current_timestamp_group_.complete_time = arrival_time; + current_timestamp_group_.last_system_time = system_time; + + return calculated_deltas; +} + +// Assumes that `timestamp` is not reordered compared to +// `current_timestamp_group_`. +bool InterArrivalDelta::NewTimestampGroup(Timestamp arrival_time, + Timestamp send_time) const { + if (current_timestamp_group_.IsFirstPacket()) { + return false; + } else if (BelongsToBurst(arrival_time, send_time)) { + return false; + } else { + return send_time - current_timestamp_group_.first_send_time > + send_time_group_length_; + } +} + +bool InterArrivalDelta::BelongsToBurst(Timestamp arrival_time, + Timestamp send_time) const { + // RTC_DCHECK(current_timestamp_group_.complete_time.IsFinite()); + TimeDelta arrival_time_delta = + arrival_time - current_timestamp_group_.complete_time; + TimeDelta send_time_delta = send_time - current_timestamp_group_.send_time; + if (send_time_delta.IsZero()) + return true; + TimeDelta propagation_delta = arrival_time_delta - send_time_delta; + if (propagation_delta < TimeDelta::Zero() && + arrival_time_delta <= kBurstDeltaThreshold && + arrival_time - current_timestamp_group_.first_arrival < kMaxBurstDuration) + return true; + return false; +} + +void InterArrivalDelta::Reset() { + num_consecutive_reordered_packets_ = 0; + current_timestamp_group_ = SendTimeGroup(); + prev_timestamp_group_ = SendTimeGroup(); +} +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.h new file mode 100644 index 0000000000..e518578754 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2020 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. + */ + +#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_ +#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_ + +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" + +namespace webrtc { + +// Helper class to compute the inter-arrival time delta and the size delta +// between two send bursts. This code is branched from +// modules/remote_bitrate_estimator/inter_arrival. +class InterArrivalDelta { + public: + // After this many packet groups received out of order InterArrival will + // reset, assuming that clocks have made a jump. + static constexpr int kReorderedResetThreshold = 3; + static constexpr TimeDelta kArrivalTimeOffsetThreshold = + TimeDelta::Seconds<3>(); + + // A send time group is defined as all packets with a send time which are at + // most send_time_group_length older than the first timestamp in that + // group. + explicit InterArrivalDelta(TimeDelta send_time_group_length); + + InterArrivalDelta() = delete; + InterArrivalDelta(const InterArrivalDelta&) = delete; + InterArrivalDelta& operator=(const InterArrivalDelta&) = delete; + + // This function returns true if a delta was computed, or false if the current + // group is still incomplete or if only one group has been completed. + // `send_time` is the send time. + // `arrival_time` is the time at which the packet arrived. + // `packet_size` is the size of the packet. + // `timestamp_delta` (output) is the computed send time delta. + // `arrival_time_delta_ms` (output) is the computed arrival-time delta. + // `packet_size_delta` (output) is the computed size delta. + bool ComputeDeltas(Timestamp send_time, + Timestamp arrival_time, + Timestamp system_time, + size_t packet_size, + TimeDelta* send_time_delta, + TimeDelta* arrival_time_delta, + int* packet_size_delta); + + private: + struct SendTimeGroup { + SendTimeGroup() + : size(0), + first_send_time(Timestamp::MinusInfinity()), + send_time(Timestamp::MinusInfinity()), + first_arrival(Timestamp::MinusInfinity()), + complete_time(Timestamp::MinusInfinity()), + last_system_time(Timestamp::MinusInfinity()) {} + + bool IsFirstPacket() const { return complete_time.IsInfinite(); } + + size_t size; + Timestamp first_send_time; + Timestamp send_time; + Timestamp first_arrival; + Timestamp complete_time; + Timestamp last_system_time; + }; + + // Returns true if the last packet was the end of the current batch and the + // packet with `send_time` is the first of a new batch. + bool NewTimestampGroup(Timestamp arrival_time, Timestamp send_time) const; + + bool BelongsToBurst(Timestamp arrival_time, Timestamp send_time) const; + + void Reset(); + + const TimeDelta send_time_group_length_; + SendTimeGroup current_timestamp_group_; + SendTimeGroup prev_timestamp_group_; + int num_consecutive_reordered_packets_; +}; +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_INTER_ARRIVAL_DELTA_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index cc745e0c23..eed3d9343a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -27,40 +27,30 @@ namespace webrtc { namespace { -// The minimum number probing packets used. -constexpr int kMinProbePacketsSent = 5; - -// The minimum probing duration in ms. -constexpr int kMinProbeDurationMs = 15; - // Maximum waiting time from the time of initiating probing to getting // the measured results back. -constexpr int64_t kMaxWaitingTimeForProbingResultMs = 1000; - -// Value of |min_bitrate_to_probe_further_bps_| that indicates -// further probing is disabled. -constexpr int kExponentialProbingDisabled = 0; +constexpr TimeDelta kMaxWaitingTimeForProbingResult = TimeDelta::Seconds<1>(); // Default probing bitrate limit. Applied only when the application didn't // specify max bitrate. -constexpr int64_t kDefaultMaxProbingBitrateBps = 5000000; +constexpr DataRate kDefaultMaxProbingBitrate = DataRate::KilobitsPerSec<5000>(); // If the bitrate drops to a factor |kBitrateDropThreshold| or lower // and we recover within |kBitrateDropTimeoutMs|, then we'll send // a probe at a fraction |kProbeFractionAfterDrop| of the original bitrate. constexpr double kBitrateDropThreshold = 0.66; -constexpr int kBitrateDropTimeoutMs = 5000; +constexpr TimeDelta kBitrateDropTimeout = TimeDelta::Seconds<5>(); constexpr double kProbeFractionAfterDrop = 0.85; // Timeout for probing after leaving ALR. If the bitrate drops significantly, // (as determined by the delay based estimator) and we leave ALR, then we will -// send a probe if we recover within |kLeftAlrTimeoutMs| ms. -constexpr int kAlrEndedTimeoutMs = 3000; +// send a probe if we recover within `kLeftAlrTimeoutMs` ms. +constexpr TimeDelta kAlrEndedTimeout = TimeDelta::Seconds<3>(); // The expected uncertainty of probe result (as a fraction of the target probe // This is a limit on how often probing can be done when there is a BW // drop detected in ALR. -constexpr int64_t kMinTimeBetweenAlrProbesMs = 5000; +constexpr TimeDelta kMinTimeBetweenAlrProbes = TimeDelta::Seconds<5>(); // bitrate). Used to avoid probing if the probe bitrate is close to our current // estimate. @@ -70,13 +60,6 @@ constexpr double kProbeUncertainty = 0.05; constexpr char kBweRapidRecoveryExperiment[] = "WebRTC-BweRapidRecoveryExperiment"; -// Never probe higher than configured by OnMaxTotalAllocatedBitrate(). -constexpr char kCappedProbingFieldTrialName[] = "WebRTC-BweCappedProbing"; - -// Only do allocation probing when in ALR (but not when network-limited). -constexpr char kAllocProbingOnlyInAlrFieldTrialName[] = - "WebRTC-BweAllocProbingOnlyInAlr"; - void MaybeLogProbeClusterCreated(const ProbeClusterConfig& probe) { #if MS_LOG_DEV_LEVEL == 3 size_t min_bytes = static_cast(probe.target_data_rate.bps() * @@ -98,14 +81,37 @@ ProbeControllerConfig::ProbeControllerConfig( further_probe_threshold("further_probe_threshold", 0.7), alr_probing_interval("alr_interval", TimeDelta::seconds(5)), alr_probe_scale("alr_scale", 2), + network_state_estimate_probing_interval("network_state_interval", + TimeDelta::PlusInfinity()), + network_state_estimate_fast_rampup_rate("network_state_fast_rampup_rate", + 0), + network_state_estimate_drop_down_rate("network_state_drop_down_rate", 0), + network_state_probe_scale("network_state_scale", 1.0), + network_state_probe_duration("network_state_probe_duration", + TimeDelta::Millis<15>()), + first_allocation_probe_scale("alloc_p1", 1), second_allocation_probe_scale("alloc_p2", 2), - allocation_allow_further_probing("alloc_probe_further", false) { + allocation_allow_further_probing("alloc_probe_further", false), + allocation_probe_max("alloc_probe_max", DataRate::PlusInfinity()), + min_probe_packets_sent("min_probe_packets_sent", 5), + min_probe_duration("min_probe_duration", TimeDelta::Millis<15>()), + limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe", + false), + skip_if_estimate_larger_than_fraction_of_max( + "skip_if_est_larger_than_fraction_of_max", + 0.0) { ParseFieldTrial( {&first_exponential_probe_scale, &second_exponential_probe_scale, &further_exponential_probe_scale, &further_probe_threshold, &alr_probing_interval, &alr_probe_scale, &first_allocation_probe_scale, - &second_allocation_probe_scale, &allocation_allow_further_probing}, + &second_allocation_probe_scale, &allocation_allow_further_probing, + &min_probe_duration, &network_state_estimate_probing_interval, + &network_state_estimate_fast_rampup_rate, + &network_state_estimate_drop_down_rate, &network_state_probe_scale, + &network_state_probe_duration, &min_probe_packets_sent, + &limit_probe_target_rate_to_loss_bwe, + &skip_if_estimate_larger_than_fraction_of_max}, key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration @@ -118,8 +124,10 @@ ProbeControllerConfig::ProbeControllerConfig( key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); ParseFieldTrial( {&first_allocation_probe_scale, &second_allocation_probe_scale, - &allocation_allow_further_probing}, + &allocation_allow_further_probing, &allocation_probe_max}, key_value_config->Lookup("WebRTC-Bwe-AllocationProbing")); + ParseFieldTrial({&min_probe_packets_sent, &min_probe_duration}, + key_value_config->Lookup("WebRTC-Bwe-ProbingBehavior")); } ProbeControllerConfig::ProbeControllerConfig(const ProbeControllerConfig&) = @@ -129,46 +137,40 @@ ProbeControllerConfig::~ProbeControllerConfig() = default; ProbeController::ProbeController(const WebRtcKeyValueConfig* key_value_config) : enable_periodic_alr_probing_(false), in_rapid_recovery_experiment_( - key_value_config->Lookup(kBweRapidRecoveryExperiment) - .find("Enabled") == 0), - limit_probes_with_allocateable_rate_( - key_value_config->Lookup(kCappedProbingFieldTrialName) - .find("Disabled") != 0), - allocation_probing_only_in_alr_( - key_value_config->Lookup(kAllocProbingOnlyInAlrFieldTrialName) - .find("Enabled") == 0), + key_value_config->Lookup(kBweRapidRecoveryExperiment).find("Enabled") == 0 + ), + //event_log_(event_log), config_(ProbeControllerConfig(key_value_config)) { - Reset(0); + Reset(Timestamp::Zero()); } ProbeController::~ProbeController() {} std::vector ProbeController::SetBitrates( - int64_t min_bitrate_bps, - int64_t start_bitrate_bps, - int64_t max_bitrate_bps, - int64_t at_time_ms) { - if (start_bitrate_bps > 0) { - start_bitrate_bps_ = start_bitrate_bps; - estimated_bitrate_bps_ = start_bitrate_bps; - } else if (start_bitrate_bps_ == 0) { - start_bitrate_bps_ = min_bitrate_bps; + DataRate min_bitrate, + DataRate start_bitrate, + DataRate max_bitrate, + Timestamp at_time) { + if (start_bitrate > DataRate::Zero()) { + start_bitrate_ = start_bitrate; + estimated_bitrate_ = start_bitrate; + } else if (start_bitrate_.IsZero()) { + start_bitrate_ = min_bitrate; } - - MS_DEBUG_DEV( - "[old_max_bitrate_bps:%lld, max_bitrate_bps:%lld]", - max_bitrate_bps_, - max_bitrate_bps); - - // The reason we use the variable |old_max_bitrate_pbs| is because we - // need to set |max_bitrate_bps_| before we call InitiateProbing. - int64_t old_max_bitrate_bps = max_bitrate_bps_; - max_bitrate_bps_ = max_bitrate_bps; + MS_DEBUG_DEV( + "[old_max_bitrate_bps:%lld, max_bitrate_bps:%lld]", + max_bitrate_bps_, + max_bitrate_bps); + // The reason we use the variable `old_max_bitrate_pbs` is because we + // need to set `max_bitrate_` before we call InitiateProbing. + DataRate old_max_bitrate = max_bitrate_; + max_bitrate_ = + max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate; switch (state_) { case State::kInit: if (network_available_) - return InitiateExponentialProbing(at_time_ms); + return InitiateExponentialProbing(at_time); break; case State::kWaitingForProbingResult: @@ -177,21 +179,20 @@ std::vector ProbeController::SetBitrates( case State::kProbingComplete: // If the new max bitrate is higher than both the old max bitrate and the // estimate then initiate probing. - if (estimated_bitrate_bps_ != 0 && - old_max_bitrate_bps < max_bitrate_bps_ && - estimated_bitrate_bps_ < max_bitrate_bps_) { + if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ && + estimated_bitrate_ < max_bitrate_) { // The assumption is that if we jump more than 20% in the bandwidth // estimate or if the bandwidth estimate is within 90% of the new // max bitrate then the probing attempt was successful. mid_call_probing_succcess_threshold_ = - std::min(estimated_bitrate_bps_ * 1.2, max_bitrate_bps_ * 0.9); + std::min(estimated_bitrate_ * 1.2, max_bitrate_ * 0.9); mid_call_probing_waiting_for_result_ = true; - mid_call_probing_bitrate_bps_ = max_bitrate_bps_; + mid_call_probing_bitrate_ = max_bitrate_; // RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated", // max_bitrate_bps_ / 1000); - return InitiateProbing(at_time_ms, {max_bitrate_bps_}, false); + return InitiateProbing(at_time, {max_bitrate_}, false); } break; } @@ -199,34 +200,36 @@ std::vector ProbeController::SetBitrates( } std::vector ProbeController::OnMaxTotalAllocatedBitrate( - int64_t max_total_allocated_bitrate, - int64_t at_time_ms) { - MS_DEBUG_DEV("[max_total_allocated_bitrate:%" PRIi64 "]", max_total_allocated_bitrate); - - const bool in_alr = alr_start_time_ms_.has_value(); - const bool allow_allocation_probe = - allocation_probing_only_in_alr_ ? in_alr : true; + DataRate max_total_allocated_bitrate, + Timestamp at_time) { + const bool in_alr = alr_start_time_.has_value(); + const bool allow_allocation_probe = in_alr; if (state_ == State::kProbingComplete && max_total_allocated_bitrate != max_total_allocated_bitrate_ && - estimated_bitrate_bps_ != 0 && - (max_bitrate_bps_ <= 0 || estimated_bitrate_bps_ < max_bitrate_bps_) && - estimated_bitrate_bps_ < max_total_allocated_bitrate && + estimated_bitrate_ < max_bitrate_ && + estimated_bitrate_ < max_total_allocated_bitrate && allow_allocation_probe) { max_total_allocated_bitrate_ = max_total_allocated_bitrate; if (!config_.first_allocation_probe_scale) return std::vector(); - std::vector probes = { - static_cast(config_.first_allocation_probe_scale.Value() * - max_total_allocated_bitrate)}; + DataRate first_probe_rate = max_total_allocated_bitrate * + config_.first_allocation_probe_scale.Value(); + DataRate probe_cap = config_.allocation_probe_max.Get(); + first_probe_rate = std::min(first_probe_rate, probe_cap); + std::vector probes = {first_probe_rate}; if (config_.second_allocation_probe_scale) { - probes.push_back(config_.second_allocation_probe_scale.Value() * - max_total_allocated_bitrate); + DataRate second_probe_rate = + max_total_allocated_bitrate * + config_.second_allocation_probe_scale.Value(); + second_probe_rate = std::min(second_probe_rate, probe_cap); + if (second_probe_rate > first_probe_rate) + probes.push_back(second_probe_rate); } - return InitiateProbing(at_time_ms, probes, - config_.allocation_allow_further_probing); + return InitiateProbing(at_time, probes, + config_.allocation_allow_further_probing.Get()); } max_total_allocated_bitrate_ = max_total_allocated_bitrate; return std::vector(); @@ -238,39 +241,52 @@ std::vector ProbeController::OnNetworkAvailability( if (!network_available_ && state_ == State::kWaitingForProbingResult) { state_ = State::kProbingComplete; - min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; + min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); } - if (network_available_ && state_ == State::kInit && start_bitrate_bps_ > 0) - return InitiateExponentialProbing(msg.at_time.ms()); + if (network_available_ && state_ == State::kInit && !start_bitrate_.IsZero()) + return InitiateExponentialProbing(msg.at_time); return std::vector(); } std::vector ProbeController::InitiateExponentialProbing( - int64_t at_time_ms) { + Timestamp at_time) { //RTC_DCHECK(network_available_); //RTC_DCHECK(state_ == State::kInit); //RTC_DCHECK_GT(start_bitrate_bps_, 0); MS_ASSERT(network_available_, "network not available"); MS_ASSERT(state_ == State::kInit, "state_ must be State::kInit"); - MS_ASSERT(start_bitrate_bps_ > 0, "start_bitrate_bps_ must be > 0"); + MS_ASSERT(start_bitrate_ > DataRate::Zero(), "start_bitrate_bps_ must be > 0"); // When probing at 1.8 Mbps ( 6x 300), this represents a threshold of // 1.2 Mbps to continue probing. - std::vector probes = {static_cast( - config_.first_exponential_probe_scale * start_bitrate_bps_)}; - if (config_.second_exponential_probe_scale) { + std::vector probes = {config_.first_exponential_probe_scale * + start_bitrate_}; + if (config_.second_exponential_probe_scale && + config_.second_exponential_probe_scale.GetOptional().value() > 0) { probes.push_back(config_.second_exponential_probe_scale.Value() * - start_bitrate_bps_); + start_bitrate_); } - return InitiateProbing(at_time_ms, probes, true); + return InitiateProbing(at_time, probes, true); } std::vector ProbeController::SetEstimatedBitrate( - int64_t bitrate_bps, - int64_t at_time_ms) { + DataRate bitrate, + bool bwe_limited_due_to_packet_loss, + Timestamp at_time) { + if (bwe_limited_due_to_packet_loss != bwe_limited_due_to_packet_loss_ && + config_.limit_probe_target_rate_to_loss_bwe) { + state_ = State::kProbingComplete; + } + bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss; + if (bitrate < kBitrateDropThreshold * estimated_bitrate_) { + time_of_last_large_drop_ = at_time; + bitrate_before_last_large_drop_ = estimated_bitrate_; + } + estimated_bitrate_ = bitrate; + if (mid_call_probing_waiting_for_result_ && - bitrate_bps >= mid_call_probing_succcess_threshold_) { + bitrate >= mid_call_probing_succcess_threshold_) { // RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Success", // mid_call_probing_bitrate_bps_ / 1000); // RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.ProbedKbps", @@ -285,22 +301,12 @@ std::vector ProbeController::SetEstimatedBitrate( // "[measured bitrate:%" PRIi64 ", minimum to probe further:%" PRIi64 "]", // bitrate_bps, min_bitrate_to_probe_further_bps_); - if (min_bitrate_to_probe_further_bps_ != kExponentialProbingDisabled && - bitrate_bps > min_bitrate_to_probe_further_bps_) { + if (bitrate > min_bitrate_to_probe_further_) { pending_probes = InitiateProbing( - at_time_ms, - {static_cast(config_.further_exponential_probe_scale * - bitrate_bps)}, - true); + at_time, {config_.further_exponential_probe_scale * bitrate}, true); } } - if (bitrate_bps < kBitrateDropThreshold * estimated_bitrate_bps_) { - time_of_last_large_drop_ms_ = at_time_ms; - bitrate_before_last_large_drop_bps_ = estimated_bitrate_bps_; - } - - estimated_bitrate_bps_ = bitrate_bps; return pending_probes; } @@ -310,153 +316,224 @@ void ProbeController::EnablePeriodicAlrProbing(bool enable) { void ProbeController::SetAlrStartTimeMs( absl::optional alr_start_time_ms) { - alr_start_time_ms_ = alr_start_time_ms; + if (alr_start_time_ms) { + alr_start_time_ = Timestamp::ms(*alr_start_time_ms); + } else { + alr_start_time_ = absl::nullopt; + } } void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) { - alr_end_time_ms_.emplace(alr_end_time_ms); + alr_end_time_.emplace(Timestamp::ms(alr_end_time_ms)); } std::vector ProbeController::RequestProbe( - int64_t at_time_ms) { + Timestamp at_time) { // Called once we have returned to normal state after a large drop in // estimated bandwidth. The current response is to initiate a single probe // session (if not already probing) at the previous bitrate. // // If the probe session fails, the assumption is that this drop was a // real one from a competing flow or a network change. - bool in_alr = alr_start_time_ms_.has_value(); + bool in_alr = alr_start_time_.has_value(); bool alr_ended_recently = - (alr_end_time_ms_.has_value() && - at_time_ms - alr_end_time_ms_.value() < kAlrEndedTimeoutMs); + (alr_end_time_.has_value() && + at_time - alr_end_time_.value() < kAlrEndedTimeout); if (in_alr || alr_ended_recently || in_rapid_recovery_experiment_) { if (state_ == State::kProbingComplete) { - uint32_t suggested_probe_bps = - kProbeFractionAfterDrop * bitrate_before_last_large_drop_bps_; - uint32_t min_expected_probe_result_bps = - (1 - kProbeUncertainty) * suggested_probe_bps; - int64_t time_since_drop_ms = at_time_ms - time_of_last_large_drop_ms_; - int64_t time_since_probe_ms = at_time_ms - last_bwe_drop_probing_time_ms_; - if (min_expected_probe_result_bps > estimated_bitrate_bps_ && - time_since_drop_ms < kBitrateDropTimeoutMs && - time_since_probe_ms > kMinTimeBetweenAlrProbesMs) { - MS_WARN_TAG(bwe, "detected big bandwidth drop, start probing"); + DataRate suggested_probe = + kProbeFractionAfterDrop * bitrate_before_last_large_drop_; + DataRate min_expected_probe_result = + (1 - kProbeUncertainty) * suggested_probe; + TimeDelta time_since_drop = at_time - time_of_last_large_drop_; + TimeDelta time_since_probe = at_time - last_bwe_drop_probing_time_; + if (min_expected_probe_result > estimated_bitrate_ && + time_since_drop < kBitrateDropTimeout && + time_since_probe > kMinTimeBetweenAlrProbes) { + MS_WARN_TAG(bwe, "detected big bandwidth drop, start probing"); // Track how often we probe in response to bandwidth drop in ALR. // RTC_HISTOGRAM_COUNTS_10000( // "WebRTC.BWE.BweDropProbingIntervalInS", // (at_time_ms - last_bwe_drop_probing_time_ms_) / 1000); - last_bwe_drop_probing_time_ms_ = at_time_ms; - return InitiateProbing(at_time_ms, {suggested_probe_bps}, false); + last_bwe_drop_probing_time_ = at_time; + return InitiateProbing(at_time, {suggested_probe}, false); } } } return std::vector(); } -void ProbeController::SetMaxBitrate(int64_t max_bitrate_bps) { - MS_DEBUG_DEV("[max_bitrate_bps:%" PRIi64 "]", max_bitrate_bps); +void ProbeController::SetMaxBitrate(DataRate max_bitrate) { + MS_DEBUG_DEV("[max_bitrate_bps:%" PRIi64 "]", max_bitrate); - max_bitrate_bps_ = max_bitrate_bps; + max_bitrate_ = max_bitrate; } -void ProbeController::Reset(int64_t at_time_ms) { - MS_DEBUG_DEV("resetted"); +void ProbeController::SetNetworkStateEstimate( + webrtc::NetworkStateEstimate estimate) { + if (config_.network_state_estimate_fast_rampup_rate > 0 && + estimated_bitrate_ < estimate.link_capacity_upper && + (!network_estimate_ || + estimate.link_capacity_upper >= + config_.network_state_estimate_fast_rampup_rate * + network_estimate_->link_capacity_upper)) { + send_probe_on_next_process_interval_ = true; + } + if (config_.network_state_estimate_drop_down_rate > 0 && network_estimate_ && + !estimate.link_capacity_upper.IsZero() && + (estimated_bitrate_ > estimate.link_capacity_upper || + bwe_limited_due_to_packet_loss_) && + estimate.link_capacity_upper <= + config_.network_state_estimate_drop_down_rate * + network_estimate_->link_capacity_upper) { + send_probe_on_next_process_interval_ = true; + } + network_estimate_ = estimate; +} + +void ProbeController::Reset(Timestamp at_time) { network_available_ = true; + bwe_limited_due_to_packet_loss_ = false; state_ = State::kInit; - min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; - time_last_probing_initiated_ms_ = 0; - estimated_bitrate_bps_ = 0; - start_bitrate_bps_ = 0; - max_bitrate_bps_ = 0; - int64_t now_ms = at_time_ms; - last_bwe_drop_probing_time_ms_ = now_ms; - alr_end_time_ms_.reset(); + min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); + time_last_probing_initiated_ = Timestamp::Zero(); + estimated_bitrate_ = DataRate::Zero(); + network_estimate_ = absl::nullopt; + start_bitrate_ = DataRate::Zero(); + max_bitrate_ = kDefaultMaxProbingBitrate; + Timestamp now = at_time; + last_bwe_drop_probing_time_ = now; + alr_end_time_.reset(); mid_call_probing_waiting_for_result_ = false; - time_of_last_large_drop_ms_ = now_ms; - bitrate_before_last_large_drop_bps_ = 0; - max_total_allocated_bitrate_ = 0; + time_of_last_large_drop_ = now; + bitrate_before_last_large_drop_ = DataRate::Zero(); + max_total_allocated_bitrate_ = DataRate::Zero(); + send_probe_on_next_process_interval_ = false; +} + +bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { + if (enable_periodic_alr_probing_ && alr_start_time_) { + Timestamp next_probe_time = + std::max(*alr_start_time_, time_last_probing_initiated_) + + config_.alr_probing_interval; + return at_time >= next_probe_time; + } + return false; +} + +bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const { + if (config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ && network_estimate_->link_capacity_upper.IsFinite() && + estimated_bitrate_ < network_estimate_->link_capacity_upper) { + Timestamp next_probe_time = time_last_probing_initiated_ + + config_.network_state_estimate_probing_interval; + return at_time >= next_probe_time; + } + return false; } -std::vector ProbeController::Process(int64_t at_time_ms) { - if (at_time_ms - time_last_probing_initiated_ms_ > - kMaxWaitingTimeForProbingResultMs) { +std::vector ProbeController::Process(Timestamp at_time) { + if (at_time - time_last_probing_initiated_ > + kMaxWaitingTimeForProbingResult) { mid_call_probing_waiting_for_result_ = false; if (state_ == State::kWaitingForProbingResult) { MS_WARN_TAG(bwe, "kWaitingForProbingResult: timeout"); state_ = State::kProbingComplete; - min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; + min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); } } - - if (enable_periodic_alr_probing_ && state_ == State::kProbingComplete) { - // Probe bandwidth periodically when in ALR state. - if (alr_start_time_ms_ && estimated_bitrate_bps_ > 0) { - int64_t next_probe_time_ms = - std::max(*alr_start_time_ms_, time_last_probing_initiated_ms_) + - config_.alr_probing_interval->ms(); - if (at_time_ms >= next_probe_time_ms) { - return InitiateProbing(at_time_ms, - {static_cast(estimated_bitrate_bps_ * - config_.alr_probe_scale)}, - true); - } - } + if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) { + return {}; + } + if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) || + TimeForNetworkStateProbe(at_time)) { + return InitiateProbing( + at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true); } return std::vector(); } std::vector ProbeController::InitiateProbing( - int64_t now_ms, - std::vector bitrates_to_probe, + Timestamp now, + std::vector bitrates_to_probe, bool probe_further) { - int64_t max_probe_bitrate_bps = - max_bitrate_bps_ > 0 ? max_bitrate_bps_ : kDefaultMaxProbingBitrateBps; + if (config_.skip_if_estimate_larger_than_fraction_of_max > 0) { + DataRate network_estimate = network_estimate_ + ? network_estimate_->link_capacity_upper + : DataRate::PlusInfinity(); + if (std::min(network_estimate, estimated_bitrate_) > + config_.skip_if_estimate_larger_than_fraction_of_max * max_bitrate_) { + return {}; + } + } - MS_DEBUG_DEV( - "[max_bitrate_bps_:%lld, max_probe_bitrate_bps:%" PRIi64 "]", - max_bitrate_bps_, - max_probe_bitrate_bps); + MS_DEBUG_DEV( + "[max_bitrate_bps_:%lld, max_probe_bitrate_bps:%" PRIi64 "]", + max_bitrate_bps_, + max_probe_bitrate_bps); - if (limit_probes_with_allocateable_rate_ && - max_total_allocated_bitrate_ > 0) { + DataRate max_probe_bitrate = max_bitrate_; + if (bwe_limited_due_to_packet_loss_ && + config_.limit_probe_target_rate_to_loss_bwe) { + max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_); + } + if (config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { + if (network_estimate_->link_capacity_upper.IsZero()) { + MS_DEBUG_TAG(bwe, "Not sending probe, Network state estimate is zero"); + return {}; + } + max_probe_bitrate = + std::min(max_probe_bitrate, network_estimate_->link_capacity_upper * + config_.network_state_probe_scale); + } + if (max_total_allocated_bitrate_ > DataRate::Zero()) { // If a max allocated bitrate has been configured, allow probing up to 2x // that rate. This allows some overhead to account for bursty streams, // which otherwise would have to ramp up when the overshoot is already in // progress. // It also avoids minor quality reduction caused by probes often being // received at slightly less than the target probe bitrate. - max_probe_bitrate_bps = - std::min(max_probe_bitrate_bps, max_total_allocated_bitrate_ * 2); + max_probe_bitrate = + std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2); } + send_probe_on_next_process_interval_ = false; + std::vector pending_probes; - for (int64_t bitrate : bitrates_to_probe) { - //RTC_DCHECK_GT(bitrate, 0); + for (DataRate bitrate : bitrates_to_probe) { + // RTC_DCHECK(!bitrate.IsZero()); - if (bitrate > max_probe_bitrate_bps) { - bitrate = max_probe_bitrate_bps; + if (bitrate > max_probe_bitrate) { + bitrate = max_probe_bitrate; probe_further = false; } ProbeClusterConfig config; - config.at_time = Timestamp::ms(now_ms); - config.target_data_rate = DataRate::bps(rtc::dchecked_cast(bitrate)); - config.target_duration = TimeDelta::ms(kMinProbeDurationMs); - config.target_probe_count = kMinProbePacketsSent; + config.at_time = now; + config.target_data_rate = bitrate; + if (network_estimate_ && + config_.network_state_estimate_probing_interval->IsFinite()) { + config.target_duration = config_.network_state_probe_duration; + } else { + config.target_duration = config_.min_probe_duration; + } + + config.target_probe_count = config_.min_probe_packets_sent; config.id = next_probe_cluster_id_; next_probe_cluster_id_++; MaybeLogProbeClusterCreated(config); pending_probes.push_back(config); } - time_last_probing_initiated_ms_ = now_ms; + time_last_probing_initiated_ = now; if (probe_further) { state_ = State::kWaitingForProbingResult; - min_bitrate_to_probe_further_bps_ = + min_bitrate_to_probe_further_ = (*(bitrates_to_probe.end() - 1)) * config_.further_probe_threshold; } else { state_ = State::kProbingComplete; - min_bitrate_to_probe_further_bps_ = kExponentialProbingDisabled; + min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); } return pending_probes; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h index c928927a42..1fda7813bf 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h @@ -31,7 +31,7 @@ struct ProbeControllerConfig { ~ProbeControllerConfig(); // These parameters configure the initial probes. First we send one or two - // probes of sizes p1 * start_bitrate_bps_ and p2 * start_bitrate_bps_. + // probes of sizes p1 * start_bitrate_ and p2 * start_bitrate_. // Then whenever we get a bitrate estimate of at least further_probe_threshold // times the size of the last sent probe we'll send another one of size // step_size times the new estimate. @@ -44,10 +44,35 @@ struct ProbeControllerConfig { FieldTrialParameter alr_probing_interval; FieldTrialParameter alr_probe_scale; + // Configures how often we send probes if NetworkStateEstimate is available. + FieldTrialParameter network_state_estimate_probing_interval; + // If the network state estimate increase more than this rate, a probe is sent + // the next process interval. + FieldTrialParameter network_state_estimate_fast_rampup_rate; + // If the network state estimate decreases more than this rate, a probe is + // sent the next process interval. + FieldTrialParameter network_state_estimate_drop_down_rate; + FieldTrialParameter network_state_probe_scale; + // Overrides min_probe_duration if network_state_estimate_probing_interval + // is set and a network state estimate is known. + FieldTrialParameter network_state_probe_duration; + // Configures the probes emitted by changed to the allocated bitrate. FieldTrialOptional first_allocation_probe_scale; FieldTrialOptional second_allocation_probe_scale; FieldTrialFlag allocation_allow_further_probing; + FieldTrialParameter allocation_probe_max; + + // The minimum number probing packets used. + FieldTrialParameter min_probe_packets_sent; + // The minimum probing duration. + FieldTrialParameter min_probe_duration; + // Max limit the target rate of a probe to current estimate if BWE is loss + // limited. + FieldTrialParameter limit_probe_target_rate_to_loss_bwe; + // Dont send a probe if min(estimate, network state estimate) is larger than + // this fraction of the set max bitrate. + FieldTrialParameter skip_if_estimate_larger_than_fraction_of_max; }; // This class controls initiation of probing to estimate initial channel @@ -58,42 +83,47 @@ class ProbeController { explicit ProbeController(const WebRtcKeyValueConfig* key_value_config); ~ProbeController(); - RTC_WARN_UNUSED_RESULT std::vector SetBitrates( - int64_t min_bitrate_bps, - int64_t start_bitrate_bps, - int64_t max_bitrate_bps, - int64_t at_time_ms); + ProbeController(const ProbeController&) = delete; + ProbeController& operator=(const ProbeController&) = delete; + + ABSL_MUST_USE_RESULT std::vector SetBitrates( + DataRate min_bitrate, + DataRate start_bitrate, + DataRate max_bitrate, + Timestamp at_time); // The total bitrate, as opposed to the max bitrate, is the sum of the // configured bitrates for all active streams. - RTC_WARN_UNUSED_RESULT std::vector - OnMaxTotalAllocatedBitrate(int64_t max_total_allocated_bitrate, - int64_t at_time_ms); + ABSL_MUST_USE_RESULT std::vector + OnMaxTotalAllocatedBitrate(DataRate max_total_allocated_bitrate, + Timestamp at_time); - RTC_WARN_UNUSED_RESULT std::vector OnNetworkAvailability( + ABSL_MUST_USE_RESULT std::vector OnNetworkAvailability( NetworkAvailability msg); - RTC_WARN_UNUSED_RESULT std::vector SetEstimatedBitrate( - int64_t bitrate_bps, - int64_t at_time_ms); + ABSL_MUST_USE_RESULT std::vector SetEstimatedBitrate( + DataRate bitrate, + bool bwe_limited_due_to_packet_loss, + Timestamp at_time); void EnablePeriodicAlrProbing(bool enable); void SetAlrStartTimeMs(absl::optional alr_start_time); void SetAlrEndedTimeMs(int64_t alr_end_time); - RTC_WARN_UNUSED_RESULT std::vector RequestProbe( - int64_t at_time_ms); + ABSL_MUST_USE_RESULT std::vector RequestProbe( + Timestamp at_time); // Sets a new maximum probing bitrate, without generating a new probe cluster. - void SetMaxBitrate(int64_t max_bitrate_bps); + void SetMaxBitrate(DataRate max_bitrate); + void SetNetworkStateEstimate(webrtc::NetworkStateEstimate estimate); // Resets the ProbeController to a state equivalent to as if it was just - // created EXCEPT for |enable_periodic_alr_probing_|. - void Reset(int64_t at_time_ms); + // created EXCEPT for `enable_periodic_alr_probing_`. + void Reset(Timestamp at_time); - RTC_WARN_UNUSED_RESULT std::vector Process( - int64_t at_time_ms); + ABSL_MUST_USE_RESULT std::vector Process( + Timestamp at_time); private: enum class State { @@ -105,41 +135,43 @@ class ProbeController { kProbingComplete, }; - RTC_WARN_UNUSED_RESULT std::vector - InitiateExponentialProbing(int64_t at_time_ms); - RTC_WARN_UNUSED_RESULT std::vector InitiateProbing( - int64_t now_ms, - std::vector bitrates_to_probe, + ABSL_MUST_USE_RESULT std::vector + InitiateExponentialProbing(Timestamp at_time); + ABSL_MUST_USE_RESULT std::vector InitiateProbing( + Timestamp now, + std::vector bitrates_to_probe, bool probe_further); + bool TimeForAlrProbe(Timestamp at_time) const; + bool TimeForNetworkStateProbe(Timestamp at_time) const; bool network_available_; + bool bwe_limited_due_to_packet_loss_; State state_; - int64_t min_bitrate_to_probe_further_bps_; - int64_t time_last_probing_initiated_ms_; - int64_t estimated_bitrate_bps_; - int64_t start_bitrate_bps_; - int64_t max_bitrate_bps_; - int64_t last_bwe_drop_probing_time_ms_; - absl::optional alr_start_time_ms_; - absl::optional alr_end_time_ms_; + DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); + Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity(); + DataRate estimated_bitrate_ = DataRate::Zero(); + bool send_probe_on_next_process_interval_; + absl::optional network_estimate_; + DataRate start_bitrate_ = DataRate::Zero(); + DataRate max_bitrate_ = DataRate::PlusInfinity(); + Timestamp last_bwe_drop_probing_time_ = Timestamp::Zero(); + absl::optional alr_start_time_; + absl::optional alr_end_time_; bool enable_periodic_alr_probing_; - int64_t time_of_last_large_drop_ms_; - int64_t bitrate_before_last_large_drop_bps_; - int64_t max_total_allocated_bitrate_; + Timestamp time_of_last_large_drop_ = Timestamp::MinusInfinity(); + DataRate bitrate_before_last_large_drop_ = DataRate::Zero(); + DataRate max_total_allocated_bitrate_ = DataRate::Zero(); const bool in_rapid_recovery_experiment_; - const bool limit_probes_with_allocateable_rate_; - const bool allocation_probing_only_in_alr_; // For WebRTC.BWE.MidCallProbing.* metric. bool mid_call_probing_waiting_for_result_; - int64_t mid_call_probing_bitrate_bps_; - int64_t mid_call_probing_succcess_threshold_; + DataRate mid_call_probing_bitrate_ = DataRate::Zero(); + DataRate mid_call_probing_succcess_threshold_ = DataRate::Zero(); + // RtcEventLog* event_log_; int32_t next_probe_cluster_id_ = 1; ProbeControllerConfig config_; - - RTC_DISALLOW_COPY_AND_ASSIGN(ProbeController); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.cc new file mode 100644 index 0000000000..5bdcf1bac6 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.cc @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2019 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 "modules/congestion_controller/goog_cc/robust_throughput_estimator.h" + +#include + +#include +#include + +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +// #include "rtc_base/checks.h" + +namespace webrtc { + +RobustThroughputEstimator::RobustThroughputEstimator( + const RobustThroughputEstimatorSettings& settings) + : settings_(settings), + latest_discarded_send_time_(Timestamp::MinusInfinity()) { + // RTC_DCHECK(settings.enabled); +} + +RobustThroughputEstimator::~RobustThroughputEstimator() {} + +bool RobustThroughputEstimator::FirstPacketOutsideWindow() { + if (window_.empty()) + return false; + if (window_.size() > settings_.max_window_packets) + return true; + TimeDelta current_window_duration = + window_.back().receive_time - window_.front().receive_time; + if (current_window_duration > settings_.max_window_duration) + return true; + if (window_.size() > settings_.window_packets && + current_window_duration > settings_.min_window_duration) { + return true; + } + return false; +} + +void RobustThroughputEstimator::IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector) { + // RTC_DCHECK(std::is_sorted(packet_feedback_vector.begin(), + // packet_feedback_vector.end(), + // PacketResult::ReceiveTimeOrder())); + for (const auto& packet : packet_feedback_vector) { + // Ignore packets without valid send or receive times. + // (This should not happen in production since lost packets are filtered + // out before passing the feedback vector to the throughput estimator. + // However, explicitly handling this case makes the estimator more robust + // and avoids a hard-to-detect bad state.) + if (packet.receive_time.IsInfinite() || + packet.sent_packet.send_time.IsInfinite()) { + continue; + } + + // Insert the new packet. + window_.push_back(packet); + window_.back().sent_packet.prior_unacked_data = + window_.back().sent_packet.prior_unacked_data * + settings_.unacked_weight; + // In most cases, receive timestamps should already be in order, but in the + // rare case where feedback packets have been reordered, we do some swaps to + // ensure that the window is sorted. + for (size_t i = window_.size() - 1; + i > 0 && window_[i].receive_time < window_[i - 1].receive_time; i--) { + std::swap(window_[i], window_[i - 1]); + } + } + + // Remove old packets. + while (FirstPacketOutsideWindow()) { + latest_discarded_send_time_ = std::max( + latest_discarded_send_time_, window_.front().sent_packet.send_time); + window_.pop_front(); + } +} + +absl::optional RobustThroughputEstimator::bitrate() const { + if (window_.empty() || window_.size() < settings_.required_packets) + return absl::nullopt; + + TimeDelta largest_recv_gap(TimeDelta::Zero()); + TimeDelta second_largest_recv_gap(TimeDelta::Zero()); + for (size_t i = 1; i < window_.size(); i++) { + // Find receive time gaps. + TimeDelta gap = window_[i].receive_time - window_[i - 1].receive_time; + if (gap > largest_recv_gap) { + second_largest_recv_gap = largest_recv_gap; + largest_recv_gap = gap; + } else if (gap > second_largest_recv_gap) { + second_largest_recv_gap = gap; + } + } + + Timestamp first_send_time = Timestamp::PlusInfinity(); + Timestamp last_send_time = Timestamp::MinusInfinity(); + Timestamp first_recv_time = Timestamp::PlusInfinity(); + Timestamp last_recv_time = Timestamp::MinusInfinity(); + DataSize recv_size = DataSize::Bytes<0>(); + DataSize send_size = DataSize::Bytes<0>(); + DataSize first_recv_size = DataSize::Bytes<0>(); + DataSize last_send_size = DataSize::Bytes<0>(); + size_t num_sent_packets_in_window = 0; + for (const auto& packet : window_) { + if (packet.receive_time < first_recv_time) { + first_recv_time = packet.receive_time; + first_recv_size = + packet.sent_packet.size + packet.sent_packet.prior_unacked_data; + } + last_recv_time = std::max(last_recv_time, packet.receive_time); + recv_size += packet.sent_packet.size; + recv_size += packet.sent_packet.prior_unacked_data; + + if (packet.sent_packet.send_time < latest_discarded_send_time_) { + // If we have dropped packets from the window that were sent after + // this packet, then this packet was reordered. Ignore it from + // the send rate computation (since the send time may be very far + // in the past, leading to underestimation of the send rate.) + // However, ignoring packets creates a risk that we end up without + // any packets left to compute a send rate. + continue; + } + if (packet.sent_packet.send_time > last_send_time) { + last_send_time = packet.sent_packet.send_time; + last_send_size = + packet.sent_packet.size + packet.sent_packet.prior_unacked_data; + } + first_send_time = std::min(first_send_time, packet.sent_packet.send_time); + + send_size += packet.sent_packet.size; + send_size += packet.sent_packet.prior_unacked_data; + ++num_sent_packets_in_window; + } + + // Suppose a packet of size S is sent every T milliseconds. + // A window of N packets would contain N*S bytes, but the time difference + // between the first and the last packet would only be (N-1)*T. Thus, we + // need to remove the size of one packet to get the correct rate of S/T. + // Which packet to remove (if the packets have varying sizes), + // depends on the network model. + // Suppose that 2 packets with sizes s1 and s2, are received at times t1 + // and t2, respectively. If the packets were transmitted back to back over + // a bottleneck with rate capacity r, then we'd expect t2 = t1 + r * s2. + // Thus, r = (t2-t1) / s2, so the size of the first packet doesn't affect + // the difference between t1 and t2. + // Analoguously, if the first packet is sent at time t1 and the sender + // paces the packets at rate r, then the second packet can be sent at time + // t2 = t1 + r * s1. Thus, the send rate estimate r = (t2-t1) / s1 doesn't + // depend on the size of the last packet. + recv_size -= first_recv_size; + send_size -= last_send_size; + + // Remove the largest gap by replacing it by the second largest gap. + // This is to ensure that spurious "delay spikes" (i.e. when the + // network stops transmitting packets for a short period, followed + // by a burst of delayed packets), don't cause the estimate to drop. + // This could cause an overestimation, which we guard against by + // never returning an estimate above the send rate. + // RTC_DCHECK(first_recv_time.IsFinite()); + // RTC_DCHECK(last_recv_time.IsFinite()); + TimeDelta recv_duration = (last_recv_time - first_recv_time) - + largest_recv_gap + second_largest_recv_gap; + recv_duration = std::max(recv_duration, TimeDelta::Millis<1>()); + + if (num_sent_packets_in_window < settings_.required_packets) { + // Too few send times to calculate a reliable send rate. + return recv_size / recv_duration; + } + + // RTC_DCHECK(first_send_time.IsFinite()); + // RTC_DCHECK(last_send_time.IsFinite()); + TimeDelta send_duration = last_send_time - first_send_time; + send_duration = std::max(send_duration, TimeDelta::Millis<1>()); + + return std::min(send_size / send_duration, recv_size / recv_duration); +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.h new file mode 100644 index 0000000000..9d89856496 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2019 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. + */ + +#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_ROBUST_THROUGHPUT_ESTIMATOR_H_ +#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_ROBUST_THROUGHPUT_ESTIMATOR_H_ + +#include +#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/acknowledged_bitrate_estimator_interface.h" + +namespace webrtc { + +class RobustThroughputEstimator : public AcknowledgedBitrateEstimatorInterface { + public: + explicit RobustThroughputEstimator( + const RobustThroughputEstimatorSettings& settings); + ~RobustThroughputEstimator() override; + + void IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector) override; + + absl::optional bitrate() const override; + + absl::optional PeekRate() const override { return bitrate(); } + void SetAlr(bool /*in_alr*/) override {} + void SetAlrEndedTime(Timestamp /*alr_ended_time*/) override {} + + private: + bool FirstPacketOutsideWindow(); + + const RobustThroughputEstimatorSettings settings_; + std::deque window_; + Timestamp latest_discarded_send_time_ = Timestamp::MinusInfinity(); +}; + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_ROBUST_THROUGHPUT_ESTIMATOR_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 885c6776cb..ac95090d75 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -28,14 +28,12 @@ namespace webrtc { namespace { // Parameters for linear least squares fit of regression line to noisy data. -constexpr size_t kDefaultTrendlineWindowSize = 20; -constexpr double kDefaultTrendlineSmoothingCoeff = 0.6; +constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; -size_t ReadTrendlineFilterWindowSize( - const WebRtcKeyValueConfig* key_value_config) { +size_t ReadTrendlineFilterWindowSize(const WebRtcKeyValueConfig* key_value_config) { std::string experiment_string = key_value_config->Lookup(kBweWindowSizeInPacketsExperiment); size_t window_size; @@ -49,60 +47,119 @@ size_t ReadTrendlineFilterWindowSize( MS_WARN_DEV( "failed to parse parameters for BweWindowSizeInPackets" " experiment from field trial string, using default"); - return kDefaultTrendlineWindowSize; + return TrendlineEstimatorSettings::kDefaultTrendlineWindowSize; } absl::optional LinearFitSlope( - const std::deque>& points) { - //RTC_DCHECK(points.size() >= 2); + const std::deque& packets) { + // RTC_DCHECK(packets.size() >= 2); // Compute the "center of mass". double sum_x = 0; double sum_y = 0; - for (const auto& point : points) { - sum_x += point.first; - sum_y += point.second; + for (const auto& packet : packets) { + sum_x += packet.arrival_time_ms; + sum_y += packet.smoothed_delay_ms; } - double x_avg = sum_x / points.size(); - double y_avg = sum_y / points.size(); + double x_avg = sum_x / packets.size(); + double y_avg = sum_y / packets.size(); // Compute the slope k = \sum (x_i-x_avg)(y_i-y_avg) / \sum (x_i-x_avg)^2 double numerator = 0; double denominator = 0; - for (const auto& point : points) { - numerator += (point.first - x_avg) * (point.second - y_avg); - denominator += (point.first - x_avg) * (point.first - x_avg); + for (const auto& packet : packets) { + double x = packet.arrival_time_ms; + double y = packet.smoothed_delay_ms; + numerator += (x - x_avg) * (y - y_avg); + denominator += (x - x_avg) * (x - x_avg); } if (denominator == 0) return absl::nullopt; return numerator / denominator; } +absl::optional ComputeSlopeCap( + const std::deque& packets, + const TrendlineEstimatorSettings& settings) { + // RTC_DCHECK(1 <= settings.beginning_packets && + // settings.beginning_packets < packets.size()); + // RTC_DCHECK(1 <= settings.end_packets && + // settings.end_packets < packets.size()); + // RTC_DCHECK(settings.beginning_packets + settings.end_packets <= + // packets.size()); + TrendlineEstimator::PacketTiming early = packets[0]; + for (size_t i = 1; i < settings.beginning_packets; ++i) { + if (packets[i].raw_delay_ms < early.raw_delay_ms) + early = packets[i]; + } + size_t late_start = packets.size() - settings.end_packets; + TrendlineEstimator::PacketTiming late = packets[late_start]; + for (size_t i = late_start + 1; i < packets.size(); ++i) { + if (packets[i].raw_delay_ms < late.raw_delay_ms) + late = packets[i]; + } + if (late.arrival_time_ms - early.arrival_time_ms < 1) { + return absl::nullopt; + } + return (late.raw_delay_ms - early.raw_delay_ms) / + (late.arrival_time_ms - early.arrival_time_ms) + + settings.cap_uncertainty; +} + constexpr double kMaxAdaptOffsetMs = 15.0; -constexpr double kOverUsingTimeThreshold = 30; +constexpr double kOverUsingTimeThreshold = 10; constexpr int kMinNumDeltas = 60; constexpr int kDeltaCounterMax = 1000; } // namespace -TrendlineEstimator::TrendlineEstimator( - const WebRtcKeyValueConfig* key_value_config, - NetworkStatePredictor* network_state_predictor) - : TrendlineEstimator( - key_value_config->Lookup(kBweWindowSizeInPacketsExperiment) - .find("Enabled") == 0 - ? ReadTrendlineFilterWindowSize(key_value_config) - : kDefaultTrendlineWindowSize, - kDefaultTrendlineSmoothingCoeff, - kDefaultTrendlineThresholdGain, - network_state_predictor) {} +constexpr char TrendlineEstimatorSettings::kKey[]; + +TrendlineEstimatorSettings::TrendlineEstimatorSettings( + const WebRtcKeyValueConfig* key_value_config) { + if (key_value_config->Lookup(kBweWindowSizeInPacketsExperiment).find("Enabled") == 0) { + window_size = ReadTrendlineFilterWindowSize(key_value_config); + } + Parser()->Parse(key_value_config->Lookup(TrendlineEstimatorSettings::kKey)); + if (window_size < 10 || 200 < window_size) { + MS_WARN_TAG(bwe, "Window size must be between 10 and 200 packets"); + window_size = kDefaultTrendlineWindowSize; + } + if (enable_cap) { + if (beginning_packets < 1 || end_packets < 1 || + beginning_packets > window_size || end_packets > window_size) { + MS_WARN_TAG(bwe, "Size of beginning and end must be between 1 and %d", window_size); + enable_cap = false; + beginning_packets = end_packets = 0; + cap_uncertainty = 0.0; + } + if (beginning_packets + end_packets > window_size) { + MS_WARN_TAG(bwe, "Size of beginning plus end can't exceed the window size"); + enable_cap = false; + beginning_packets = end_packets = 0; + cap_uncertainty = 0.0; + } + if (cap_uncertainty < 0.0 || 0.025 < cap_uncertainty) { + MS_WARN_TAG(bwe, "Cap uncertainty must be between 0 and 0.025"); + cap_uncertainty = 0.0; + } + } +} + +std::unique_ptr TrendlineEstimatorSettings::Parser() { + return StructParametersParser::Create("sort", &enable_sort, // + "cap", &enable_cap, // + "beginning_packets", + &beginning_packets, // + "end_packets", &end_packets, // + "cap_uncertainty", &cap_uncertainty, // + "window_size", &window_size); +} TrendlineEstimator::TrendlineEstimator( - size_t window_size, - double smoothing_coef, - double threshold_gain, + const WebRtcKeyValueConfig* key_value_config, NetworkStatePredictor* network_state_predictor) - : window_size_(window_size), - smoothing_coef_(smoothing_coef), - threshold_gain_(threshold_gain), + : settings_(key_value_config), + smoothing_coef_(kDefaultTrendlineSmoothingCoeff), + threshold_gain_(kDefaultTrendlineThresholdGain), num_of_deltas_(0), first_arrival_time_ms_(-1), accumulated_delay_(0), @@ -127,56 +184,74 @@ TrendlineEstimator::TrendlineEstimator( TrendlineEstimator::~TrendlineEstimator() {} +void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, + double send_delta_ms, + int64_t send_time_ms, + int64_t arrival_time_ms, + size_t packet_size) { + const double delta_ms = recv_delta_ms - send_delta_ms; + ++num_of_deltas_; + num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax); + if (first_arrival_time_ms_ == -1) + first_arrival_time_ms_ = arrival_time_ms; + + // Exponential backoff filter. + accumulated_delay_ += delta_ms; + // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, + // accumulated_delay_); + smoothed_delay_ = smoothing_coef_ * smoothed_delay_ + + (1 - smoothing_coef_) * accumulated_delay_; + // BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms, + // smoothed_delay_); + + // Maintain packet window + delay_hist_.emplace_back( + static_cast(arrival_time_ms - first_arrival_time_ms_), + smoothed_delay_, accumulated_delay_); + if (settings_.enable_sort) { + for (size_t i = delay_hist_.size() - 1; + i > 0 && + delay_hist_[i].arrival_time_ms < delay_hist_[i - 1].arrival_time_ms; + --i) { + std::swap(delay_hist_[i], delay_hist_[i - 1]); + } + } + if (delay_hist_.size() > settings_.window_size) + delay_hist_.pop_front(); + + // Simple linear regression. + double trend = prev_trend_; + if (delay_hist_.size() == settings_.window_size) { + // Update trend_ if it is possible to fit a line to the data. The delay + // trend can be seen as an estimate of (send_rate - capacity)/capacity. + // 0 < trend < 1 -> the delay increases, queues are filling up + // trend == 0 -> the delay does not change + // trend < 0 -> the delay decreases, queues are being emptied + trend = LinearFitSlope(delay_hist_).value_or(trend); + if (settings_.enable_cap) { + absl::optional cap = ComputeSlopeCap(delay_hist_, settings_); + // We only use the cap to filter out overuse detections, not + // to detect additional underuses. + if (trend >= 0 && cap.has_value() && trend > cap.value()) { + trend = cap.value(); + } + } + } + // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend); + + Detect(trend, send_delta_ms, arrival_time_ms); +} + void TrendlineEstimator::Update(double recv_delta_ms, double send_delta_ms, int64_t send_time_ms, int64_t arrival_time_ms, + size_t packet_size, bool calculated_deltas) { if (calculated_deltas) { - const double delta_ms = recv_delta_ms - send_delta_ms; - ++num_of_deltas_; - num_of_deltas_ = std::min(num_of_deltas_, kDeltaCounterMax); - if (first_arrival_time_ms_ == -1) - first_arrival_time_ms_ = arrival_time_ms; - - // Exponential backoff filter. - accumulated_delay_ += delta_ms; - // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, - // accumulated_delay_); - // smoothed_delay_ = smoothing_coef_ * smoothed_delay_ + - // (1 - smoothing_coef_) * accumulated_delay_; - // MS_NOTE: Apply WEMA to the current delta_ms. Don't consider the - // accumulated delay. Tests show it behaves more robustly upon delta peaks. - smoothed_delay_ = smoothing_coef_ * delta_ms + - (1 - smoothing_coef_) * smoothed_delay_; - // BWE_TEST_LOGGING_PLOT(1, "smoothed_delay_ms", arrival_time_ms, - // smoothed_delay_); - - // Simple linear regression. - delay_hist_.push_back(std::make_pair( - static_cast(arrival_time_ms - first_arrival_time_ms_), - smoothed_delay_)); - if (delay_hist_.size() > window_size_) - delay_hist_.pop_front(); - double trend = prev_trend_; - if (delay_hist_.size() == window_size_) { - // Update trend_ if it is possible to fit a line to the data. The delay - // trend can be seen as an estimate of (send_rate - capacity)/capacity. - // 0 < trend < 1 -> the delay increases, queues are filling up - // trend == 0 -> the delay does not change - // trend < 0 -> the delay decreases, queues are being emptied - trend = LinearFitSlope(delay_hist_).value_or(trend); - } - - // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend); - - MS_DEBUG_DEV("trend:%f, send_delta_ms:%f, recv_delta_ms:%f, delta_ms:%f arrival_time_ms:%" PRIi64 ", accumulated_delay_:%f, smoothed_delay_:%f", trend, send_delta_ms, recv_delta_ms, delta_ms, arrival_time_ms, accumulated_delay_, smoothed_delay_); - Detect(trend, send_delta_ms, arrival_time_ms); + UpdateTrendline(recv_delta_ms, send_delta_ms, send_time_ms, arrival_time_ms, + packet_size); } - else { - MS_DEBUG_DEV("no calculated deltas"); - } - if (network_state_predictor_) { hypothesis_predicted_ = network_state_predictor_->Update( send_time_ms, arrival_time_ms, hypothesis_); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index f4c23d706d..6ae5b263bd 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -15,6 +15,7 @@ #include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/constructor_magic.h" +#include "rtc_base/experiments/struct_parameters_parser.h" #include #include @@ -23,6 +24,30 @@ namespace webrtc { +struct TrendlineEstimatorSettings { + static constexpr char kKey[] = "WebRTC-Bwe-TrendlineEstimatorSettings"; + static constexpr unsigned kDefaultTrendlineWindowSize = 20; + + TrendlineEstimatorSettings() = delete; + explicit TrendlineEstimatorSettings(const WebRtcKeyValueConfig* key_value_config); + + // Sort the packets in the window. Should be redundant, + // but then almost no cost. + bool enable_sort = false; + + // Cap the trendline slope based on the minimum delay seen + // in the beginning_packets and end_packets respectively. + bool enable_cap = false; + unsigned beginning_packets = 7; + unsigned end_packets = 7; + double cap_uncertainty = 0.0; + + // Size (in packets) of the window. + unsigned window_size = kDefaultTrendlineWindowSize; + + std::unique_ptr Parser(); +}; + class TrendlineEstimator : public DelayIncreaseDetectorInterface { public: TrendlineEstimator(const WebRtcKeyValueConfig* key_value_config, @@ -41,29 +66,46 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { ~TrendlineEstimator() override; + TrendlineEstimator(const TrendlineEstimator&) = delete; + TrendlineEstimator& operator=(const TrendlineEstimator&) = delete; + // Update the estimator with a new sample. The deltas should represent deltas // between timestamp groups as defined by the InterArrival class. void Update(double recv_delta_ms, double send_delta_ms, int64_t send_time_ms, int64_t arrival_time_ms, + size_t packet_size, bool calculated_deltas) override; + void UpdateTrendline(double recv_delta_ms, + double send_delta_ms, + int64_t send_time_ms, + int64_t arrival_time_ms, + size_t packet_size); + BandwidthUsage State() const override; - protected: - // Used in unit tests. - double modified_trend() const { return prev_trend_ * threshold_gain_; } + struct PacketTiming { + PacketTiming(double arrival_time_ms, + double smoothed_delay_ms, + double raw_delay_ms) + : arrival_time_ms(arrival_time_ms), + smoothed_delay_ms(smoothed_delay_ms), + raw_delay_ms(raw_delay_ms) {} + double arrival_time_ms; + double smoothed_delay_ms; + double raw_delay_ms; + }; private: friend class GoogCcStatePrinter; - void Detect(double trend, double ts_delta, int64_t now_ms); void UpdateThreshold(double modified_offset, int64_t now_ms); // Parameters. - const size_t window_size_; + TrendlineEstimatorSettings settings_; const double smoothing_coef_; const double threshold_gain_; // Used by the existing threshold. @@ -74,7 +116,7 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double accumulated_delay_; double smoothed_delay_; // Linear least squares regression. - std::deque> delay_hist_; + std::deque delay_hist_; const double k_up_; const double k_down_; @@ -88,8 +130,6 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { BandwidthUsage hypothesis_; BandwidthUsage hypothesis_predicted_; NetworkStatePredictor* network_state_predictor_; - - RTC_DISALLOW_COPY_AND_ASSIGN(TrendlineEstimator); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h index 11469b6a43..f3213e4904 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h @@ -29,6 +29,8 @@ DataRate GetMinBitrate(); static const int64_t kBitrateWindowMs = 1000; +constexpr DataRate kCongestionControllerMinBitrate = DataRate::BitsPerSec<5000>(); + extern const char kBweTypeHistogram[]; enum BweNames { diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.cc new file mode 100644 index 0000000000..101e428f7e --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.cc @@ -0,0 +1,59 @@ +/* + * Copyright 2019 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 "rtc_base/experiments/field_trial_list.h" + +//#include "absl/strings/string_view.h" + +namespace webrtc { + +FieldTrialListBase::FieldTrialListBase(std::string key) + : FieldTrialParameterInterface(key), + failed_(false), + parse_got_called_(false) {} + +bool FieldTrialListBase::Failed() const { + return failed_; +} +bool FieldTrialListBase::Used() const { + return parse_got_called_; +} + +int FieldTrialListWrapper::Length() { + return GetList()->Size(); +} +bool FieldTrialListWrapper::Failed() { + return GetList()->Failed(); +} +bool FieldTrialListWrapper::Used() { + return GetList()->Used(); +} + +bool FieldTrialStructListBase::Parse(absl::optional str_value) { + // RTC_DCHECK_NOTREACHED(); + return true; +} + +int FieldTrialStructListBase::ValidateAndGetLength() { + int length = -1; + for (std::unique_ptr& list : sub_lists_) { + if (list->Failed()) + return -1; + else if (!list->Used()) + continue; + else if (length == -1) + length = list->Length(); + else if (length != list->Length()) + return -1; + } + + return length; +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.h new file mode 100644 index 0000000000..b302104c64 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_list.h @@ -0,0 +1,237 @@ +/* + * Copyright 2018 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. + */ +#ifndef RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_ +#define RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_ + +#include +#include +#include +#include + +#include "absl/strings/string_view.h" +#include "rtc_base/experiments/field_trial_parser.h" + +// List support for field trial strings. FieldTrialList and FieldTrialStructList +// are used similarly to the other FieldTrialParameters, but take a variable +// number of parameters. A FieldTrialList parses a |-delimeted string into a +// list of T, using ParseTypedParameter to parse the individual tokens. +// Example string: "my_list:1|2|3,empty_list,other_list:aardvark". + +// A FieldTrialStructList combines multiple lists into a list-of-structs. It +// ensures that all its sublists parse correctly and have the same length, then +// uses user-supplied accessor functions to write those elements into structs of +// a user-supplied type. + +// See the unit test for usage and behavior. + +namespace webrtc { + +class FieldTrialListBase : public FieldTrialParameterInterface { + protected: + friend class FieldTrialListWrapper; + explicit FieldTrialListBase(std::string key); + + bool Failed() const; + bool Used() const; + + virtual int Size() = 0; + + bool failed_; + bool parse_got_called_; +}; + +// This class represents a vector of type T. The elements are separated by a | +// and parsed using ParseTypedParameter. +template +class FieldTrialList : public FieldTrialListBase { + public: + explicit FieldTrialList(std::string key) : FieldTrialList(key, {}) {} + FieldTrialList(std::string key, std::initializer_list default_values) + : FieldTrialListBase(key), values_(default_values) {} + + std::vector Get() const { return values_; } + operator std::vector() const { return Get(); } + typename std::vector::const_reference operator[](size_t index) const { + return values_[index]; + } + const std::vector* operator->() const { return &values_; } + std::vector split(std::string source, char delimiter) { + std::vector fields; + size_t last = 0; + for (size_t i = 0; i < source.length(); ++i) { + if (source[i] == delimiter) { + fields.push_back(source.substr(last, i - last)); + last = i + 1; + } + } + fields.push_back(source.substr(last)); + return fields; + } + + protected: + bool Parse(absl::optional str_value) override { + parse_got_called_ = true; + + if (!str_value) { + values_.clear(); + return true; + } + + std::vector new_values_; + + for (const std::string& token : split(str_value.value(), '|')) { + absl::optional value = ParseTypedParameter(token); + if (value) { + new_values_.push_back(*value); + } else { + failed_ = true; + return false; + } + } + + values_.swap(new_values_); + return true; + } + + int Size() override { return values_.size(); } + + private: + std::vector values_; +}; + +class FieldTrialListWrapper { + public: + virtual ~FieldTrialListWrapper() = default; + + // Takes the element at the given index in the wrapped list and writes it to + // the given struct. + virtual void WriteElement(void* struct_to_write, int index) = 0; + + virtual FieldTrialListBase* GetList() = 0; + + int Length(); + + // Returns true iff the wrapped list has failed to parse at least one token. + bool Failed(); + + bool Used(); + + protected: + FieldTrialListWrapper() = default; +}; + +namespace field_trial_list_impl { +// The LambdaTypeTraits struct provides type information about lambdas in the +// template expressions below. +template +struct LambdaTypeTraits : public LambdaTypeTraits {}; + +template +struct LambdaTypeTraits { + using ret = RetType; + using src = SourceType; +}; + +template +struct TypedFieldTrialListWrapper : FieldTrialListWrapper { + public: + TypedFieldTrialListWrapper(absl::string_view key, + std::function sink) + : list_(key), sink_(sink) {} + + void WriteElement(void* struct_to_write, int index) override { + sink_(struct_to_write, list_[index]); + } + + FieldTrialListBase* GetList() override { return &list_; } + + private: + FieldTrialList list_; + std::function sink_; +}; + +} // namespace field_trial_list_impl + +template > +FieldTrialListWrapper* FieldTrialStructMember(std::string key, + F accessor) { + return new field_trial_list_impl::TypedFieldTrialListWrapper< + typename Traits::ret>(key, [accessor](void* s, typename Traits::ret t) { + *accessor(static_cast(s)) = t; + }); +} + +// This base class is here to reduce the amount of code we have to generate for +// each type of FieldTrialStructList. +class FieldTrialStructListBase : public FieldTrialParameterInterface { + protected: + FieldTrialStructListBase( + std::initializer_list sub_lists) + : FieldTrialParameterInterface(""), sub_lists_() { + // Take ownership of the list wrappers generated by FieldTrialStructMember + // on the call site. + for (FieldTrialListWrapper* const* it = sub_lists.begin(); + it != sub_lists.end(); it++) { + sub_parameters_.push_back((*it)->GetList()); + sub_lists_.push_back(std::unique_ptr(*it)); + } + } + + // Check that all of our sublists that were in the field trial string had the + // same number of elements. If they do, we return that length. If they had + // different lengths, any sublist had parse failures or no sublists had + // user-supplied values, we return -1. + int ValidateAndGetLength(); + + bool Parse(absl::optional str_value) override; + + std::vector> sub_lists_; +}; + +template +class FieldTrialStructList : public FieldTrialStructListBase { + public: + FieldTrialStructList(std::initializer_list l, + std::initializer_list default_list) + : FieldTrialStructListBase(l), values_(default_list) {} + + std::vector Get() const { return values_; } + operator std::vector() const { return Get(); } + const S& operator[](size_t index) const { return values_[index]; } + const std::vector* operator->() const { return &values_; } + + protected: + void ParseDone() override { + int length = ValidateAndGetLength(); + + if (length == -1) + return; + + std::vector new_values(length, S()); + + for (std::unique_ptr& li : sub_lists_) { + if (li->Used()) { + for (int i = 0; i < length; i++) { + li->WriteElement(&new_values[i], i); + } + } + } + + values_.swap(new_values); + } + + private: + std::vector values_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_FIELD_TRIAL_LIST_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.cc index 9cfc67286b..b53715f5f0 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.cc +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.cc @@ -118,21 +118,55 @@ absl::optional ParseTypedParameter(std::string str) { template <> absl::optional ParseTypedParameter(std::string str) { - int value; - if (sscanf(str.c_str(), "%i", &value) == 1) { - return value; - } else { - return absl::nullopt; + int64_t value; + if (sscanf(std::string(str).c_str(), "%" SCNd64, &value) == 1) { + //if (rtc::IsValueInRangeForNumericType(value)) { + return static_cast(value); + //} } + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter(std::string str) { + int64_t value; + if (sscanf(std::string(str).c_str(), "%" SCNd64, &value) == 1) { + //if (rtc::IsValueInRangeForNumericType(value)) { + return static_cast(value); + //} + } + return absl::nullopt; } template <> -absl::optional ParseTypedParameter(std::string str) { - return std::move(str); +absl::optional ParseTypedParameter( + std::string str) { + return std::string(str); } FieldTrialFlag::FieldTrialFlag(std::string key) : FieldTrialFlag(key, false) {} +template <> +absl::optional> ParseTypedParameter>( + std::string str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> ParseTypedParameter>( + std::string str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(std::string str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(std::string str) { + return ParseOptionalParameter(str); +} + FieldTrialFlag::FieldTrialFlag(std::string key, bool default_value) : FieldTrialParameterInterface(key), value_(default_value) {} @@ -191,13 +225,16 @@ bool AbstractFieldTrialEnum::Parse(absl::optional str_value) { template class FieldTrialParameter; template class FieldTrialParameter; template class FieldTrialParameter; +template class FieldTrialParameter; template class FieldTrialParameter; template class FieldTrialConstrained; template class FieldTrialConstrained; +template class FieldTrialConstrained; template class FieldTrialOptional; template class FieldTrialOptional; +template class FieldTrialOptional; template class FieldTrialOptional; template class FieldTrialOptional; diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.h index 685468f2ac..6401ea08cc 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.h +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_parser.h @@ -226,20 +226,60 @@ class FieldTrialFlag : public FieldTrialParameterInterface { bool value_; }; +template +absl::optional> ParseOptionalParameter( + std::string str) { + if (str.empty()) + return absl::optional(); + auto parsed = ParseTypedParameter(str); + if (parsed.has_value()) + return parsed; + return absl::nullopt; +} + +template <> +absl::optional ParseTypedParameter(std::string str); +template <> +absl::optional ParseTypedParameter(std::string str); +template <> +absl::optional ParseTypedParameter(std::string str); +template <> +absl::optional ParseTypedParameter(std::string str); +template <> +absl::optional ParseTypedParameter( + std::string str); + +template <> +absl::optional> ParseTypedParameter>( + std::string str); +template <> +absl::optional> ParseTypedParameter>( + std::string str); +template <> +absl::optional> +ParseTypedParameter>(std::string str); +template <> +absl::optional> +ParseTypedParameter>(std::string str); + // Accepts true, false, else parsed with sscanf %i, true if != 0. extern template class FieldTrialParameter; // Interpreted using sscanf %lf. extern template class FieldTrialParameter; // Interpreted using sscanf %i. extern template class FieldTrialParameter; +// Interpreted using sscanf %u. +extern template class FieldTrialParameter; // Using the given value as is. extern template class FieldTrialParameter; extern template class FieldTrialConstrained; extern template class FieldTrialConstrained; +extern template class FieldTrialConstrained; extern template class FieldTrialOptional; extern template class FieldTrialOptional; +extern template class FieldTrialOptional; extern template class FieldTrialOptional; extern template class FieldTrialOptional; diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_units.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_units.cc index 7fb514df7d..4d32ef3244 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_units.cc +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/field_trial_units.cc @@ -82,6 +82,22 @@ absl::optional ParseTypedParameter(std::string str) { return absl::nullopt; } +template <> +absl::optional> +ParseTypedParameter>(std::string str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(std::string str) { + return ParseOptionalParameter(str); +} +template <> +absl::optional> +ParseTypedParameter>(std::string str) { + return ParseOptionalParameter(str); +} + template class FieldTrialParameter; template class FieldTrialParameter; template class FieldTrialParameter; diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.cc index 0b5e61ecb3..f486f20741 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.cc +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.cc @@ -11,6 +11,7 @@ #include "rtc_base/experiments/rate_control_settings.h" #include "api/transport/field_trial_based_config.h" #include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/experiments/struct_parameters_parser.h" #include "rtc_base/numerics/safe_conversions.h" #include @@ -21,27 +22,69 @@ namespace webrtc { namespace { -const int kDefaultAcceptedQueueMs = 250; +const int kDefaultAcceptedQueueMs = 350; const int kDefaultMinPushbackTargetBitrateBps = 30000; +const char kCongestionWindowDefaultFieldTrialString[] = + "QueueSize:350,MinBitrate:30000,DropFrame:true"; + +const char kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName[] = + "WebRTC-UseBaseHeavyVP8TL3RateAllocation"; + +bool IsEnabled(const WebRtcKeyValueConfig* const key_value_config, + absl::string_view key) { + return key_value_config->Lookup(key).find("Enabled") == 0; +} + } // namespace +constexpr char CongestionWindowConfig::kKey[]; + +std::unique_ptr CongestionWindowConfig::Parser() { + return StructParametersParser::Create("QueueSize", &queue_size_ms, // + "MinBitrate", &min_bitrate_bps, + "InitWin", &initial_data_window, + "DropFrame", &drop_frame_only); +} + +// static +CongestionWindowConfig CongestionWindowConfig::Parse(absl::string_view config) { + CongestionWindowConfig res; + res.Parser()->Parse(config); + return res; +} + +constexpr char VideoRateControlConfig::kKey[]; + +std::unique_ptr VideoRateControlConfig::Parser() { + // The empty comments ensures that each pair is on a separate line. + return StructParametersParser::Create( + "pacing_factor", &pacing_factor, // + "alr_probing", &alr_probing, // + "vp8_qp_max", &vp8_qp_max, // + "vp8_min_pixels", &vp8_min_pixels, // + "trust_vp8", &trust_vp8, // + "trust_vp9", &trust_vp9, // + "probe_max_allocation", &probe_max_allocation, // + "bitrate_adjuster", &bitrate_adjuster, // + "adjuster_use_headroom", &adjuster_use_headroom, // + "vp8_s0_boost", &vp8_s0_boost, // + "vp8_base_heavy_tl3_alloc", &vp8_base_heavy_tl3_alloc); +} + RateControlSettings::RateControlSettings( - const WebRtcKeyValueConfig* const key_value_config) - : congestion_window_("QueueSize"), - congestion_window_pushback_("MinBitrate"), - pacing_factor_("pacing_factor"), - alr_probing_("alr_probing", false), - probe_max_allocation_("probe_max_allocation", true), - bitrate_adjuster_("bitrate_adjuster", false), - adjuster_use_headroom_("adjuster_use_headroom", false) { - ParseFieldTrial({&congestion_window_, &congestion_window_pushback_}, - key_value_config->Lookup("WebRTC-CongestionWindow")); - ParseFieldTrial( - {&pacing_factor_, &alr_probing_, - &probe_max_allocation_, &bitrate_adjuster_, &adjuster_use_headroom_}, - key_value_config->Lookup("WebRTC-VideoRateControl")); + const WebRtcKeyValueConfig* const key_value_config) { + std::string congestion_window_config = + key_value_config->Lookup(CongestionWindowConfig::kKey).empty() + ? kCongestionWindowDefaultFieldTrialString + : key_value_config->Lookup(CongestionWindowConfig::kKey); + congestion_window_config_ = + CongestionWindowConfig::Parse(congestion_window_config); + video_config_.vp8_base_heavy_tl3_alloc = IsEnabled( + key_value_config, kUseBaseHeavyVp8Tl3RateAllocationFieldTrialName); + video_config_.Parser()->Parse( + key_value_config->Lookup(VideoRateControlConfig::kKey)); } RateControlSettings::~RateControlSettings() = default; @@ -60,41 +103,84 @@ RateControlSettings RateControlSettings::ParseFromKeyValueConfig( } bool RateControlSettings::UseCongestionWindow() const { - return static_cast(congestion_window_); + return static_cast(congestion_window_config_.queue_size_ms); } int64_t RateControlSettings::GetCongestionWindowAdditionalTimeMs() const { - return congestion_window_.GetOptional().value_or(kDefaultAcceptedQueueMs); + return congestion_window_config_.queue_size_ms.value_or( + kDefaultAcceptedQueueMs); } bool RateControlSettings::UseCongestionWindowPushback() const { - return congestion_window_ && congestion_window_pushback_; + return congestion_window_config_.queue_size_ms && + congestion_window_config_.min_bitrate_bps; +} + +bool RateControlSettings::UseCongestionWindowDropFrameOnly() const { + return congestion_window_config_.drop_frame_only; } uint32_t RateControlSettings::CongestionWindowMinPushbackTargetBitrateBps() const { - return congestion_window_pushback_.GetOptional().value_or( + return congestion_window_config_.min_bitrate_bps.value_or( kDefaultMinPushbackTargetBitrateBps); } +absl::optional +RateControlSettings::CongestionWindowInitialDataWindow() const { + return congestion_window_config_.initial_data_window; +} + absl::optional RateControlSettings::GetPacingFactor() const { - return pacing_factor_.GetOptional(); + return video_config_.pacing_factor; } bool RateControlSettings::UseAlrProbing() const { - return alr_probing_.Get(); + return video_config_.alr_probing; +} + +absl::optional RateControlSettings::LibvpxVp8QpMax() const { + if (video_config_.vp8_qp_max && + (*video_config_.vp8_qp_max < 0 || *video_config_.vp8_qp_max > 63)) { + // RTC_LOG(LS_WARNING) << "Unsupported vp8_qp_max_ value, ignored."; + return absl::nullopt; + } + return video_config_.vp8_qp_max; +} + +absl::optional RateControlSettings::LibvpxVp8MinPixels() const { + if (video_config_.vp8_min_pixels && *video_config_.vp8_min_pixels < 1) { + return absl::nullopt; + } + return video_config_.vp8_min_pixels; +} + +bool RateControlSettings::LibvpxVp8TrustedRateController() const { + return video_config_.trust_vp8; +} + +bool RateControlSettings::Vp8BoostBaseLayerQuality() const { + return video_config_.vp8_s0_boost; +} + +bool RateControlSettings::LibvpxVp9TrustedRateController() const { + return video_config_.trust_vp9; +} + +bool RateControlSettings::Vp8BaseHeavyTl3RateAllocation() const { + return video_config_.vp8_base_heavy_tl3_alloc; } bool RateControlSettings::TriggerProbeOnMaxAllocatedBitrateChange() const { - return probe_max_allocation_.Get(); + return video_config_.probe_max_allocation; } bool RateControlSettings::UseEncoderBitrateAdjuster() const { - return bitrate_adjuster_.Get(); + return video_config_.bitrate_adjuster; } bool RateControlSettings::BitrateAdjusterCanUseNetworkHeadroom() const { - return adjuster_use_headroom_.Get(); + return video_config_.adjuster_use_headroom; } } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.h index a08afbd03f..fce5831159 100644 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.h +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/rate_control_settings.h @@ -13,12 +13,40 @@ #include "api/transport/webrtc_key_value_config.h" #include "rtc_base/experiments/field_trial_parser.h" -// #include "rtc_base/experiments/field_trial_units.h" +#include "rtc_base/experiments/field_trial_units.h" +#include "rtc_base/experiments/struct_parameters_parser.h" #include namespace webrtc { +struct CongestionWindowConfig { + static constexpr char kKey[] = "WebRTC-CongestionWindow"; + absl::optional queue_size_ms; + absl::optional min_bitrate_bps; + absl::optional initial_data_window; + bool drop_frame_only = false; + std::unique_ptr Parser(); + static CongestionWindowConfig Parse(absl::string_view config); +}; + +struct VideoRateControlConfig { + static constexpr char kKey[] = "WebRTC-VideoRateControl"; + absl::optional pacing_factor; + bool alr_probing = false; + absl::optional vp8_qp_max; + absl::optional vp8_min_pixels; + bool trust_vp8 = true; + bool trust_vp9 = true; + bool probe_max_allocation = true; + bool bitrate_adjuster = true; + bool adjuster_use_headroom = true; + bool vp8_s0_boost = false; + bool vp8_base_heavy_tl3_alloc = false; + + std::unique_ptr Parser(); +}; + class RateControlSettings final { public: ~RateControlSettings(); @@ -34,11 +62,23 @@ class RateControlSettings final { bool UseCongestionWindow() const; int64_t GetCongestionWindowAdditionalTimeMs() const; bool UseCongestionWindowPushback() const; + bool UseCongestionWindowDropFrameOnly() const; uint32_t CongestionWindowMinPushbackTargetBitrateBps() const; + absl::optional CongestionWindowInitialDataWindow() const; absl::optional GetPacingFactor() const; bool UseAlrProbing() const; + absl::optional LibvpxVp8QpMax() const; + absl::optional LibvpxVp8MinPixels() const; + bool LibvpxVp8TrustedRateController() const; + bool Vp8BoostBaseLayerQuality() const; + bool Vp8DynamicRateSettings() const; + bool LibvpxVp9TrustedRateController() const; + bool Vp9DynamicRateSettings() const; + + bool Vp8BaseHeavyTl3RateAllocation() const; + bool TriggerProbeOnMaxAllocatedBitrateChange() const; bool UseEncoderBitrateAdjuster() const; bool BitrateAdjusterCanUseNetworkHeadroom() const; @@ -47,15 +87,8 @@ class RateControlSettings final { explicit RateControlSettings( const WebRtcKeyValueConfig* const key_value_config); - double GetSimulcastScreenshareHysteresisFactor() const; - - FieldTrialOptional congestion_window_; - FieldTrialOptional congestion_window_pushback_; - FieldTrialOptional pacing_factor_; - FieldTrialParameter alr_probing_; - FieldTrialParameter probe_max_allocation_; - FieldTrialParameter bitrate_adjuster_; - FieldTrialParameter adjuster_use_headroom_; + CongestionWindowConfig congestion_window_config_; + VideoRateControlConfig video_config_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc new file mode 100644 index 0000000000..b2cf80c66b --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.cc @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2019 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 "rtc_base/experiments/struct_parameters_parser.h" + +#include + +#include "absl/strings/string_view.h" +//#include "rtc_base/logging.h" + +namespace webrtc { +namespace { +size_t FindOrEnd(absl::string_view str, size_t start, char delimiter) { + size_t pos = str.find(delimiter, start); + pos = (pos == absl::string_view::npos) ? str.length() : pos; + return pos; +} +} // namespace + +std::string ToString(const double d) { + char buf[32]; + const int len = std::snprintf(&buf[0], ABSL_ARRAYSIZE(buf), "%g", d); + // RTC_DCHECK_LE(len, arraysize(buf)); + return std::string(&buf[0], len); +} + +std::string ToString(const bool b) { + return b ? "true" : "false"; +} + +std::string ToString(const int s) { + char buf[32]; + const int len = std::snprintf(&buf[0], ABSL_ARRAYSIZE(buf), "%d", s); + // RTC_DCHECK_LE(len, arraysize(buf)); + return std::string(&buf[0], len); +} + +std::string ToString(const unsigned int s) { + char buf[32]; + const int len = std::snprintf(&buf[0], ABSL_ARRAYSIZE(buf), "%u", s); + // RTC_DCHECK_LE(len, arraysize(buf)); + return std::string(&buf[0], len); +} + +namespace struct_parser_impl { +namespace { +inline void StringEncode(std::string* target, bool val) { + *target += ToString(val); +} +inline void StringEncode(std::string* target, double val) { + *target += ToString(val); +} +inline void StringEncode(std::string* target, int val) { + *target += ToString(val); +} +inline void StringEncode(std::string* target, unsigned val) { + *target += ToString(val); +} +inline void StringEncode(std::string* target, DataRate val) { + *target += webrtc::ToString(val); +} +inline void StringEncode(std::string* target, DataSize val) { + *target += webrtc::ToString(val); +} +inline void StringEncode(std::string* target, TimeDelta val) { + *target += webrtc::ToString(val); +} + +template +inline void StringEncode(std::string* sb, absl::optional val) { + if (val) + StringEncode(sb, *val); +} +} // namespace +template +bool TypedParser::Parse(absl::string_view src, void* target) { + auto parsed = ParseTypedParameter(std::string(src)); + if (parsed.has_value()) + *reinterpret_cast(target) = *parsed; + return parsed.has_value(); +} +template +void TypedParser::Encode(const void* src, std::string* target) { + StringEncode(target, *reinterpret_cast(src)); +} + +template class TypedParser; +template class TypedParser; +template class TypedParser; +template class TypedParser; +template class TypedParser>; +template class TypedParser>; +template class TypedParser>; + +template class TypedParser; +template class TypedParser; +template class TypedParser; +template class TypedParser>; +template class TypedParser>; +template class TypedParser>; +} // namespace struct_parser_impl + +StructParametersParser::StructParametersParser( + std::vector members) + : members_(std::move(members)) {} + +void StructParametersParser::Parse(absl::string_view src) { + size_t i = 0; + while (i < src.length()) { + size_t val_end = FindOrEnd(src, i, ','); + size_t colon_pos = FindOrEnd(src, i, ':'); + size_t key_end = std::min(val_end, colon_pos); + size_t val_begin = key_end + 1u; + absl::string_view key(src.substr(i, key_end - i)); + absl::string_view opt_value; + if (val_end >= val_begin) + opt_value = src.substr(val_begin, val_end - val_begin); + i = val_end + 1u; + bool found = false; + for (auto& member : members_) { + if (key == member.key) { + found = true; + if (!member.parser.parse(opt_value, member.member_ptr)) { + // RTC_LOG(LS_WARNING) << "Failed to read field with key: '" << key + // << "' in trial: \"" << src << "\""; + } + break; + } + } + // "_" is be used to prefix keys that are part of the string for + // debugging purposes but not neccessarily used. + // e.g. WebRTC-Experiment/param: value, _DebuggingString + if (!found && (key.empty() || key[0] != '_')) { + // RTC_LOG(LS_INFO) << "No field with key: '" << key + // << "' (found in trial: \"" << src << "\")"; + } + } +} + +std::string StructParametersParser::Encode() const { + std::string res; + bool first = true; + for (const auto& member : members_) { + if (!first) + res += ","; + res += member.key; + res += ":"; + member.parser.encode(member.member_ptr, &res); + first = false; + } + return res; +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.h new file mode 100644 index 0000000000..1de1c00ff0 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/experiments/struct_parameters_parser.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2019 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. + */ +#ifndef RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_ +#define RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_ + +#include +#include +#include +#include +#include +#include + +#include "absl/memory/memory.h" +#include "absl/strings/string_view.h" +#include "absl/types/optional.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/experiments/field_trial_units.h" + +namespace webrtc { +namespace struct_parser_impl { +struct TypedMemberParser { + public: + bool (*parse)(absl::string_view src, void* target); + void (*encode)(const void* src, std::string* target); +}; + +struct MemberParameter { + const char* key; + void* member_ptr; + TypedMemberParser parser; +}; + +template +class TypedParser { + public: + static bool Parse(absl::string_view src, void* target); + static void Encode(const void* src, std::string* target); +}; + +// Instantiated in cc file to avoid duplication during compile. Add additional +// parsers as needed. Generally, try to use these suggested types even if the +// context where the value is used might require a different type. For instance, +// a size_t representing a packet size should use an int parameter as there's no +// need to support packet sizes larger than INT32_MAX. +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser>; +extern template class TypedParser>; +extern template class TypedParser>; + +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser; +extern template class TypedParser>; +extern template class TypedParser>; +extern template class TypedParser>; + +template +void AddMembers(MemberParameter* out, const char* key, T* member) { + *out = MemberParameter{ + key, member, + TypedMemberParser{&TypedParser::Parse, &TypedParser::Encode}}; +} + +template +void AddMembers(MemberParameter* out, + const char* key, + T* member, + Args... args) { + AddMembers(out, key, member); + AddMembers(++out, args...); +} +} // namespace struct_parser_impl + +class StructParametersParser { + public: + template + static std::unique_ptr Create(const char* first_key, + T* first_member, + Args... args) { + std::vector members( + sizeof...(args) / 2 + 1); + struct_parser_impl::AddMembers(&members.front(), std::move(first_key), + first_member, args...); + return absl::WrapUnique(new StructParametersParser(std::move(members))); + } + + void Parse(absl::string_view src); + std::string Encode() const; + + private: + explicit StructParametersParser( + std::vector members); + + std::vector members_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_EXPERIMENTS_STRUCT_PARAMETERS_PARSER_H_ From 44088ebc85db1d388721baf3d50f3ed2eb219785 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 10 Oct 2022 10:47:52 +0300 Subject: [PATCH 02/70] Initial commit, backport main component. --- worker/deps/libwebrtc/meson.build | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 7d2c54e219..610646fd9f 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -4,7 +4,9 @@ libwebrtc_sources = [ 'libwebrtc/rtc_base/experiments/field_trial_parser.cc', 'libwebrtc/rtc_base/experiments/alr_experiment.cc', 'libwebrtc/rtc_base/experiments/field_trial_units.cc', + 'libwebrtc/rtc_base/experiments/field_trial_list.cc', 'libwebrtc/rtc_base/experiments/rate_control_settings.cc', + 'libwebrtc/rtc_base/experiments/struct_parameters_parser.cc', 'libwebrtc/rtc_base/network/sent_packet.cc', 'libwebrtc/call/rtp_transport_controller_send.cc', 'libwebrtc/api/transport/bitrate_settings.cc', @@ -23,12 +25,13 @@ libwebrtc_sources = [ 'libwebrtc/modules/remote_bitrate_estimator/overuse_detector.cc', 'libwebrtc/modules/remote_bitrate_estimator/overuse_estimator.cc', 'libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc', - 'libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc', 'libwebrtc/modules/remote_bitrate_estimator/bwe_defines.cc', 'libwebrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc', + 'libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc', 'libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.cc', 'libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc', 'libwebrtc/modules/bitrate_controller/loss_based_bandwidth_estimation.cc', + 'libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc', 'libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc', 'libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc', @@ -40,6 +43,9 @@ libwebrtc_sources = [ 'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc', 'libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator.cc', + 'libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc', + 'libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc', + 'libwebrtc/modules/congestion_controller/goog_cc/robust_throughput_estimator.cc', 'libwebrtc/modules/congestion_controller/rtp/send_time_history.cc', 'libwebrtc/modules/congestion_controller/rtp/transport_feedback_adapter.cc', 'libwebrtc/modules/congestion_controller/rtp/control_handler.cc', From f01bd515731520378b26cff0352fb24ccbd4ced2 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 14 Nov 2022 16:51:27 +0200 Subject: [PATCH 03/70] First failed attempt to backport Pacer, save to preserve. --- worker/deps/libwebrtc/libwebrtc.gyp | 2 +- .../libwebrtc/api/bitrate_constraints.h | 41 -- .../api/transport/bitrate_settings.h | 18 +- .../libwebrtc/api/transport/network_types.h | 10 +- .../call/rtp_transport_controller_send.cc | 158 ++-- .../call/rtp_transport_controller_send.h | 43 +- .../rtp_transport_controller_send_interface.h | 8 +- .../congestion_window_pushback_controller.cc | 14 +- .../goog_cc/median_slope_estimator.cc | 88 --- .../goog_cc/median_slope_estimator.h | 72 -- .../goog_cc/probe_bitrate_estimator.cc | 5 - .../goog_cc/probe_bitrate_estimator.h | 3 - .../goog_cc/trendline_estimator.h | 2 - .../modules/pacing/bitrate_prober.cc | 162 ++--- .../libwebrtc/modules/pacing/bitrate_prober.h | 50 +- .../libwebrtc/modules/pacing/paced_sender.cc | 461 ++++++------ .../libwebrtc/modules/pacing/paced_sender.h | 264 ++++--- .../modules/pacing/pacing_controller.cc | 686 ++++++++++++++++++ .../modules/pacing/pacing_controller.h | 237 ++++++ .../pacing/prioritized_packet_queue.cc | 272 +++++++ .../modules/pacing/prioritized_packet_queue.h | 159 ++++ .../modules/pacing/rtp_packet_pacer.h | 74 ++ .../modules/pacing/rtp_packet_sender.h | 34 + .../aimd_rate_control.cc | 193 ++--- .../aimd_rate_control.h | 33 +- .../remote_bitrate_estimator/inter_arrival.cc | 9 +- .../remote_bitrate_estimator/inter_arrival.h | 6 +- .../rtp_rtcp/include/rtp_rtcp_defines.h | 11 + .../libwebrtc/rtc_base/rate_limiter.cc | 69 ++ .../libwebrtc/rtc_base/rate_limiter.h | 56 ++ worker/deps/libwebrtc/meson.build | 4 +- worker/include/RTC/RtpPacket.hpp | 6 + 32 files changed, 2412 insertions(+), 838 deletions(-) delete mode 100644 worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h diff --git a/worker/deps/libwebrtc/libwebrtc.gyp b/worker/deps/libwebrtc/libwebrtc.gyp index bc786cf165..6d469fbaac 100644 --- a/worker/deps/libwebrtc/libwebrtc.gyp +++ b/worker/deps/libwebrtc/libwebrtc.gyp @@ -85,7 +85,7 @@ 'libwebrtc/api/transport/network_control.h', 'libwebrtc/api/transport/field_trial_based_config.h', 'libwebrtc/api/transport/goog_cc_factory.h', - 'libwebrtc/api/bitrate_constraints.h', + 'libwebrtc/api/transport/bitrate_settings.cc', 'libwebrtc/api/units/frequency.h', 'libwebrtc/api/units/data_size.h', 'libwebrtc/api/units/time_delta.h', diff --git a/worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h b/worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h deleted file mode 100644 index 98e89c0858..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2018 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. - */ - -#ifndef API_BITRATE_CONSTRAINTS_H_ -#define API_BITRATE_CONSTRAINTS_H_ - -#include - -namespace webrtc { -// TODO(srte): BitrateConstraints and BitrateSettings should be merged. -// Both represent the same kind data, but are using different default -// initializer and representation of unset values. -struct BitrateConstraints { - int min_bitrate_bps = 0; - int start_bitrate_bps = kDefaultStartBitrateBps; - int max_bitrate_bps = -1; - - private: - static constexpr int kDefaultStartBitrateBps = 300000; -}; - -// Like std::min, but considers non-positive values to be unset. -template -static T MinPositive(T a, T b) { - if (a <= 0) { - return b; - } - if (b <= 0) { - return a; - } - return std::min(a, b); -} -} // namespace webrtc -#endif // API_BITRATE_CONSTRAINTS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h b/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h index 7a09c2e839..cc7e548966 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h @@ -11,11 +11,13 @@ #ifndef API_TRANSPORT_BITRATE_SETTINGS_H_ #define API_TRANSPORT_BITRATE_SETTINGS_H_ -#include +#include + +#include "absl/types/optional.h" namespace webrtc { -// Configuration of send bitrate. The |start_bitrate_bps| value is +// Configuration of send bitrate. The `start_bitrate_bps` value is // used for multiple purposes, both as a prior in the bandwidth // estimator, and for initial configuration of the encoder. We may // want to create separate apis for those, and use a smaller struct @@ -30,6 +32,18 @@ struct BitrateSettings { absl::optional max_bitrate_bps; }; +// TODO(srte): BitrateConstraints and BitrateSettings should be merged. +// Both represent the same kind data, but are using different default +// initializer and representation of unset values. +struct BitrateConstraints { + int min_bitrate_bps = 0; + int start_bitrate_bps = kDefaultStartBitrateBps; + int max_bitrate_bps = -1; + + private: + static constexpr int kDefaultStartBitrateBps = 300000; +}; + } // namespace webrtc #endif // API_TRANSPORT_BITRATE_SETTINGS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index bd76166aa9..0cef4b4cf8 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -210,11 +210,11 @@ struct PacerConfig { }; struct ProbeClusterConfig { - Timestamp at_time = Timestamp::PlusInfinity(); - DataRate target_data_rate = DataRate::Zero(); - TimeDelta target_duration = TimeDelta::Zero(); - int32_t target_probe_count = 0; - int32_t id = 0; + Timestamp at_time = Timestamp::PlusInfinity(); + DataRate target_data_rate = DataRate::Zero(); + TimeDelta target_duration = TimeDelta::Zero(); + int32_t target_probe_count = 0; + int32_t id = 0; }; struct TargetTransferRate { diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc index f99aaa2846..3bd7a3db14 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc @@ -30,8 +30,11 @@ namespace webrtc { namespace { +static const int64_t kRetransmitWindowSizeMs = 500; static const size_t kMaxOverheadBytes = 500; +constexpr TimeDelta kPacerQueueUpdateInterval = TimeDelta::Millis<25>(); + TargetRateConstraints ConvertConstraints(int min_bitrate_bps, int max_bitrate_bps, int start_bitrate_bps) { @@ -51,15 +54,33 @@ TargetRateConstraints ConvertConstraints(const BitrateConstraints& contraints) { contraints.max_bitrate_bps, contraints.start_bitrate_bps); } + +bool IsEnabled(const WebRtcKeyValueConfig& trials, absl::string_view key) { + return absl::StartsWith(trials.Lookup(key), "Enabled"); +} + +bool IsDisabled(const WebRtcKeyValueConfig& trials, absl::string_view key) { + return absl::StartsWith(trials.Lookup(key), "Disabled"); +} + } // namespace +RtpTransportControllerSend::PacerSettings::PacerSettings( + const WebRtcKeyValueConfig& trials) + : holdback_window("holdback_window", TimeDelta::ms(5)), + holdback_packets("holdback_packets", 3) { + ParseFieldTrial({&holdback_window, &holdback_packets}, + trials.Lookup("WebRTC-TaskQueuePacer")); +} + RtpTransportControllerSend::RtpTransportControllerSend( PacketRouter* packet_router, NetworkStatePredictorFactoryInterface* predictor_factory, NetworkControllerFactoryInterface* controller_factory, - const BitrateConstraints& bitrate_config) + const BitrateConstraints& bitrate_config, + const WebRtcKeyValueConfig& trials) : packet_router_(packet_router), - pacer_(packet_router_), + pacer_(packet_router_, trials), observer_(nullptr), controller_factory_override_(controller_factory), process_interval_(controller_factory_override_->GetProcessInterval()), @@ -74,7 +95,7 @@ RtpTransportControllerSend::RtpTransportControllerSend( // RTC_DCHECK(bitrate_config.start_bitrate_bps > 0); MS_ASSERT(bitrate_config.start_bitrate_bps > 0, "start bitrate must be > 0"); - pacer_.SetPacingRates(bitrate_config.start_bitrate_bps, 0); + pacer_.SetPacingRates(DataRate::bps(bitrate_config.start_bitrate_bps), DataRate::bps(0)); } RtpTransportControllerSend::~RtpTransportControllerSend() { @@ -84,7 +105,7 @@ void RtpTransportControllerSend::UpdateControlState() { absl::optional update = control_handler_->GetUpdate(); if (!update) return; - + retransmission_rate_limiter_.SetMaxRate(update->target_rate.bps()); // We won't create control_handler_ until we have an observers. // RTC_DCHECK(observer_ != nullptr); MS_ASSERT(observer_ != nullptr, "no observer"); @@ -92,22 +113,31 @@ void RtpTransportControllerSend::UpdateControlState() { observer_->OnTargetTransferRate(*update); } +void RtpTransportControllerSend::UpdateCongestedState() { + bool congested = transport_feedback_adapter_.GetOutstandingData() >= + congestion_window_size_; + if (congested != is_congested_) { + is_congested_ = congested; + pacer_.SetCongested(congested); + } +} + PacketRouter* RtpTransportControllerSend::packet_router() { return this->packet_router_; } NetworkStateEstimateObserver* RtpTransportControllerSend::network_state_estimate_observer() { - return this; + return this->network_state_estimate_observer(); } TransportFeedbackObserver* RtpTransportControllerSend::transport_feedback_observer() { - return this; + return this->transport_feedback_observer(); } -PacedSender* RtpTransportControllerSend::packet_sender() { - return &pacer_; +RtpPacketSender* RtpTransportControllerSend::packet_sender() { + return &this->pacer_; } void RtpTransportControllerSend::SetAllocatedSendBitrateLimits( @@ -131,6 +161,9 @@ void RtpTransportControllerSend::SetPacingFactor(float pacing_factor) { streams_config_.pacing_factor = pacing_factor; UpdateStreamsConfig(); } +/*void RtpTransportControllerSend::SetQueueTimeLimit(int limit_ms) { + pacer_.SetQueueTimeLimit(TimeDelta::ms(limit_ms)); +}*/ void RtpTransportControllerSend::RegisterTargetTransferRateObserver( TargetTransferRateObserver* observer) { @@ -158,16 +191,17 @@ void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) { } else { pacer_.Pause(); } - pacer_.UpdateOutstandingData(0); + is_congested_ = false; + pacer_.SetCongested(false); control_handler_->SetNetworkAvailability(network_available_); PostUpdates(controller_->OnNetworkAvailability(msg)); UpdateControlState(); } -RtcpBandwidthObserver* RtpTransportControllerSend::GetBandwidthObserver() { +/*RtcpBandwidthObserver* RtpTransportControllerSend::GetBandwidthObserver() { return this; -} +}*/ void RtpTransportControllerSend::EnablePeriodicAlrProbing(bool enable) { streams_config_.requests_alr_probing = enable; @@ -175,17 +209,55 @@ void RtpTransportControllerSend::EnablePeriodicAlrProbing(bool enable) { } void RtpTransportControllerSend::OnSentPacket( - const rtc::SentPacket& sent_packet, size_t size) { - MS_DEBUG_DEV("<<<<< size:%zu", size); + const rtc::SentPacket& sent_packet, size_t size) +{ + MS_DEBUG_DEV("<<<<< size:%zu", size); + + absl::optional packet_msg = transport_feedback_adapter_.ProcessSentPacket(sent_packet); + if (packet_msg) + { + // Only update outstanding data if: + // 1. Packet feadback is used. + // 2. The packet has not yet received an acknowledgement. + // 3. It is not a retransmission of an earlier packet. + UpdateCongestedState(); + if (controller_) + PostUpdates(controller_->OnSentPacket(*packet_msg)); + } +} - absl::optional packet_msg = - transport_feedback_adapter_.ProcessSentPacket(sent_packet); - if (packet_msg) - PostUpdates(controller_->OnSentPacket(*packet_msg)); - pacer_.UpdateOutstandingData( - transport_feedback_adapter_.GetOutstandingData().bytes()); +void RtpTransportControllerSend::UpdateBitrateConstraints( + const BitrateConstraints& updated) { + TargetRateConstraints msg = ConvertConstraints(updated); + PostUpdates(controller_->OnTargetRateConstraints(msg)); + }; + +/*void RtpTransportControllerSend::SetSdpBitrateParameters( + const BitrateConstraints& constraints) { + absl::optional updated = + bitrate_configurator_.UpdateWithSdpParameters(constraints); + if (updated.has_value()) { + UpdateBitrateConstraints(*updated); + } else { + RTC_LOG(LS_VERBOSE) + << "WebRTC.RtpTransportControllerSend.SetSdpBitrateParameters: " + "nothing to update"; + } } +void RtpTransportControllerSend::SetClientBitratePreferences( + const BitrateSettings& preferences) { + absl::optional updated = + bitrate_configurator_.UpdateWithClientPreferences(preferences); + if (updated.has_value()) { + UpdateBitrateConstraints(*updated); + } else { + RTC_LOG(LS_VERBOSE) + << "WebRTC.RtpTransportControllerSend.SetClientBitratePreferences: " + "nothing to update"; + } +}*/ + void RtpTransportControllerSend::OnTransportOverheadChanged( size_t transport_overhead_bytes_per_packet) { MS_DEBUG_DEV("<<<<< transport_overhead_bytes_per_packet:%zu", transport_overhead_bytes_per_packet); @@ -194,6 +266,9 @@ void RtpTransportControllerSend::OnTransportOverheadChanged( MS_ERROR("transport overhead exceeds: %zu", kMaxOverheadBytes); return; } + + pacer_.SetTransportOverhead( + DataSize::bytes(transport_overhead_bytes_per_packet)); } void RtpTransportControllerSend::OnReceivedEstimatedBitrate(uint32_t bitrate) { @@ -226,7 +301,7 @@ void RtpTransportControllerSend::OnAddPacket( const RtpPacketSendInfo& packet_info) { transport_feedback_adapter_.AddPacket( packet_info, - send_side_bwe_with_overhead_ ? transport_overhead_bytes_per_packet_.load() + send_side_bwe_with_overhead_ ? transport_overhead_bytes_per_packet_ : 0, Timestamp::ms(DepLibUV::GetTimeMsInt64())); } @@ -240,14 +315,14 @@ void RtpTransportControllerSend::OnTransportFeedback( feedback, Timestamp::ms(DepLibUV::GetTimeMsInt64())); if (feedback_msg) PostUpdates(controller_->OnTransportPacketsFeedback(*feedback_msg)); - pacer_.UpdateOutstandingData( - transport_feedback_adapter_.GetOutstandingData().bytes()); + + UpdateCongestedState(); } void RtpTransportControllerSend::OnRemoteNetworkEstimate( NetworkStateEstimate estimate) { estimate.update_time = Timestamp::ms(DepLibUV::GetTimeMsInt64()); - controller_->OnNetworkStateEstimate(estimate); + PostUpdates(controller_->OnNetworkStateEstimate(estimate)); } void RtpTransportControllerSend::Process() @@ -297,28 +372,21 @@ void RtpTransportControllerSend::UpdateStreamsConfig() { } void RtpTransportControllerSend::PostUpdates(NetworkControlUpdate update) { - if (update.congestion_window) { - if (update.congestion_window->IsFinite()) - pacer_.SetCongestionWindow(update.congestion_window->bytes()); - else - pacer_.SetCongestionWindow(PacedSender::kNoCongestionWindow); - } - if (update.pacer_config) { - pacer_.SetPacingRates(update.pacer_config->data_rate().bps(), - update.pacer_config->pad_rate().bps()); - } - - // TODO: REMOVE: this removes any probation. - // update.probe_cluster_configs.clear(); - - for (const auto& probe : update.probe_cluster_configs) { - int64_t bitrate_bps = probe.target_data_rate.bps(); - pacer_.CreateProbeCluster(bitrate_bps, probe.id); - } - if (update.target_rate) { - control_handler_->SetTargetRate(*update.target_rate); - UpdateControlState(); - } + if (update.congestion_window) { + congestion_window_size_ = *update.congestion_window; + UpdateCongestedState(); + } + if (update.pacer_config) { + pacer_.SetPacingRates(update.pacer_config->data_rate(), + update.pacer_config->pad_rate()); + } + if (!update.probe_cluster_configs.empty()) { + pacer_.CreateProbeClusters(update.probe_cluster_configs); + } + if (update.target_rate) { + control_handler_->SetTargetRate(*update.target_rate); + UpdateControlState(); + } } void RtpTransportControllerSend::OnReceivedRtcpReceiverReportBlocks( diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h index 7ffc321717..6a1bb53db4 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h @@ -18,9 +18,11 @@ #include "call/rtp_transport_controller_send_interface.h" #include "modules/congestion_controller/rtp/control_handler.h" #include "modules/congestion_controller/rtp/transport_feedback_adapter.h" -#include "rtc_base/constructor_magic.h" -#include "modules/pacing/packet_router.h" #include "modules/pacing/paced_sender.h" +#include "modules/pacing/pacing_controller.h" +#include "modules/pacing/packet_router.h" +#include "rtc_base/constructor_magic.h" +#include "rtc_base/rate_limiter.h" #include #include @@ -43,14 +45,19 @@ class RtpTransportControllerSend final PacketRouter* packet_router, NetworkStatePredictorFactoryInterface* predictor_factory, NetworkControllerFactoryInterface* controller_factory, - const BitrateConstraints& bitrate_config); + const BitrateConstraints& bitrate_config, + const WebRtcKeyValueConfig& trials); ~RtpTransportControllerSend() override; + RtpTransportControllerSend(const RtpTransportControllerSend&) = delete; + RtpTransportControllerSend& operator=(const RtpTransportControllerSend&) = + delete; + PacketRouter* packet_router() override; NetworkStateEstimateObserver* network_state_estimate_observer() override; TransportFeedbackObserver* transport_feedback_observer() override; - PacedSender* packet_sender() override; + RtpPacketSender* packet_sender() override; void SetAllocatedSendBitrateLimits(int min_send_bitrate_bps, int max_padding_bitrate_bps, @@ -67,7 +74,7 @@ class RtpTransportControllerSend final void OnSentPacket(const rtc::SentPacket& sent_packet, size_t size) override; void OnTransportOverheadChanged( - size_t transport_overhead_per_packet) override; + size_t transport_overhead_bytes_per_packet) override; // Implements RtcpBandwidthObserver interface void OnReceivedEstimatedBitrate(uint32_t bitrate) override; @@ -85,15 +92,24 @@ class RtpTransportControllerSend final void Process(); private: - void MaybeCreateControllers(); + struct PacerSettings { + explicit PacerSettings(const WebRtcKeyValueConfig& trials); + FieldTrialParameter holdback_window; + FieldTrialParameter holdback_packets; + }; + + void MaybeCreateControllers(); void UpdateControllerWithTimeInterval(); + void UpdateBitrateConstraints(const BitrateConstraints& updated); void UpdateStreamsConfig(); void OnReceivedRtcpReceiverReportBlocks(const ReportBlockList& report_blocks, int64_t now_ms); + void PostUpdates(NetworkControlUpdate update); void UpdateControlState(); + void UpdateCongestedState(); const FieldTrialBasedConfig trial_based_config_; @@ -123,15 +139,20 @@ class RtpTransportControllerSend final // const bool add_pacing_to_cwin_; // Transport overhead is written by OnNetworkRouteChanged and read by // AddPacket. - // TODO(srte): Remove atomic when feedback adapter runs on task queue. - std::atomic transport_overhead_bytes_per_packet_; + size_t transport_overhead_bytes_per_packet_; bool network_available_; - // TODO(perkj): |task_queue_| is supposed to replace |process_thread_|. - // |task_queue_| is defined last to ensure all pending tasks are cancelled + DataSize congestion_window_size_; + bool is_congested_; + + // Protected by internal locks. + RateLimiter retransmission_rate_limiter_; + + // TODO(perkj): `task_queue_` is supposed to replace `process_thread_`. + // `task_queue_` is defined last to ensure all pending tasks are cancelled // and deleted before any other members. - RTC_DISALLOW_COPY_AND_ASSIGN(RtpTransportControllerSend); + const WebRtcKeyValueConfig& field_trials_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h index 1575f45b78..b5eb2e3548 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h @@ -11,7 +11,6 @@ #ifndef CALL_RTP_TRANSPORT_CONTROLLER_SEND_INTERFACE_H_ #define CALL_RTP_TRANSPORT_CONTROLLER_SEND_INTERFACE_H_ -#include "api/bitrate_constraints.h" #include "api/transport/bitrate_settings.h" // #include "call/rtp_config.h" // #include "modules/rtp_rtcp/include/report_block_data.h" @@ -19,13 +18,14 @@ #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" // #include "modules/rtp_rtcp/source/rtp_packet_received.h" +#include "modules/pacing/pacing_controller.h" #include "RTC/RtpPacket.hpp" #include -#include -#include #include #include +#include +#include #include #include @@ -76,7 +76,7 @@ class RtpTransportControllerSendInterface { virtual NetworkStateEstimateObserver* network_state_estimate_observer() = 0; virtual TransportFeedbackObserver* transport_feedback_observer() = 0; - virtual PacedSender* packet_sender() = 0; + virtual PacingController* packet_sender() = 0; // SetAllocatedSendBitrateLimits sets bitrates limits imposed by send codec // settings. diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc index 53b9bd4c96..a43cc9bd8b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc @@ -25,7 +25,10 @@ CongestionWindowPushbackController::CongestionWindowPushbackController( .find("Enabled") == 0), min_pushback_target_bitrate_bps_( RateControlSettings::ParseFromKeyValueConfig(key_value_config) - .CongestionWindowMinPushbackTargetBitrateBps()) {} + .CongestionWindowMinPushbackTargetBitrateBps()), + current_data_window_( + RateControlSettings::ParseFromKeyValueConfig(key_value_config) + .CongestionWindowInitialDataWindow()) {} CongestionWindowPushbackController::CongestionWindowPushbackController( const WebRtcKeyValueConfig* key_value_config, @@ -44,15 +47,6 @@ void CongestionWindowPushbackController::UpdatePacingQueue( pacing_bytes_ = pacing_bytes; } -void CongestionWindowPushbackController::UpdateMaxOutstandingData( - size_t max_outstanding_bytes) { - DataSize data_window = DataSize::bytes(max_outstanding_bytes); - if (current_data_window_) { - data_window = (data_window + current_data_window_.value()) / 2; - } - current_data_window_ = data_window; -} - void CongestionWindowPushbackController::SetDataWindow(DataSize data_window) { current_data_window_ = data_window; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc deleted file mode 100644 index 07648b9751..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2016 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 "modules/congestion_controller/goog_cc/median_slope_estimator.h" - -#include - -namespace webrtc { - -constexpr unsigned int kDeltaCounterMax = 1000; - -MedianSlopeEstimator::MedianSlopeEstimator(size_t window_size, - double threshold_gain) - : window_size_(window_size), - threshold_gain_(threshold_gain), - num_of_deltas_(0), - accumulated_delay_(0), - delay_hist_(), - median_filter_(0.5), - trendline_(0) {} - -MedianSlopeEstimator::~MedianSlopeEstimator() {} - -MedianSlopeEstimator::DelayInfo::DelayInfo(int64_t time, - double delay, - size_t slope_count) - : time(time), delay(delay) { - slopes.reserve(slope_count); -} - -MedianSlopeEstimator::DelayInfo::~DelayInfo() = default; - -void MedianSlopeEstimator::Update(double recv_delta_ms, - double send_delta_ms, - int64_t arrival_time_ms) { - const double delta_ms = recv_delta_ms - send_delta_ms; - ++num_of_deltas_; - if (num_of_deltas_ > kDeltaCounterMax) - num_of_deltas_ = kDeltaCounterMax; - - accumulated_delay_ += delta_ms; - // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, - // accumulated_delay_); - - // If the window is full, remove the |window_size_| - 1 slopes that belong to - // the oldest point. - if (delay_hist_.size() == window_size_) { - // for (double slope : delay_hist_.front().slopes) { - // const bool success = median_filter_.Erase(slope); - // RTC_CHECK(success); - // } - delay_hist_.pop_front(); - } - // Add |window_size_| - 1 new slopes. - for (auto& old_delay : delay_hist_) { - if (arrival_time_ms - old_delay.time != 0) { - // The C99 standard explicitly states that casts and assignments must - // perform the associated conversions. This means that |slope| will be - // a 64-bit double even if the division is computed using, e.g., 80-bit - // extended precision. I believe this also holds in C++ even though the - // C++11 standard isn't as explicit. Furthermore, there are good reasons - // to believe that compilers couldn't perform optimizations that break - // this assumption even if they wanted to. - double slope = (accumulated_delay_ - old_delay.delay) / - static_cast(arrival_time_ms - old_delay.time); - median_filter_.Insert(slope); - // We want to avoid issues with different rounding mode / precision - // which we might get if we recomputed the slope when we remove it. - old_delay.slopes.push_back(slope); - } - } - delay_hist_.emplace_back(arrival_time_ms, accumulated_delay_, - window_size_ - 1); - // Recompute the median slope. - if (delay_hist_.size() == window_size_) - trendline_ = median_filter_.GetPercentileValue(); - - // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trendline_); -} - -} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h deleted file mode 100644 index 674a82829a..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ -#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ - -#include "rtc_base/constructor_magic.h" -#include "rtc_base/numerics/percentile_filter.h" - -#include -#include -#include -#include - -namespace webrtc { - -class MedianSlopeEstimator { - public: - // |window_size| is the number of points required to compute a trend line. - // |threshold_gain| is used to scale the trendline slope for comparison to - // the old threshold. Once the old estimator has been removed (or the - // thresholds been merged into the estimators), we can just set the - // threshold instead of setting a gain. - MedianSlopeEstimator(size_t window_size, double threshold_gain); - ~MedianSlopeEstimator(); - - // Update the estimator with a new sample. The deltas should represent deltas - // between timestamp groups as defined by the InterArrival class. - void Update(double recv_delta_ms, - double send_delta_ms, - int64_t arrival_time_ms); - - // Returns the estimated trend k multiplied by some gain. - // 0 < k < 1 -> the delay increases, queues are filling up - // k == 0 -> the delay does not change - // k < 0 -> the delay decreases, queues are being emptied - double trendline_slope() const { return trendline_ * threshold_gain_; } - - // Returns the number of deltas which the current estimator state is based on. - unsigned int num_of_deltas() const { return num_of_deltas_; } - - private: - struct DelayInfo { - DelayInfo(int64_t time, double delay, size_t slope_count); - ~DelayInfo(); - int64_t time; - double delay; - std::vector slopes; - }; - // Parameters. - const size_t window_size_; - const double threshold_gain_; - // Used by the existing threshold. - unsigned int num_of_deltas_; - // Theil-Sen robust line fitting - double accumulated_delay_; - std::deque delay_hist_; - PercentileFilter median_filter_; - double trendline_; - - RTC_DISALLOW_COPY_AND_ASSIGN(MedianSlopeEstimator); -}; - -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc index 6022dbdd99..3e24dcdcd4 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc @@ -200,7 +200,6 @@ absl::optional ProbeBitrateEstimator::HandleProbeAndEstimateBitrate( //RTC_DCHECK_GT(send_rate, receive_rate); res = kTargetUtilizationFraction * receive_rate; } - last_estimate_ = res; estimated_data_rate_ = res; return res; } @@ -212,10 +211,6 @@ ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrate() { return estimated_data_rate; } -absl::optional ProbeBitrateEstimator::last_estimate() const { - return last_estimate_; -} - void ProbeBitrateEstimator::EraseOldClusters(Timestamp timestamp) { for (auto it = clusters_.begin(); it != clusters_.end();) { if (it->second.last_receive + kMaxClusterHistory < timestamp) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h index b3eb21c7b0..d826cbc08d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h @@ -33,8 +33,6 @@ class ProbeBitrateEstimator { absl::optional FetchAndResetLastEstimatedBitrate(); - absl::optional last_estimate() const; - private: struct AggregatedCluster { int num_probes = 0; @@ -52,7 +50,6 @@ class ProbeBitrateEstimator { std::map clusters_; absl::optional estimated_data_rate_; - absl::optional last_estimate_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index 6ae5b263bd..a7fef47fc0 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -60,8 +60,6 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { // threshold instead of setting a gain.|network_state_predictor| is used to // bettter predict network state. TrendlineEstimator(size_t window_size, - double smoothing_coef, - double threshold_gain, NetworkStatePredictor* network_state_predictor); ~TrendlineEstimator() override; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc index 1d3ce9806f..4779009bb2 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc @@ -42,26 +42,16 @@ namespace webrtc { namespace { -// The min probe packet size is scaled with the bitrate we're probing at. -// This defines the max min probe packet size, meaning that on high bitrates -// we have a min probe packet size of 200 bytes. -constexpr size_t kMinProbePacketSize = 200; - -constexpr int64_t kProbeClusterTimeoutMs = 5000; +constexpr TimeDelta kProbeClusterTimeout = TimeDelta::Seconds<5>(); } // namespace BitrateProberConfig::BitrateProberConfig( const WebRtcKeyValueConfig* key_value_config) - : min_probe_packets_sent("min_probe_packets_sent", 5), - min_probe_delta("min_probe_delta", TimeDelta::ms(1)), - min_probe_duration("min_probe_duration", TimeDelta::ms(15)), - max_probe_delay("max_probe_delay", TimeDelta::ms(3)) { - ParseFieldTrial({&min_probe_packets_sent, &min_probe_delta, - &min_probe_duration, &max_probe_delay}, - key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); - ParseFieldTrial({&min_probe_packets_sent, &min_probe_delta, - &min_probe_duration, &max_probe_delay}, + : min_probe_delta("min_probe_delta", TimeDelta::Millis<2>()), + max_probe_delay("max_probe_delay", TimeDelta::Millis<10>()), + min_packet_size("min_packet_size", DataSize::Bytes<200>()) { + ParseFieldTrial({&min_probe_delta, &max_probe_delay, &min_packet_size}, key_value_config->Lookup("WebRTC-Bwe-ProbingBehavior")); } @@ -74,7 +64,7 @@ BitrateProber::~BitrateProber() { BitrateProber::BitrateProber(const WebRtcKeyValueConfig& field_trials) : probing_state_(ProbingState::kDisabled), - next_probe_time_ms_(-1), + next_probe_time_(Timestamp::PlusInfinity()), total_probe_count_(0), total_failed_probe_count_(0), config_(&field_trials) { @@ -99,18 +89,16 @@ void BitrateProber::SetEnabled(bool enable) { TODO_PRINT_PROBING_STATE(); } -bool BitrateProber::IsProbing() const { - return probing_state_ == ProbingState::kActive; -} - -void BitrateProber::OnIncomingPacket(size_t packet_size) { +void BitrateProber::OnIncomingPacket(DataSize packet_size) { // Don't initialize probing unless we have something large enough to start // probing. + // Note that the pacer can send several packets at once when sending a probe, + // and thus, packets can be smaller than needed for a probe. if (probing_state_ == ProbingState::kInactive && !clusters_.empty() && packet_size >= - std::min(RecommendedMinProbeSize(), kMinProbePacketSize)) { + std::min(RecommendedMinProbeSize(), config_.min_packet_size.Get())) { // Send next probe right away. - next_probe_time_ms_ = -1; + next_probe_time_ = Timestamp::MinusInfinity(); probing_state_ = ProbingState::kActive; } @@ -118,33 +106,32 @@ void BitrateProber::OnIncomingPacket(size_t packet_size) { TODO_PRINT_PROBING_STATE(); } -void BitrateProber::CreateProbeCluster(int bitrate_bps, - int64_t now_ms, - int cluster_id) { +void BitrateProber::CreateProbeCluster(const ProbeClusterConfig& cluster_config) { // RTC_DCHECK(probing_state_ != ProbingState::kDisabled); // RTC_DCHECK_GT(bitrate_bps, 0); MS_ASSERT(probing_state_ != ProbingState::kDisabled, "probing disabled"); - MS_ASSERT(bitrate_bps > 0, "bitrate must be > 0"); + MS_ASSERT(cluster_config.target_data_rate.bps() > 0, "bitrate must be > 0"); total_probe_count_++; while (!clusters_.empty() && - now_ms - clusters_.front().time_created_ms > kProbeClusterTimeoutMs) { + cluster_config.at_time - clusters_.front().requested_at > + kProbeClusterTimeout) { clusters_.pop(); total_failed_probe_count_++; } ProbeCluster cluster; - cluster.time_created_ms = now_ms; - cluster.pace_info.probe_cluster_min_probes = config_.min_probe_packets_sent; + cluster.requested_at = cluster_config.at_time; + cluster.pace_info.probe_cluster_min_probes = + cluster_config.target_probe_count; cluster.pace_info.probe_cluster_min_bytes = - static_cast(static_cast(bitrate_bps) * - config_.min_probe_duration->ms() / 8000); - + (cluster_config.target_data_rate * cluster_config.target_duration) + .bytes(); // RTC_DCHECK_GE(cluster.pace_info.probe_cluster_min_bytes, 0); - MS_ASSERT(cluster.pace_info.probe_cluster_min_bytes >= 0, "cluster min bytes must be >= 0"); - cluster.pace_info.send_bitrate_bps = bitrate_bps; - cluster.pace_info.probe_cluster_id = cluster_id; + MS_ASSERT(cluster.pace_info.probe_cluster_min_bytes >= 0, "cluster min bytes must be >= 0"); + cluster.pace_info.send_bitrate_bps = cluster_config.target_data_rate.bps(); + cluster.pace_info.probe_cluster_id = cluster_config.id; clusters_.push(cluster); MS_DEBUG_DEV("probe cluster [bitrate:%d, min bytes:%d, min probes:%d]", @@ -159,75 +146,73 @@ void BitrateProber::CreateProbeCluster(int bitrate_bps, // TODO (ibc): We need to send probation even if there is no real packets, so add // this code (taken from `OnIncomingPacket()` above) also here. - if (probing_state_ == ProbingState::kInactive && !clusters_.empty()) { +/* if (probing_state_ == ProbingState::kInactive && !clusters_.empty()) { // Send next probe right away. next_probe_time_ms_ = -1; probing_state_ = ProbingState::kActive; - } + }*/ // TODO: jeje TODO_PRINT_PROBING_STATE(); } -int BitrateProber::TimeUntilNextProbe(int64_t now_ms) { - // TODO: jeje - TODO_PRINT_PROBING_STATE(); - +Timestamp BitrateProber::NextProbeTime(Timestamp now) const { + // TODO: jeje + TODO_PRINT_PROBING_STATE(); // Probing is not active or probing is already complete. - if (probing_state_ != ProbingState::kActive || clusters_.empty()) - return -1; - - int time_until_probe_ms = 0; - if (next_probe_time_ms_ >= 0) { - time_until_probe_ms = next_probe_time_ms_ - now_ms; - if (time_until_probe_ms < -config_.max_probe_delay->ms()) { - MS_WARN_TAG(bwe, "probe delay too high [next_ms:%" PRIi64 ", now_ms:%" PRIi64 "]", - next_probe_time_ms_, - now_ms); - return -1; - } + if (probing_state_ != ProbingState::kActive || clusters_.empty()) { + return Timestamp::PlusInfinity(); } - return std::max(time_until_probe_ms, 0); + return next_probe_time_; } -PacedPacketInfo BitrateProber::CurrentCluster() const { - // RTC_DCHECK(!clusters_.empty()); - // RTC_DCHECK(probing_state_ == ProbingState::kActive); - MS_ASSERT(!clusters_.empty(), "clusters is empty"); - MS_ASSERT(probing_state_ == ProbingState::kActive, "probing not active"); +absl::optional BitrateProber::CurrentCluster(Timestamp now) { + if (clusters_.empty() || probing_state_ != ProbingState::kActive) { + return absl::nullopt; + } - return clusters_.front().pace_info; -} + if (next_probe_time_.IsFinite() && + now - next_probe_time_ > config_.max_probe_delay.Get()) { + MS_WARN_TAG(bwe, "probe delay too high [next_ms:%" PRIi64 ", now_ms:%" PRIi64 "], discarding probe cluster.", + next_probe_time_.ms(), + now.ms()); + clusters_.pop(); + if (clusters_.empty()) { + probing_state_ = ProbingState::kSuspended; + return absl::nullopt; + } + } -// Probe size is recommended based on the probe bitrate required. We choose -// a minimum of twice |kMinProbeDeltaMs| interval to allow scheduling to be -// feasible. -size_t BitrateProber::RecommendedMinProbeSize() const { - // RTC_DCHECK(!clusters_.empty()); - MS_ASSERT(!clusters_.empty(), "clusters is empty"); + PacedPacketInfo info = clusters_.front().pace_info; + info.probe_cluster_bytes_sent = clusters_.front().sent_bytes; + return info; +} - return clusters_.front().pace_info.send_bitrate_bps * 2 * - config_.min_probe_delta->ms() / (8 * 1000); +DataSize BitrateProber::RecommendedMinProbeSize() const { + if (clusters_.empty()) { + return DataSize::Zero(); + } + DataRate send_rate = + DataRate::bps(clusters_.front().pace_info.send_bitrate_bps); + return send_rate * config_.min_probe_delta; } -void BitrateProber::ProbeSent(int64_t now_ms, size_t bytes) { +void BitrateProber::ProbeSent(Timestamp now, DataSize size) { // RTC_DCHECK(probing_state_ == ProbingState::kActive); - // RTC_DCHECK_GT(bytes, 0); - MS_ASSERT(probing_state_ == ProbingState::kActive, "probing not active"); - MS_ASSERT(bytes > 0, "bytes must be > 0"); + // RTC_DCHECK(!size.IsZero()); if (!clusters_.empty()) { ProbeCluster* cluster = &clusters_.front(); if (cluster->sent_probes == 0) { - // RTC_DCHECK_EQ(cluster->time_started_ms, -1); - MS_ASSERT(cluster->time_started_ms == -1, "cluster started time must not be -1"); + // RTC_DCHECK(cluster->started_at.IsInfinite()); - cluster->time_started_ms = now_ms; + MS_ASSERT(cluster->started_at.IsInfinite(), "cluster started time must not be -1"); + cluster->started_at = now; } - cluster->sent_bytes += static_cast(bytes); + cluster->sent_bytes += size.bytes(); cluster->sent_probes += 1; - next_probe_time_ms_ = GetNextProbeTime(*cluster); + next_probe_time_ = CalculateNextProbeTime(*cluster); if (cluster->sent_bytes >= cluster->pace_info.probe_cluster_min_bytes && cluster->sent_probes >= cluster->pace_info.probe_cluster_min_probes) { // RTC_HISTOGRAM_COUNTS_100000("WebRTC.BWE.Probing.ProbeClusterSizeInBytes", @@ -247,18 +232,21 @@ void BitrateProber::ProbeSent(int64_t now_ms, size_t bytes) { } } -int64_t BitrateProber::GetNextProbeTime(const ProbeCluster& cluster) { +Timestamp BitrateProber::CalculateNextProbeTime( + const ProbeCluster& cluster) const { // RTC_CHECK_GT(cluster.pace_info.send_bitrate_bps, 0); - // RTC_CHECK_GE(cluster.time_started_ms, 0); - MS_ASSERT(cluster.pace_info.send_bitrate_bps > 0, "cluster.pace_info.send_bitrate_bps must be > 0"); - MS_ASSERT(cluster.time_started_ms > 0, "cluster.time_started_ms must be > 0"); + // RTC_CHECK(cluster.started_at.IsFinite()); + MS_ASSERT(cluster.pace_info.send_bitrate_bps > 0, "cluster.pace_info.send_bitrate_bps must be > 0"); + MS_ASSERT(cluster.started_at.IsFinite(), "cluster.time_started_ms must be > 0"); // Compute the time delta from the cluster start to ensure probe bitrate stays // close to the target bitrate. Result is in milliseconds. - int64_t delta_ms = - (8000ll * cluster.sent_bytes + cluster.pace_info.send_bitrate_bps / 2) / - cluster.pace_info.send_bitrate_bps; - return cluster.time_started_ms + delta_ms; + DataSize sent_bytes = DataSize::bytes(cluster.sent_bytes); + DataRate send_bitrate = + DataRate::bps(cluster.pace_info.send_bitrate_bps); + + TimeDelta delta = sent_bytes / send_bitrate; + return cluster.started_at + delta; } } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h index ed42c531d8..4fc128999b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h @@ -27,15 +27,15 @@ struct BitrateProberConfig { BitrateProberConfig& operator=(const BitrateProberConfig&) = default; ~BitrateProberConfig() = default; - // The minimum number probing packets used. - FieldTrialParameter min_probe_packets_sent; // A minimum interval between probes to allow scheduling to be feasible. FieldTrialParameter min_probe_delta; - // The minimum probing duration. - FieldTrialParameter min_probe_duration; - // Maximum amount of time each probe can be delayed. Probe cluster is reset - // and retried from the start when this limit is reached. + // Maximum amount of time each probe can be delayed. FieldTrialParameter max_probe_delay; + // This is used to start sending a probe after a large enough packet. + // The min packet size is scaled with the bitrate we're probing at. + // This defines the max min packet size, meaning that on high bitrates + // a packet of at least this size is needed to trigger sending a probe. + FieldTrialParameter min_packet_size; }; // Note that this class isn't thread-safe by itself and therefore relies @@ -50,33 +50,33 @@ class BitrateProber { // Returns true if the prober is in a probing session, i.e., it currently // wants packets to be sent out according to the time returned by // TimeUntilNextProbe(). - bool IsProbing() const; + bool is_probing() const { return probing_state_ == ProbingState::kActive; } // Initializes a new probing session if the prober is allowed to probe. Does // not initialize the prober unless the packet size is large enough to probe // with. - void OnIncomingPacket(size_t packet_size); + void OnIncomingPacket(DataSize packet_size); - // Create a cluster used to probe for |bitrate_bps| with |num_probes| number - // of probes. - void CreateProbeCluster(int bitrate_bps, int64_t now_ms, int cluster_id); - - // Returns the number of milliseconds until the next probe should be sent to - // get accurate probing. - int TimeUntilNextProbe(int64_t now_ms); + // Create a cluster used to probe. + void CreateProbeCluster(const ProbeClusterConfig& cluster_config); + // Returns the time at which the next probe should be sent to get accurate + // probing. If probing is not desired at this time, Timestamp::PlusInfinity() + // will be returned. + // TODO(bugs.webrtc.org/11780): Remove `now` argument when old mode is gone. + Timestamp NextProbeTime(Timestamp now) const; // Information about the current probing cluster. - PacedPacketInfo CurrentCluster() const; + absl::optional CurrentCluster(Timestamp now); // Returns the minimum number of bytes that the prober recommends for - // the next probe. - size_t RecommendedMinProbeSize() const; + // the next probe, or zero if not probing. A probe can consist of multiple + // packets that are sent back to back. + DataSize RecommendedMinProbeSize() const; // Called to report to the prober that a probe has been sent. In case of // multiple packets per probe, this call would be made at the end of sending - // the last packet in probe. |probe_size| is the total size of all packets - // in probe. - void ProbeSent(int64_t now_ms, size_t probe_size); + // the last packet in probe. `size` is the total size of all packets in probe. + void ProbeSent(Timestamp now, DataSize size); private: enum class ProbingState { @@ -99,12 +99,12 @@ class BitrateProber { int sent_probes = 0; int sent_bytes = 0; - int64_t time_created_ms = -1; - int64_t time_started_ms = -1; + Timestamp requested_at = Timestamp::MinusInfinity(); + Timestamp started_at = Timestamp::MinusInfinity(); int retries = 0; }; - int64_t GetNextProbeTime(const ProbeCluster& cluster); + Timestamp CalculateNextProbeTime(const ProbeCluster& cluster) const; ProbingState probing_state_; @@ -114,7 +114,7 @@ class BitrateProber { std::queue clusters_; // Time the next probe should be sent when in kActive state. - int64_t next_probe_time_ms_; + Timestamp next_probe_time_; int total_probe_count_; int total_failed_probe_count_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc index 1c638428b2..704869648c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2019 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 @@ -8,286 +8,317 @@ * be found in the AUTHORS file in the root of the source tree. */ -#define MS_CLASS "webrtc::PacedSender" -// #define MS_LOG_DEV_LEVEL 3 - #include "modules/pacing/paced_sender.h" -#include "modules/pacing/bitrate_prober.h" -#include "modules/pacing/interval_budget.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "system_wrappers/source/field_trial.h" // webrtc::field_trial. - -#include "DepLibUV.hpp" -#include "Logger.hpp" -#include "RTC/RtpPacket.hpp" -#include #include #include +#include "absl/memory/memory.h" +// #include "api/task_queue/pending_task_safety_flag.h" +#include "api/transport/network_types.h" +// #include "rtc_base/checks.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/experiments/field_trial_units.h" +#include "rtc_base/system/unused.h" +// #include "rtc_base/trace_event.h" + namespace webrtc { + namespace { -// Time limit in milliseconds between packet bursts. -const int64_t kDefaultMinPacketLimitMs = 5; -const int64_t kCongestedPacketIntervalMs = 500; -const int64_t kPausedProcessIntervalMs = kCongestedPacketIntervalMs; -const int64_t kMaxElapsedTimeMs = 2000; -// Upper cap on process interval, in case process has not been called in a long -// time. -const int64_t kMaxIntervalTimeMs = 30; +constexpr const char* kBurstyPacerFieldTrial = "WebRTC-BurstyPacer"; + +constexpr const char* kSlackedPacedSenderFieldTrial = + "WebRTC-SlackedPacedSender"; } // namespace -const float PacedSender::kDefaultPaceMultiplier = 2.5f; - -PacedSender::PacedSender(PacketRouter* packet_router, - const WebRtcKeyValueConfig* field_trials) - : packet_router_(packet_router), - fallback_field_trials_( - !field_trials ? absl::make_unique() : nullptr), - field_trials_(field_trials ? field_trials : fallback_field_trials_.get()), - min_packet_limit_ms_("", kDefaultMinPacketLimitMs), - paused_(false), - media_budget_(0), - padding_budget_(0), - prober_(*field_trials_), - probing_send_failure_(false), - pacing_bitrate_kbps_(0), - time_last_process_us_(DepLibUV::GetTimeUsInt64()), - first_sent_packet_ms_(-1), - packet_counter_(0), - account_for_audio_(false) { - ParseFieldTrial({&min_packet_limit_ms_}, - webrtc::field_trial::FindFullName("WebRTC-Pacer-MinPacketLimitMs")); - UpdateBudgetWithElapsedTime(min_packet_limit_ms_); -} -void PacedSender::CreateProbeCluster(int bitrate_bps, int cluster_id) { - // TODO: REMOVE - // MS_DEBUG_DEV("---- bitrate_bps:%d, cluster_id:%d", bitrate_bps, cluster_id); +const int PacedSender::kNoPacketHoldback = -1; - prober_.CreateProbeCluster(bitrate_bps, DepLibUV::GetTimeMsInt64(), cluster_id); +PacedSender::BurstyPacerFlags::BurstyPacerFlags( + const WebRtcKeyValueConfig& field_trials) + : burst("burst") { + ParseFieldTrial({&burst}, field_trials.Lookup(kBurstyPacerFieldTrial)); } -void PacedSender::Pause() { - if (!paused_) - MS_DEBUG_DEV("paused"); - - paused_ = true; +PacedSender::SlackedPacerFlags::SlackedPacerFlags( + const WebRtcKeyValueConfig& field_trials) + : allow_low_precision("Enabled"), + max_low_precision_expected_queue_time("max_queue_time"), + send_burst_interval("send_burst_interval") { + ParseFieldTrial({&allow_low_precision, &max_low_precision_expected_queue_time, + &send_burst_interval}, + field_trials.Lookup(kSlackedPacedSenderFieldTrial)); } -void PacedSender::Resume() { - if (paused_) - MS_DEBUG_DEV("resumed"); - - paused_ = false; +PacedSender::PacedSender( + Clock* clock, + PacingController::PacketSender* packet_sender, + const WebRtcKeyValueConfig& field_trials, + TimeDelta max_hold_back_window, + int max_hold_back_window_in_packets) + : clock_(clock), + bursty_pacer_flags_(field_trials), + slacked_pacer_flags_(field_trials), + max_hold_back_window_(slacked_pacer_flags_.allow_low_precision + ? PacingController::kMinSleepTime + : max_hold_back_window), + max_hold_back_window_in_packets_(slacked_pacer_flags_.allow_low_precision + ? 0 + : max_hold_back_window_in_packets), + pacing_controller_(packet_sender, field_trials), + next_process_time_(Timestamp::MinusInfinity()), + is_started_(false), + is_shutdown_(false), + packet_size_(/*alpha=*/0.95), + include_overhead_(false) { + // RTC_DCHECK_GE(max_hold_back_window_, PacingController::kMinSleepTime); + // There are multiple field trials that can affect burst. If multiple bursts + // are specified we pick the largest of the values. + absl::optional burst = bursty_pacer_flags_.burst.GetOptional(); + if (slacked_pacer_flags_.allow_low_precision && + slacked_pacer_flags_.send_burst_interval) { + TimeDelta slacked_burst = slacked_pacer_flags_.send_burst_interval.Value(); + if (!burst.has_value() || burst.value() < slacked_burst) { + burst = slacked_burst; + } + } + if (burst.has_value()) { + pacing_controller_.SetSendBurstInterval(burst.value()); + } } -void PacedSender::SetCongestionWindow(int64_t congestion_window_bytes) { - congestion_window_bytes_ = congestion_window_bytes; +PacedSender::~PacedSender() { + is_shutdown_ = true; } -void PacedSender::UpdateOutstandingData(int64_t outstanding_bytes) { - outstanding_bytes_ = outstanding_bytes; +void PacedSender::EnsureStarted() { + is_started_ = true; + MaybeProcessPackets(Timestamp::MinusInfinity()); } -bool PacedSender::Congested() const { - if (congestion_window_bytes_ == kNoCongestionWindow) - return false; - return outstanding_bytes_ >= congestion_window_bytes_; +void PacedSender::CreateProbeClusters( + std::vector probe_cluster_configs) { + pacing_controller_.CreateProbeClusters(probe_cluster_configs); + MaybeProcessPackets(Timestamp::MinusInfinity()); } -void PacedSender::SetProbingEnabled(bool enabled) { - // RTC_CHECK_EQ(0, packet_counter_); - MS_ASSERT(packet_counter_ == 0, "packet counter must be 0"); - - prober_.SetEnabled(enabled); +void PacedSender::Pause() { + pacing_controller_.Pause(); } -void PacedSender::SetPacingRates(uint32_t pacing_rate_bps, - uint32_t padding_rate_bps) { - // RTC_DCHECK(pacing_rate_bps > 0); - MS_ASSERT(pacing_rate_bps > 0, "pacing rate must be > 0"); - - pacing_bitrate_kbps_ = pacing_rate_bps / 1000; - padding_budget_.set_target_rate_kbps(padding_rate_bps / 1000); - - // TODO: REMOVE - // MS_DEBUG_DEV("[pacer_updated pacing_kbps:%" PRIu32 ", padding_budget_kbps:%" PRIu32 "]", - // pacing_bitrate_kbps_, - // padding_rate_bps / 1000); +void PacedSender::Resume() { + pacing_controller_.Resume(); + MaybeProcessPackets(Timestamp::MinusInfinity()); } -void PacedSender::InsertPacket(size_t bytes) { - // RTC_DCHECK(pacing_bitrate_kbps_ > 0) - // << "SetPacingRate must be called before InsertPacket."; - MS_ASSERT(pacing_bitrate_kbps_ > 0, "SetPacingRates() must be called before InsertPacket()"); - - prober_.OnIncomingPacket(bytes); +void PacedSender::SetCongested(bool congested) { + pacing_controller_.SetCongested(congested); + MaybeProcessPackets(Timestamp::MinusInfinity()); +} - packet_counter_++; +void PacedSender::SetPacingRates(DataRate pacing_rate, + DataRate padding_rate) { + pacing_controller_.SetPacingRates(pacing_rate, padding_rate); + MaybeProcessPackets(Timestamp::MinusInfinity()); +} - // MS_NOTE: Since we don't send media packets within ::Process(), - // we use this callback to acknowledge sent packets. - OnPacketSent(bytes); +void PacedSender::EnqueuePackets( + std::vector> packets) { + for (auto& packet : packets) { + /* TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), + "PacedSender::EnqueuePackets::Loop", + "sequence_number", packet->SequenceNumber(), + "rtp_timestamp", packet->Timestamp());*/ + + size_t packet_size = packet->payload_size() + packet->padding_size(); + if (include_overhead_) { + packet_size += packet->headers_size(); + } + packet_size_.Apply(1, packet_size); + RTC_DCHECK_GE(packet->capture_time(), Timestamp::Zero()); + pacing_controller_.EnqueuePacket(std::move(packet)); + } + MaybeProcessPackets(Timestamp::MinusInfinity()); } void PacedSender::SetAccountForAudioPackets(bool account_for_audio) { - account_for_audio_ = account_for_audio; + pacing_controller_.SetAccountForAudioPackets(account_for_audio); + MaybeProcessPackets(Timestamp::MinusInfinity()); } -int64_t PacedSender::TimeUntilNextProcess() { - int64_t elapsed_time_us = - DepLibUV::GetTimeUsInt64() - time_last_process_us_; - int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000; - // When paused we wake up every 500 ms to send a padding packet to ensure - // we won't get stuck in the paused state due to no feedback being received. - if (paused_) - return std::max(kPausedProcessIntervalMs - elapsed_time_ms, 0); - - if (prober_.IsProbing()) { - int64_t ret = prober_.TimeUntilNextProbe(DepLibUV::GetTimeMsInt64()); - if (ret > 0 || (ret == 0 && !probing_send_failure_)) - return ret; - } - return std::max(min_packet_limit_ms_ - elapsed_time_ms, 0); +void PacedSender::SetIncludeOverhead() { + include_overhead_ = true; + pacing_controller_.SetIncludeOverhead(); + MaybeProcessPackets(Timestamp::MinusInfinity()); } -int64_t PacedSender::UpdateTimeAndGetElapsedMs(int64_t now_us) { - int64_t elapsed_time_ms = (now_us - time_last_process_us_ + 500) / 1000; - time_last_process_us_ = now_us; - if (elapsed_time_ms > kMaxElapsedTimeMs) { - MS_WARN_TAG(bwe, "elapsed time (%" PRIi64 " ms) longer than expected," - " limiting to %" PRIi64 " ms", - elapsed_time_ms, - kMaxElapsedTimeMs); - elapsed_time_ms = kMaxElapsedTimeMs; - } - return elapsed_time_ms; +void PacedSender::SetTransportOverhead(DataSize overhead_per_packet) { + pacing_controller_.SetTransportOverhead(overhead_per_packet); + MaybeProcessPackets(Timestamp::MinusInfinity()); } -void PacedSender::Process() { - int64_t now_us = DepLibUV::GetTimeUsInt64(); - int64_t elapsed_time_ms = UpdateTimeAndGetElapsedMs(now_us); - - if (paused_) - return; - - if (elapsed_time_ms > 0) { - int target_bitrate_kbps = pacing_bitrate_kbps_; - media_budget_.set_target_rate_kbps(target_bitrate_kbps); - UpdateBudgetWithElapsedTime(elapsed_time_ms); - } - - if (!prober_.IsProbing()) - return; +void PacedSender::SetQueueTimeLimit(TimeDelta limit) { + pacing_controller_.SetQueueTimeLimit(limit); + MaybeProcessPackets(Timestamp::MinusInfinity()); +} - PacedPacketInfo pacing_info; - absl::optional recommended_probe_size; +TimeDelta PacedSender::ExpectedQueueTime() const { + return GetStats().expected_queue_time; +} - pacing_info = prober_.CurrentCluster(); - recommended_probe_size = prober_.RecommendedMinProbeSize(); +DataSize PacedSender::QueueSizeData() const { + return GetStats().queue_size; +} - size_t bytes_sent = 0; - // MS_NOTE: Let's not use a useless vector. - RTC::RtpPacket* padding_packet{ nullptr }; +absl::optional PacedSender::FirstSentPacketTime() const { + return GetStats().first_sent_packet_time; +} - // Check if we should send padding. - while (true) - { - size_t padding_bytes_to_add = - PaddingBytesToAdd(recommended_probe_size, bytes_sent); +TimeDelta PacedSender::OldestPacketWaitTime() const { + Timestamp oldest_packet = GetStats().oldest_packet_enqueue_time; + if (oldest_packet.IsInfinite()) { + return TimeDelta::Zero(); + } - if (padding_bytes_to_add == 0) - break; + // (webrtc:9716): The clock is not always monotonic. + Timestamp current = clock_->CurrentTime(); + if (current < oldest_packet) { + return TimeDelta::Zero(); + } - // TODO: REMOVE - // MS_DEBUG_DEV( - // "[recommended_probe_size:%zu, padding_bytes_to_add:%zu]", - // *recommended_probe_size, padding_bytes_to_add); + return current - oldest_packet; +} - padding_packet = - packet_router_->GeneratePadding(padding_bytes_to_add); +void PacedSender::OnStatsUpdated(const Stats& stats) { + current_stats_ = stats; +} - // TODO: REMOVE. - // MS_DEBUG_DEV("sending padding packet [size:%zu]", padding_packet->GetSize()); +void PacedSender::MaybeProcessPackets( + Timestamp scheduled_process_time) { +/* RTC_DCHECK_RUN_ON(&task_queue_); - packet_router_->SendPacket(padding_packet, pacing_info); - bytes_sent += padding_packet->GetSize(); + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webrtc"), + "PacedSender::MaybeProcessPackets");*/ - if (recommended_probe_size && bytes_sent > *recommended_probe_size) - break; + if (is_shutdown_ || !is_started_) { + return; } - if (bytes_sent != 0) - { - auto now = DepLibUV::GetTimeUsInt64(); - - OnPaddingSent(now, bytes_sent); - prober_.ProbeSent((now + 500) / 1000, bytes_sent); + Timestamp next_send_time = pacing_controller_.NextSendTime(); + // RTC_DCHECK(next_send_time.IsFinite()); + const Timestamp now = clock_->CurrentTime(); + TimeDelta early_execute_margin = + pacing_controller_.IsProbing() + ? PacingController::kMaxEarlyProbeProcessing + : TimeDelta::Zero(); + + // Process packets and update stats. + while (next_send_time <= now + early_execute_margin) { + pacing_controller_.ProcessPackets(); + next_send_time = pacing_controller_.NextSendTime(); + // RTC_DCHECK(next_send_time.IsFinite()); + + // Probing state could change. Get margin after process packets. + early_execute_margin = pacing_controller_.IsProbing() + ? PacingController::kMaxEarlyProbeProcessing + : TimeDelta::Zero(); } -} + UpdateStats(); -size_t PacedSender::PaddingBytesToAdd( - absl::optional recommended_probe_size, - size_t bytes_sent) { - - // Don't add padding if congested, even if requested for probing. - if (Congested()) { - return 0; + // Ignore retired scheduled task, otherwise reset `next_process_time_`. + if (scheduled_process_time.IsFinite()) { + if (scheduled_process_time != next_process_time_) { + return; + } + next_process_time_ = Timestamp::MinusInfinity(); } - // MS_NOTE: This does not apply to mediasoup. - // We can not send padding unless a normal packet has first been sent. If we - // do, timestamps get messed up. - // if (packet_counter_ == 0) { - // return 0; - // } - - if (recommended_probe_size) { - if (*recommended_probe_size > bytes_sent) { - return *recommended_probe_size - bytes_sent; + // Do not hold back in probing. + TimeDelta hold_back_window = TimeDelta::Zero(); + if (!pacing_controller_.IsProbing()) { + hold_back_window = max_hold_back_window_; + DataRate pacing_rate = pacing_controller_.pacing_rate(); + if (max_hold_back_window_in_packets_ != kNoPacketHoldback && + !pacing_rate.IsZero() && + packet_size_.filtered() != rtc::ExpFilter::kValueUndefined) { + TimeDelta avg_packet_send_time = + DataSize::Bytes(packet_size_.filtered()) / pacing_rate; + hold_back_window = + std::min(hold_back_window, + avg_packet_send_time * max_hold_back_window_in_packets_); } - return 0; } - return padding_budget_.bytes_remaining(); -} - -void PacedSender::OnPacketSent(size_t size) { - if (first_sent_packet_ms_ == -1) - first_sent_packet_ms_ = DepLibUV::GetTimeMsInt64(); - - // Update media bytes sent. - UpdateBudgetWithBytesSent(size); -} - -PacedPacketInfo PacedSender::GetPacingInfo() { - PacedPacketInfo pacing_info; + // Calculate next process time. + TimeDelta time_to_next_process = + std::max(hold_back_window, next_send_time - now - early_execute_margin); + next_send_time = now + time_to_next_process; + + // If no in flight task or in flight task is later than `next_send_time`, + // schedule a new one. Previous in flight task will be retired. + if (next_process_time_.IsMinusInfinity() || + next_process_time_ > next_send_time) { + // Prefer low precision if allowed and not probing. + TaskQueueBase::DelayPrecision precision = + slacked_pacer_flags_.allow_low_precision && + !pacing_controller_.IsProbing() + ? TaskQueueBase::DelayPrecision::kLow + : TaskQueueBase::DelayPrecision::kHigh; + // Check for cases where we need high precision. + if (precision == TaskQueueBase::DelayPrecision::kLow) { + auto& packets_per_type = + pacing_controller_.SizeInPacketsPerRtpPacketMediaType(); + bool audio_or_retransmission_packets_in_queue = + packets_per_type[static_cast(RtpPacketMediaType::kAudio)] > + 0 || + packets_per_type[static_cast( + RtpPacketMediaType::kRetransmission)] > 0; + bool queue_time_too_large = + slacked_pacer_flags_.max_low_precision_expected_queue_time && + pacing_controller_.ExpectedQueueTime() >= + slacked_pacer_flags_.max_low_precision_expected_queue_time + .Value(); + if (audio_or_retransmission_packets_in_queue || queue_time_too_large) { + precision = TaskQueueBase::DelayPrecision::kHigh; + } + } - if (prober_.IsProbing()) { - pacing_info = prober_.CurrentCluster(); + task_queue_.TaskQueueForDelayedTasks()->PostDelayedTaskWithPrecision( + precision, + task_queue_.MaybeSafeTask( + safety_.flag(), + [this, next_send_time]() { MaybeProcessPackets(next_send_time); }), + time_to_next_process.RoundUpTo(TimeDelta::Millis(1))); + next_process_time_ = next_send_time; } - - return pacing_info; } -void PacedSender::OnPaddingSent(int64_t now, size_t bytes_sent) { - if (bytes_sent > 0) { - UpdateBudgetWithBytesSent(bytes_sent); - } +int64_t PacedSender::TimeUntilNextProcess() { + Timestamp next_send_time = pacing_controller_.NextSendTime(); + TimeDelta sleep_time = + std::max(TimeDelta::Zero(), next_send_time - clock_->CurrentTime()); + if (process_mode_ == PacingController::ProcessMode::kDynamic) { + return std::max(sleep_time, PacingController::kMinSleepTime).ms(); + } + return sleep_time.ms(); +} +void PacedSender::Process() { + pacing_controller_.ProcessPackets(); } -void PacedSender::UpdateBudgetWithElapsedTime(int64_t delta_time_ms) { - delta_time_ms = std::min(kMaxIntervalTimeMs, delta_time_ms); - media_budget_.IncreaseBudget(delta_time_ms); - padding_budget_.IncreaseBudget(delta_time_ms); +void PacedSender::UpdateStats() { + Stats new_stats; + new_stats.expected_queue_time = pacing_controller_.ExpectedQueueTime(); + new_stats.first_sent_packet_time = pacing_controller_.FirstSentPacketTime(); + new_stats.oldest_packet_enqueue_time = + pacing_controller_.OldestPacketEnqueueTime(); + new_stats.queue_size = pacing_controller_.QueueSizeData(); + OnStatsUpdated(new_stats); } -void PacedSender::UpdateBudgetWithBytesSent(size_t bytes_sent) { - outstanding_bytes_ += bytes_sent; - media_budget_.UseBudget(bytes_sent); - padding_budget_.UseBudget(bytes_sent); +PacedSender::Stats PacedSender::GetStats() const { + return current_stats_; } } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h index 4364f3bed4..de741e8b6c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2019 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 @@ -8,127 +8,191 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_PACING_PACED_SENDER_H_ -#define MODULES_PACING_PACED_SENDER_H_ +#ifndef MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ +#define MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ -#include "api/transport/field_trial_based_config.h" -#include "api/transport/network_types.h" -#include "api/transport/webrtc_key_value_config.h" -#include "modules/pacing/bitrate_prober.h" -#include "modules/pacing/interval_budget.h" -#include "modules/pacing/packet_router.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "rtc_base/experiments/field_trial_parser.h" - -#include "RTC/RtpPacket.hpp" - -#include #include #include -#include + #include +#include + +#include "absl/types/optional.h" +//#include "api/field_trials_view.h" +//#include "api/sequence_checker.h" +//#include "api/task_queue/task_queue_factory.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "modules/pacing/pacing_controller.h" +#include "modules/pacing/rtp_packet_pacer.h" +#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" +//#include "modules/utility/maybe_worker_thread.h" +#include "rtc_base/experiments/field_trial_parser.h" +#include "rtc_base/numerics/exp_filter.h" +//#include "rtc_base/thread_annotations.h" namespace webrtc { +class Clock; -class PacedSender { +class PacedSender : public RtpPacketPacer, public RtpPacketSender { public: - static constexpr int64_t kNoCongestionWindow = -1; + static const int kNoPacketHoldback; + + // The `hold_back_window` parameter sets a lower bound on time to sleep if + // there is currently a pacer queue and packets can't immediately be + // processed. Increasing this reduces thread wakeups at the expense of higher + // latency. + PacedSender(Clock* clock, + PacingController::PacketSender* packet_sender, + const WebRtcKeyValueConfig& field_trials, + TimeDelta max_hold_back_window, + int max_hold_back_window_in_packets); + + ~PacedSender() override; - // Pacing-rate relative to our target send rate. - // Multiplicative factor that is applied to the target bitrate to calculate - // the number of bytes that can be transmitted per interval. - // Increasing this factor will result in lower delays in cases of bitrate - // overshoots from the encoder. - static const float kDefaultPaceMultiplier; + // Ensure that necessary delayed tasks are scheduled. + void EnsureStarted(); - PacedSender(PacketRouter* packet_router, - const WebRtcKeyValueConfig* field_trials = nullptr); + // Methods implementing RtpPacketSender. - virtual ~PacedSender() = default; + // Adds the packet to the queue and calls + // PacingController::PacketSender::SendPacket() when it's time to send. + void EnqueuePackets( + std::vector> packets) override; - virtual void CreateProbeCluster(int bitrate_bps, int cluster_id); + // Methods implementing RtpPacketPacer. + + void CreateProbeClusters( + std::vector probe_cluster_configs) override; // Temporarily pause all sending. - void Pause(); + void Pause() override; // Resume sending packets. - void Resume(); - - void SetCongestionWindow(int64_t congestion_window_bytes); - void UpdateOutstandingData(int64_t outstanding_bytes); + void Resume() override; - // Enable bitrate probing. Enabled by default, mostly here to simplify - // testing. Must be called before any packets are being sent to have an - // effect. - void SetProbingEnabled(bool enabled); + void SetCongested(bool congested) override; // Sets the pacing rates. Must be called once before packets can be sent. - void SetPacingRates(uint32_t pacing_rate_bps, uint32_t padding_rate_bps); - - // Adds the packet information to the queue and calls TimeToSendPacket - // when it's time to send. - // MS_NOTE: defined in "modules/rtp_rtcp/include/rtp_packet_sender.h" - void InsertPacket(size_t bytes); + void SetPacingRates(DataRate pacing_rate, DataRate padding_rate) override; - // Currently audio traffic is not accounted by pacer and passed through. - // With the introduction of audio BWE audio traffic will be accounted for - // the pacer budget calculation. The audio traffic still will be injected + // Currently audio traffic is not accounted for by pacer and passed through. + // With the introduction of audio BWE, audio traffic will be accounted for + // in the pacer budget calculation. The audio traffic will still be injected // at high priority. - void SetAccountForAudioPackets(bool account_for_audio); - - // Returns the number of milliseconds until the module want a worker thread - // to call Process. - int64_t TimeUntilNextProcess(); - - // Process any pending packets in the queue(s). - void Process(); - - void OnPacketSent(size_t size); - PacedPacketInfo GetPacingInfo(); + void SetAccountForAudioPackets(bool account_for_audio) override; + + void SetIncludeOverhead() override; + void SetTransportOverhead(DataSize overhead_per_packet) override; + + // Returns the time since the oldest queued packet was enqueued. + TimeDelta OldestPacketWaitTime() const override; + + // Returns total size of all packets in the pacer queue. + DataSize QueueSizeData() const override; + + // Returns the time when the first packet was sent; + absl::optional FirstSentPacketTime() const override; + + // Returns the number of milliseconds it will take to send the current + // packets in the queue, given the current size and bitrate, ignoring prio. + TimeDelta ExpectedQueueTime() const override; + + // Set the max desired queuing delay, pacer will override the pacing rate + // specified by SetPacingRates() if needed to achieve this goal. + void SetQueueTimeLimit(TimeDelta limit) override; + + protected: + // Exposed as protected for test. + struct Stats { + Stats() + : oldest_packet_enqueue_time(Timestamp::MinusInfinity()), + queue_size(DataSize::Zero()), + expected_queue_time(TimeDelta::Zero()) {} + Timestamp oldest_packet_enqueue_time; + DataSize queue_size; + TimeDelta expected_queue_time; + absl::optional first_sent_packet_time; + }; + void OnStatsUpdated(const Stats& stats); private: - int64_t UpdateTimeAndGetElapsedMs(int64_t now_us); - - // Updates the number of bytes that can be sent for the next time interval. - void UpdateBudgetWithElapsedTime(int64_t delta_time_in_ms); - void UpdateBudgetWithBytesSent(size_t bytes); - - size_t PaddingBytesToAdd(absl::optional recommended_probe_size, - size_t bytes_sent); - - void OnPaddingSent(int64_t now_us, size_t bytes_sent); - - bool Congested() const; - - PacketRouter* const packet_router_; - const std::unique_ptr fallback_field_trials_; - const WebRtcKeyValueConfig* field_trials_; - - FieldTrialParameter min_packet_limit_ms_; - - bool paused_; - // This is the media budget, keeping track of how many bits of media - // we can pace out during the current interval. - IntervalBudget media_budget_; - // This is the padding budget, keeping track of how many bits of padding we're - // allowed to send out during the current interval. This budget will be - // utilized when there's no media to send. - IntervalBudget padding_budget_; - - BitrateProber prober_; - bool probing_send_failure_; - - uint32_t pacing_bitrate_kbps_; - - int64_t time_last_process_us_; - int64_t first_sent_packet_ms_; - - uint64_t packet_counter_; - - int64_t congestion_window_bytes_ = kNoCongestionWindow; - int64_t outstanding_bytes_ = 0; - - bool account_for_audio_; + // Check if it is time to send packets, or schedule a delayed task if not. + // Use Timestamp::MinusInfinity() to indicate that this call has _not_ + // been scheduled by the pacing controller. If this is the case, check if + // can execute immediately otherwise schedule a delay task that calls this + // method again with desired (finite) scheduled process time. + void MaybeProcessPackets(Timestamp scheduled_process_time); + + void UpdateStats(); + Stats GetStats() const; + + Clock* const clock_; + struct BurstyPacerFlags { + // Parses `kBurstyPacerFieldTrial`. Example: + // --force-fieldtrials=WebRTC-BurstyPacer/burst:20ms/ + explicit BurstyPacerFlags(const WebRtcKeyValueConfig& field_trials); + // If set, the pacer is allowed to build up a packet "debt" that correspond + // to approximately the send rate during the specified interval. + FieldTrialOptional burst; + }; + const BurstyPacerFlags bursty_pacer_flags_; + struct SlackedPacerFlags { + // Parses `kSlackedPacedSenderFieldTrial`. Example: + // --force-fieldtrials=WebRTC-SlackedPacedSender/Enabled,max_queue_time:75ms/ + explicit SlackedPacerFlags(const WebRtcKeyValueConfig& field_trials); + // When "Enabled", delayed tasks invoking MaybeProcessPackets() are + // scheduled using low precision instead of high precision, resulting in + // less idle wake ups and packets being sent in bursts if the `task_queue_` + // implementation supports slack. When probing, high precision is used + // regardless to ensure good bandwidth estimation. + FieldTrialFlag allow_low_precision; + // Controlled via the "max_queue_time" experiment argument. If set, uses + // high precision scheduling of MaybeProcessPackets() whenever the expected + // queue time is greater than or equal to this value. + FieldTrialOptional max_low_precision_expected_queue_time; + // Controlled via "send_burst_interval" experiment argument. If set, the + // pacer is allowed to build up a packet "debt" that correspond to + // approximately the send rate during the specified interval. + FieldTrialOptional send_burst_interval; + }; + const SlackedPacerFlags slacked_pacer_flags_; + // The holdback window prevents too frequent delayed MaybeProcessPackets() + // calls. These are only applicable if `allow_low_precision` is false. + const TimeDelta max_hold_back_window_; + const int max_hold_back_window_in_packets_; + + PacingController pacing_controller_; + + // We want only one (valid) delayed process task in flight at a time. + // If the value of `next_process_time_` is finite, it is an id for a + // delayed task that will call MaybeProcessPackets() with that time + // as parameter. + // Timestamp::MinusInfinity() indicates no valid pending task. + Timestamp next_process_time_; + + // Indicates if this task queue is started. If not, don't allow + // posting delayed tasks yet. + bool is_started_; + + // Indicates if this task queue is shutting down. If so, don't allow + // posting any more delayed tasks as that can cause the task queue to + // never drain. + bool is_shutdown_; + + // Filtered size of enqueued packets, in bytes. + rtc::ExpFilter packet_size_; + bool include_overhead_; + + // Returns the number of milliseconds until the module want a worker thread + // to call Process. + int64_t TimeUntilNextProcess(); + + // Process any pending packets in the queue(s). + void Process(); + + Stats current_stats_; }; } // namespace webrtc -#endif // MODULES_PACING_PACED_SENDER_H_ +#endif // MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc new file mode 100644 index 0000000000..5471dddf78 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2019 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 "modules/pacing/pacing_controller.h" + +#include +#include +#include +#include + +#include "absl/strings/match.h" +#include "modules/pacing/bitrate_prober.h" +#include "modules/pacing/interval_budget.h" +// #include "rtc_base/checks.h" +#include "DepLibUV.hpp" +#include "rtc_base/experiments/field_trial_parser.h" +// #include "rtc_base/logging.h" +// #include "rtc_base/time_utils.h" +// #include "system_wrappers/include/clock.h" + +namespace webrtc { +namespace { +// Time limit in milliseconds between packet bursts. +constexpr TimeDelta kDefaultMinPacketLimit = TimeDelta::Millis<5>(); +constexpr TimeDelta kCongestedPacketInterval = TimeDelta::Millis<500>(); +// TODO(sprang): Consider dropping this limit. +// The maximum debt level, in terms of time, capped when sending packets. +constexpr TimeDelta kMaxDebtInTime = TimeDelta::Millis<500>(); +constexpr TimeDelta kMaxElapsedTime = TimeDelta::Seconds<2>(); +constexpr TimeDelta kTargetPaddingDuration = TimeDelta::Millis<5>(); + +bool IsDisabled(const WebRtcKeyValueConfig& field_trials, absl::string_view key) { + return absl::StartsWith(field_trials.Lookup(key), "Disabled"); +} + +bool IsEnabled(const WebRtcKeyValueConfig& field_trials, absl::string_view key) { + return absl::StartsWith(field_trials.Lookup(key), "Enabled"); +} + +} // namespace + +const TimeDelta PacingController::kMaxExpectedQueueLength = + TimeDelta::ms(2000); +const TimeDelta PacingController::kPausedProcessInterval = + kCongestedPacketInterval; +const TimeDelta PacingController::kMinSleepTime = TimeDelta::ms(1); +const TimeDelta PacingController::kMaxEarlyProbeProcessing = + TimeDelta::ms(1); + +PacingController::PacingController(PacketSender* packet_sender, + const WebRtcKeyValueConfig& field_trials) + : packet_sender_(packet_sender), + field_trials_(field_trials), + drain_large_queues_( + !IsDisabled(field_trials_, "WebRTC-Pacer-DrainQueue")), + send_padding_if_silent_( + IsEnabled(field_trials_, "WebRTC-Pacer-PadInSilence")), + pace_audio_(IsEnabled(field_trials_, "WebRTC-Pacer-BlockAudio")), + ignore_transport_overhead_( + IsEnabled(field_trials_, "WebRTC-Pacer-IgnoreTransportOverhead")), + fast_retransmissions_( + IsEnabled(field_trials_, "WebRTC-Pacer-FastRetransmissions")), + min_packet_limit_(kDefaultMinPacketLimit), + transport_overhead_per_packet_(DataSize::Zero()), + send_burst_interval_(TimeDelta::Zero()), + last_timestamp_(Timestamp::ms(DepLibUV::GetTimeMsInt64())), + paused_(false), + media_debt_(DataSize::Zero()), + padding_debt_(DataSize::Zero()), + pacing_rate_(DataRate::Zero()), + adjusted_media_rate_(DataRate::Zero()), + padding_rate_(DataRate::Zero()), + prober_(field_trials_), + probing_send_failure_(false), + last_process_time_(Timestamp::ms(DepLibUV::GetTimeMsInt64())), + last_send_time_(last_process_time_), + seen_first_packet_(false), + packet_queue_(/*creation_time=*/last_process_time_), + congested_(false), + queue_time_limit_(kMaxExpectedQueueLength), + account_for_audio_(false), + include_overhead_(false) { + if (!drain_large_queues_) { +/* RTC_LOG(LS_WARNING) << "Pacer queues will not be drained," + "pushback experiment must be enabled.";*/ + } + FieldTrialParameter min_packet_limit_ms("", min_packet_limit_.ms()); + ParseFieldTrial({&min_packet_limit_ms}, + field_trials_.Lookup("WebRTC-Pacer-MinPacketLimitMs")); + min_packet_limit_ = TimeDelta::ms(min_packet_limit_ms.Get()); + UpdateBudgetWithElapsedTime(min_packet_limit_); +} + +PacingController::~PacingController() = default; + +void PacingController::CreateProbeCluster(DataRate bitrate, int cluster_id) { + + ProbeClusterConfig config; + config.at_time = CurrentTime(); + config.target_data_rate = bitrate; + config.target_duration = TimeDelta::ms(15); + config.target_probe_count = 5; + config.id = cluster_id; + + prober_.CreateProbeCluster(config); +} + +void PacingController::CreateProbeClusters( + std::vector probe_cluster_configs) { + for (const ProbeClusterConfig probe_cluster_config : probe_cluster_configs) { + prober_.CreateProbeCluster(probe_cluster_config); + } +} + +void PacingController::Pause() { + if (!paused_) + // RTC_LOG(LS_INFO) << "PacedSender paused."; + paused_ = true; + packet_queue_.SetPauseState(true, CurrentTime()); +} + +void PacingController::Resume() { + if (paused_) + // RTC_LOG(LS_INFO) << "PacedSender resumed."; + paused_ = false; + packet_queue_.SetPauseState(false, CurrentTime()); +} + +bool PacingController::IsPaused() const { + return paused_; +} + +void PacingController::SetCongested(bool congested) { + if (congested_ && !congested) { + UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(CurrentTime())); + } + congested_ = congested; +} + +bool PacingController::IsProbing() const { + return prober_.is_probing(); +} + +Timestamp PacingController::CurrentTime() const { + Timestamp time = Timestamp::ms(DepLibUV::GetTimeMsInt64()); + if (time < last_timestamp_) { +/* RTC_LOG(LS_WARNING) + << "Non-monotonic clock behavior observed. Previous timestamp: " + << last_timestamp_.ms() << ", new timestamp: " << time.ms(); + RTC_DCHECK_GE(time, last_timestamp_);*/ + time = last_timestamp_; + } + last_timestamp_ = time; + return time; +} + +void PacingController::SetProbingEnabled(bool enabled) { + // RTC_CHECK(!seen_first_packet_); + prober_.SetEnabled(enabled); +} + +void PacingController::SetPacingRates(DataRate pacing_rate, + DataRate padding_rate) { + static constexpr DataRate kMaxRate = DataRate::KilobitsPerSec<100000>(); + // RTC_CHECK_GT(pacing_rate, DataRate::Zero()); + // RTC_CHECK_GE(padding_rate, DataRate::Zero()); + if (padding_rate > pacing_rate) { +/* RTC_LOG(LS_WARNING) << "Padding rate " << padding_rate.kbps() + << "kbps is higher than the pacing rate " + << pacing_rate.kbps() << "kbps, capping.";*/ + padding_rate = pacing_rate; + } + + if (pacing_rate > kMaxRate || padding_rate > kMaxRate) { +/* RTC_LOG(LS_WARNING) << "Very high pacing rates ( > " << kMaxRate.kbps() + << " kbps) configured: pacing = " << pacing_rate.kbps() + << " kbps, padding = " << padding_rate.kbps() + << " kbps.";*/ + } + pacing_rate_ = pacing_rate; + padding_rate_ = padding_rate; + MaybeUpdateMediaRateDueToLongQueue(CurrentTime()); + +/* RTC_LOG(LS_VERBOSE) << "bwe:pacer_updated pacing_kbps=" << pacing_rate_.kbps() + << " padding_budget_kbps=" << padding_rate.kbps();*/ +} + +void PacingController::EnqueuePacket(std::unique_ptr packet) { + // RTC_DCHECK(pacing_rate_ > DataRate::Zero()) << "SetPacingRate must be called before InsertPacket."; + // RTC_CHECK(packet->GetPacketType()); + + prober_.OnIncomingPacket(DataSize::bytes(packet->GetPayloadLength())); + + const Timestamp now = CurrentTime(); + if (packet_queue_.Empty()) { + // If queue is empty, we need to "fast-forward" the last process time, + // so that we don't use passed time as budget for sending the first new + // packet. + Timestamp target_process_time = now; + Timestamp next_send_time = NextSendTime(); + if (next_send_time.IsFinite()) { + // There was already a valid planned send time, such as a keep-alive. + // Use that as last process time only if it's prior to now. + target_process_time = std::min(now, next_send_time); + } + UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(target_process_time)); + } + packet_queue_.Push(now, std::move(packet)); + seen_first_packet_ = true; + + // Queue length has increased, check if we need to change the pacing rate. + MaybeUpdateMediaRateDueToLongQueue(now); +} + +void PacingController::SetAccountForAudioPackets(bool account_for_audio) { + account_for_audio_ = account_for_audio; +} + +void PacingController::SetIncludeOverhead() { + include_overhead_ = true; +} + +void PacingController::SetTransportOverhead(DataSize overhead_per_packet) { + if (ignore_transport_overhead_) + return; + transport_overhead_per_packet_ = overhead_per_packet; +} + +void PacingController::SetSendBurstInterval(TimeDelta burst_interval) { + send_burst_interval_ = burst_interval; +} + +TimeDelta PacingController::ExpectedQueueTime() const { + // RTC_DCHECK_GT(adjusted_media_rate_, DataRate::Zero()); + return QueueSizeData() / adjusted_media_rate_; +} + +size_t PacingController::QueueSizePackets() const { + return rtc::checked_cast(packet_queue_.SizeInPackets()); +} + +const std::array& +PacingController::SizeInPacketsPerRtpPacketMediaType() const { + return packet_queue_.SizeInPacketsPerRtpPacketMediaType(); +} + +DataSize PacingController::QueueSizeData() const { + DataSize size = packet_queue_.SizeInPayloadBytes(); + if (include_overhead_) { + size += static_cast(packet_queue_.SizeInPackets()) * + transport_overhead_per_packet_; + } + return size; +} + +DataSize PacingController::CurrentBufferLevel() const { + return std::max(media_debt_, padding_debt_); +} + +absl::optional PacingController::FirstSentPacketTime() const { + return first_sent_packet_time_; +} + +Timestamp PacingController::OldestPacketEnqueueTime() const { + return packet_queue_.OldestEnqueueTime(); +} + +TimeDelta PacingController::UpdateTimeAndGetElapsed(Timestamp now) { + // If no previous processing, or last process was "in the future" because of + // early probe processing, then there is no elapsed time to add budget for. + if (last_process_time_.IsMinusInfinity() || now < last_process_time_) { + return TimeDelta::Zero(); + } + TimeDelta elapsed_time = now - last_process_time_; + last_process_time_ = now; + if (elapsed_time > kMaxElapsedTime) { +/* RTC_LOG(LS_WARNING) << "Elapsed time (" << elapsed_time.ms() + << " ms) longer than expected, limiting to " + << kMaxElapsedTime.ms();*/ + elapsed_time = kMaxElapsedTime; + } + return elapsed_time; +} + +bool PacingController::ShouldSendKeepalive(Timestamp now) const { + if (send_padding_if_silent_ || paused_ || congested_ || !seen_first_packet_) { + // We send a padding packet every 500 ms to ensure we won't get stuck in + // congested state due to no feedback being received. + if (now - last_send_time_ >= kCongestedPacketInterval) { + return true; + } + } + return false; +} + +Timestamp PacingController::NextSendTime() const { + const Timestamp now = CurrentTime(); + Timestamp next_send_time = Timestamp::PlusInfinity(); + + if (paused_) { + return last_send_time_ + kPausedProcessInterval; + } + + // If probing is active, that always takes priority. + if (prober_.is_probing() && !probing_send_failure_) { + Timestamp probe_time = prober_.NextProbeTime(now); + if (!probe_time.IsPlusInfinity()) { + return probe_time.IsMinusInfinity() ? now : probe_time; + } + } + + // If queue contains a packet which should not be paced, its target send time + // is the time at which it was enqueued. + Timestamp unpaced_send_time = NextUnpacedSendTime(); + if (unpaced_send_time.IsFinite()) { + return unpaced_send_time; + } + + if (congested_ || !seen_first_packet_) { + // We need to at least send keep-alive packets with some interval. + return last_send_time_ + kCongestedPacketInterval; + } + + if (adjusted_media_rate_ > DataRate::Zero() && !packet_queue_.Empty()) { + // If packets are allowed to be sent in a burst, the + // debt is allowed to grow up to one packet more than what can be sent + // during 'send_burst_period_'. + TimeDelta drain_time = media_debt_ / adjusted_media_rate_; + next_send_time = + last_process_time_ + + ((send_burst_interval_ > drain_time) ? TimeDelta::Zero() : drain_time); + } else if (padding_rate_ > DataRate::Zero() && packet_queue_.Empty()) { + // If we _don't_ have pending packets, check how long until we have + // bandwidth for padding packets. Both media and padding debts must + // have been drained to do this. + // RTC_DCHECK_GT(adjusted_media_rate_, DataRate::Zero()); + TimeDelta drain_time = std::max(media_debt_ / adjusted_media_rate_, + padding_debt_ / padding_rate_); + + if (drain_time.IsZero() && + (!media_debt_.IsZero() || !padding_debt_.IsZero())) { + // We have a non-zero debt, but drain time is smaller than tick size of + // TimeDelta, round it up to the smallest possible non-zero delta. + drain_time = TimeDelta::Micros<1>(); + } + next_send_time = last_process_time_ + drain_time; + } else { + // Nothing to do. + next_send_time = last_process_time_ + kPausedProcessInterval; + } + + if (send_padding_if_silent_) { + next_send_time = + std::min(next_send_time, last_send_time_ + kPausedProcessInterval); + } + + return next_send_time; +} + +void PacingController::ProcessPackets() { + const Timestamp now = CurrentTime(); + Timestamp target_send_time = now; + + if (ShouldSendKeepalive(now)) { + DataSize keepalive_data_sent = DataSize::Zero(); + // We can not send padding unless a normal packet has first been sent. If + // we do, timestamps get messed up. + if (seen_first_packet_) { + std::vector> keepalive_packets = + packet_sender_->GeneratePadding(DataSize::bytes(1)); + for (auto& packet : keepalive_packets) { + keepalive_data_sent += + DataSize::bytes(packet->GetPayloadLength() + packet->GetPayloadPadding()); + packet_sender_->SendPacket(std::move(packet), PacedPacketInfo()); + for (auto& packet : packet_sender_->FetchFec()) { + EnqueuePacket(std::move(packet)); + } + } + } + OnPacketSent(RtpPacketMediaType::kPadding, keepalive_data_sent, now); + } + + if (paused_) { + return; + } + + TimeDelta early_execute_margin = + prober_.is_probing() ? kMaxEarlyProbeProcessing : TimeDelta::Zero(); + + target_send_time = NextSendTime(); + if (now + early_execute_margin < target_send_time) { + // We are too early, but if queue is empty still allow draining some debt. + // Probing is allowed to be sent up to kMinSleepTime early. + UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(now)); + return; + } + + TimeDelta elapsed_time = UpdateTimeAndGetElapsed(target_send_time); + + if (elapsed_time > TimeDelta::Zero()) { + UpdateBudgetWithElapsedTime(elapsed_time); + } + + PacedPacketInfo pacing_info; + DataSize recommended_probe_size = DataSize::Zero(); + bool is_probing = prober_.is_probing(); + if (is_probing) { + // Probe timing is sensitive, and handled explicitly by BitrateProber, so + // use actual send time rather than target. + pacing_info = prober_.CurrentCluster(now).value_or(PacedPacketInfo()); + if (pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe) { + recommended_probe_size = prober_.RecommendedMinProbeSize(); + // RTC_DCHECK_GT(recommended_probe_size, DataSize::Zero()); + } else { + // No valid probe cluster returned, probe might have timed out. + is_probing = false; + } + } + + DataSize data_sent = DataSize::Zero(); + // Circuit breaker, making sure main loop isn't forever. + static constexpr int kMaxIterations = 1 << 16; + int iteration = 0; + int packets_sent = 0; + int padding_packets_generated = 0; + for (; iteration < kMaxIterations; ++iteration) { + // Fetch packet, so long as queue is not empty or budget is not + // exhausted. + std::unique_ptr rtp_packet = + GetPendingPacket(pacing_info, target_send_time, now); + if (rtp_packet == nullptr) { + // No packet available to send, check if we should send padding. + DataSize padding_to_add = PaddingToAdd(recommended_probe_size, data_sent); + if (padding_to_add > DataSize::Zero()) { + std::vector> padding_packets = + packet_sender_->GeneratePadding(padding_to_add); + if (!padding_packets.empty()) { + padding_packets_generated += padding_packets.size(); + for (auto& packet : padding_packets) { + EnqueuePacket(std::move(packet)); + } + // Continue loop to send the padding that was just added. + continue; + } else { + // Can't generate padding, still update padding budget for next send + // time. + UpdatePaddingBudgetWithSentData(padding_to_add); + } + } + // Can't fetch new packet and no padding to send, exit send loop. + break; + } else { + // RTC_DCHECK(rtp_packet); + // RTC_DCHECK(rtp_packet->packet_type().has_value()); + const RtpPacketMediaType packet_type = rtp_packet->GetPacketType(); + DataSize packet_size = DataSize::bytes(rtp_packet->GetPayloadLength() + + rtp_packet->GetPayloadPadding()); + + if (include_overhead_) { + packet_size += DataSize::bytes(rtp_packet->GetSize() - rtp_packet->GetPayloadLength() - rtp_packet->GetPayloadPadding()) + + transport_overhead_per_packet_; + } + + packet_sender_->SendPacket(std::move(rtp_packet), pacing_info); + for (auto& packet : packet_sender_->FetchFec()) { + EnqueuePacket(std::move(packet)); + } + data_sent += packet_size; + ++packets_sent; + + // Send done, update send time. + OnPacketSent(packet_type, packet_size, now); + + if (is_probing) { + pacing_info.probe_cluster_bytes_sent += packet_size.bytes(); + // If we are currently probing, we need to stop the send loop when we + // have reached the send target. + if (data_sent >= recommended_probe_size) { + break; + } + } + + // Update target send time in case that are more packets that we are late + // in processing. + target_send_time = NextSendTime(); + if (target_send_time > now) { + // Exit loop if not probing. + if (!is_probing) { + break; + } + target_send_time = now; + } + UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(target_send_time)); + } + } + + if (iteration >= kMaxIterations) { + // Circuit break activated. Log warning, adjust send time and return. + // TODO(sprang): Consider completely clearing state. +/* RTC_LOG(LS_ERROR) << "PacingController exceeded max iterations in " + "send-loop: packets sent = " + << packets_sent << ", padding packets generated = " + << padding_packets_generated + << ", bytes sent = " << data_sent.bytes();*/ + last_send_time_ = now; + last_process_time_ = now; + return; + } + + if (is_probing) { + probing_send_failure_ = data_sent == DataSize::Zero(); + if (!probing_send_failure_) { + prober_.ProbeSent(CurrentTime(), data_sent); + } + } + + // Queue length has probably decreased, check if pacing rate needs to updated. + // Poll the time again, since we might have enqueued new fec/padding packets + // with a later timestamp than `now`. + MaybeUpdateMediaRateDueToLongQueue(CurrentTime()); +} + +DataSize PacingController::PaddingToAdd(DataSize recommended_probe_size, + DataSize data_sent) const { + if (!packet_queue_.Empty()) { + // Actual payload available, no need to add padding. + return DataSize::Zero(); + } + + if (congested_) { + // Don't add padding if congested, even if requested for probing. + return DataSize::Zero(); + } + + if (!seen_first_packet_) { + // We can not send padding unless a normal packet has first been sent. If + // we do, timestamps get messed up. + return DataSize::Zero(); + } + + if (!recommended_probe_size.IsZero()) { + if (recommended_probe_size > data_sent) { + return recommended_probe_size - data_sent; + } + return DataSize::Zero(); + } + + if (padding_rate_ > DataRate::Zero() && padding_debt_ == DataSize::Zero()) { + return kTargetPaddingDuration * padding_rate_; + } + return DataSize::Zero(); +} + +std::unique_ptr PacingController::GetPendingPacket( + const PacedPacketInfo& pacing_info, + Timestamp target_send_time, + Timestamp now) { + const bool is_probe = + pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe; + // If first packet in probe, insert a small padding packet so we have a + // more reliable start window for the rate estimation. + if (is_probe && pacing_info.probe_cluster_bytes_sent == 0) { + auto padding = packet_sender_->GeneratePadding(DataSize::bytes(1)); + // If no RTP modules sending media are registered, we may not get a + // padding packet back. + if (!padding.empty()) { + // We should never get more than one padding packets with a requested + // size of 1 byte. + // RTC_DCHECK_EQ(padding.size(), 1u); + return std::move(padding[0]); + } + } + + if (packet_queue_.Empty()) { + return nullptr; + } + + // First, check if there is any reason _not_ to send the next queued packet. + // Unpaced packets and probes are exempted from send checks. + if (NextUnpacedSendTime().IsInfinite() && !is_probe) { + if (congested_) { + // Don't send anything if congested. + return nullptr; + } + + if (now <= target_send_time && send_burst_interval_.IsZero()) { + // We allow sending slightly early if we think that we would actually + // had been able to, had we been right on time - i.e. the current debt + // is not more than would be reduced to zero at the target sent time. + // If we allow packets to be sent in a burst, packet are allowed to be + // sent early. + TimeDelta flush_time = media_debt_ / adjusted_media_rate_; + if (now + flush_time > target_send_time) { + return nullptr; + } + } + } + + return packet_queue_.Pop(); +} + +void PacingController::OnPacketSent(RtpPacketMediaType packet_type, + DataSize packet_size, + Timestamp send_time) { + if (!first_sent_packet_time_ && packet_type != RtpPacketMediaType::kPadding) { + first_sent_packet_time_ = send_time; + } + + bool audio_packet = packet_type == RtpPacketMediaType::kAudio; + if ((!audio_packet || account_for_audio_) && packet_size > DataSize::Zero()) { + UpdateBudgetWithSentData(packet_size); + } + + last_send_time_ = send_time; +} + +void PacingController::UpdateBudgetWithElapsedTime(TimeDelta delta) { + media_debt_ -= std::min(media_debt_, adjusted_media_rate_ * delta); + padding_debt_ -= std::min(padding_debt_, padding_rate_ * delta); +} + +void PacingController::UpdateBudgetWithSentData(DataSize size) { + media_debt_ += size; + media_debt_ = std::min(media_debt_, adjusted_media_rate_ * kMaxDebtInTime); + UpdatePaddingBudgetWithSentData(size); +} + +void PacingController::UpdatePaddingBudgetWithSentData(DataSize size) { + padding_debt_ += size; + padding_debt_ = std::min(padding_debt_, padding_rate_ * kMaxDebtInTime); +} + +void PacingController::SetQueueTimeLimit(TimeDelta limit) { + queue_time_limit_ = limit; +} + +void PacingController::MaybeUpdateMediaRateDueToLongQueue(Timestamp now) { + adjusted_media_rate_ = pacing_rate_; + if (!drain_large_queues_) { + return; + } + + DataSize queue_size_data = QueueSizeData(); + if (queue_size_data > DataSize::Zero()) { + // Assuming equal size packets and input/output rate, the average packet + // has avg_time_left_ms left to get queue_size_bytes out of the queue, if + // time constraint shall be met. Determine bitrate needed for that. + packet_queue_.UpdateAverageQueueTime(now); + TimeDelta avg_time_left = + std::max(TimeDelta::ms(1), + queue_time_limit_ - packet_queue_.AverageQueueTime()); + DataRate min_rate_needed = queue_size_data / avg_time_left; + if (min_rate_needed > pacing_rate_) { + adjusted_media_rate_ = min_rate_needed; + // RTC_LOG(LS_VERBOSE) << "bwe:large_pacing_queue pacing_rate_kbps=" << pacing_rate_.kbps(); + } + } +} + +Timestamp PacingController::NextUnpacedSendTime() const { + if (!pace_audio_) { + Timestamp leading_audio_send_time = + packet_queue_.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio); + if (leading_audio_send_time.IsFinite()) { + return leading_audio_send_time; + } + } + if (fast_retransmissions_) { + Timestamp leading_retransmission_send_time = + packet_queue_.LeadingPacketEnqueueTime( + RtpPacketMediaType::kRetransmission); + if (leading_retransmission_send_time.IsFinite()) { + return leading_retransmission_send_time; + } + } + return Timestamp::MinusInfinity(); +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h new file mode 100644 index 0000000000..e7baaaffdc --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2019 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. + */ + +#ifndef MODULES_PACING_PACING_CONTROLLER_H_ +#define MODULES_PACING_PACING_CONTROLLER_H_ + +#include +#include + +#include +#include +#include +#include + +#include "absl/types/optional.h" +// #include "api/field_trials_view.h" +// #include "api/function_view.h" +#include "api/transport/field_trial_based_config.h" +#include "api/transport/network_types.h" +#include "modules/pacing/bitrate_prober.h" +#include "modules/pacing/interval_budget.h" +#include "modules/pacing/prioritized_packet_queue.h" +#include "modules/pacing/rtp_packet_sender.h" +// #include "modules/pacing/rtp_packet_pacer.h" +// #include "modules/rtp_rtcp/include/rtp_packet_sender.h" +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +//#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" +#include "rtc_base/experiments/field_trial_parser.h" +//#include "rtc_base/thread_annotations.h" + +namespace webrtc { + +// This class implements a leaky-bucket packet pacing algorithm. It handles the +// logic of determining which packets to send when, but the actual timing of +// the processing is done externally (e.g. RtpPacketPacer). Furthermore, the +// forwarding of packets when they are ready to be sent is also handled +// externally, via the PacingController::PacketSender interface. +class PacingController { + public: + class PacketSender: RtpPacketSender { + public: + virtual ~PacketSender() = default; + virtual void SendPacket(std::unique_ptr packet, + const PacedPacketInfo& cluster_info) = 0; + // Should be called after each call to SendPacket(). + virtual std::vector> FetchFec() = 0; + virtual std::vector> GeneratePadding( + DataSize size) = 0; + + // TODO(bugs.webrtc.org/11340): Make pure virtual once downstream projects + // have been updated. + virtual void OnAbortedRetransmissions( + uint32_t ssrc, + std::vector sequence_numbers) {} + virtual absl::optional GetRtxSsrcForMedia(uint32_t ssrc) const { + return absl::nullopt; + } + }; + + // Expected max pacer delay. If ExpectedQueueTime() is higher than + // this value, the packet producers should wait (eg drop frames rather than + // encoding them). Bitrate sent may temporarily exceed target set by + // UpdateBitrate() so that this limit will be upheld. + static const TimeDelta kMaxExpectedQueueLength; + // If no media or paused, wake up at least every `kPausedProcessIntervalMs` in + // order to send a keep-alive packet so we don't get stuck in a bad state due + // to lack of feedback. + static const TimeDelta kPausedProcessInterval; + + static const TimeDelta kMinSleepTime; + + // Allow probes to be processed slightly ahead of inteded send time. Currently + // set to 1ms as this is intended to allow times be rounded down to the + // nearest millisecond. + static const TimeDelta kMaxEarlyProbeProcessing; + + PacingController(PacketSender* packet_sender, + const WebRtcKeyValueConfig& field_trials); + + ~PacingController(); + + // Adds the packet to the queue and calls PacketRouter::SendPacket() when + // it's time to send. + void EnqueuePacket(std::unique_ptr packet); + + // ABSL_DEPRECATED("Use CreateProbeClusters instead") + void CreateProbeCluster(DataRate bitrate, int cluster_id); + void CreateProbeClusters( + std::vector probe_cluster_configs); + + void Pause(); // Temporarily pause all sending. + void Resume(); // Resume sending packets. + bool IsPaused() const; + + void SetCongested(bool congested); + + // Sets the pacing rates. Must be called once before packets can be sent. + void SetPacingRates(DataRate pacing_rate, DataRate padding_rate); + DataRate pacing_rate() const { return adjusted_media_rate_; } + + // Currently audio traffic is not accounted by pacer and passed through. + // With the introduction of audio BWE audio traffic will be accounted for + // the pacer budget calculation. The audio traffic still will be injected + // at high priority. + void SetAccountForAudioPackets(bool account_for_audio); + void SetIncludeOverhead(); + + void SetTransportOverhead(DataSize overhead_per_packet); + // The pacer is allowed to send enqued packets in bursts and can build up a + // packet "debt" that correspond to approximately the send rate during + // 'burst_interval'. + void SetSendBurstInterval(TimeDelta burst_interval); + + // Returns the time when the oldest packet was queued. + Timestamp OldestPacketEnqueueTime() const; + + // Number of packets in the pacer queue. + size_t QueueSizePackets() const; + // Number of packets in the pacer queue per media type (RtpPacketMediaType + // values are used as lookup index). + const std::array& SizeInPacketsPerRtpPacketMediaType() + const; + // Totals size of packets in the pacer queue. + DataSize QueueSizeData() const; + + // Current buffer level, i.e. max of media and padding debt. + DataSize CurrentBufferLevel() const; + + // Returns the time when the first packet was sent. + absl::optional FirstSentPacketTime() const; + + // Returns the number of milliseconds it will take to send the current + // packets in the queue, given the current size and bitrate, ignoring prio. + TimeDelta ExpectedQueueTime() const; + + void SetQueueTimeLimit(TimeDelta limit); + + // Enable bitrate probing. Enabled by default, mostly here to simplify + // testing. Must be called before any packets are being sent to have an + // effect. + void SetProbingEnabled(bool enabled); + + // Returns the next time we expect ProcessPackets() to be called. + Timestamp NextSendTime() const; + + // Check queue of pending packets and send them or padding packets, if budget + // is available. + void ProcessPackets(); + + bool IsProbing() const; + + private: + TimeDelta UpdateTimeAndGetElapsed(Timestamp now); + bool ShouldSendKeepalive(Timestamp now) const; + + // Updates the number of bytes that can be sent for the next time interval. + void UpdateBudgetWithElapsedTime(TimeDelta delta); + void UpdateBudgetWithSentData(DataSize size); + void UpdatePaddingBudgetWithSentData(DataSize size); + + DataSize PaddingToAdd(DataSize recommended_probe_size, + DataSize data_sent) const; + + std::unique_ptr GetPendingPacket( + const PacedPacketInfo& pacing_info, + Timestamp target_send_time, + Timestamp now); + void OnPacketSent(RtpPacketMediaType packet_type, + DataSize packet_size, + Timestamp send_time); + void MaybeUpdateMediaRateDueToLongQueue(Timestamp now); + + Timestamp CurrentTime() const; + + // Helper methods for packet that may not be paced. Returns a finite Timestamp + // if a packet type is configured to not be paced and the packet queue has at + // least one packet of that type. Otherwise returns + // Timestamp::MinusInfinity(). + Timestamp NextUnpacedSendTime() const; + + PacketSender* const packet_sender_; + const WebRtcKeyValueConfig& field_trials_; + + const bool drain_large_queues_; + const bool send_padding_if_silent_; + const bool pace_audio_; + const bool ignore_transport_overhead_; + const bool fast_retransmissions_; + + TimeDelta min_packet_limit_; + DataSize transport_overhead_per_packet_; + TimeDelta send_burst_interval_; + + // TODO(webrtc:9716): Remove this when we are certain clocks are monotonic. + // The last millisecond timestamp returned by `clock_`. + mutable Timestamp last_timestamp_; + bool paused_; + + // Amount of outstanding data for media and padding. + DataSize media_debt_; + DataSize padding_debt_; + + // The target pacing rate, signaled via SetPacingRates(). + DataRate pacing_rate_; + // The media send rate, which might adjusted from pacing_rate_, e.g. if the + // pacing queue is growing too long. + DataRate adjusted_media_rate_; + // The padding target rate. We aim to fill up to this rate with padding what + // is not already used by media. + DataRate padding_rate_; + + BitrateProber prober_; + bool probing_send_failure_; + + Timestamp last_process_time_; + Timestamp last_send_time_; + absl::optional first_sent_packet_time_; + bool seen_first_packet_; + + PrioritizedPacketQueue packet_queue_; + + bool congested_; + + TimeDelta queue_time_limit_; + bool account_for_audio_; + bool include_overhead_; +}; +} // namespace webrtc + +#endif // MODULES_PACING_PACING_CONTROLLER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc new file mode 100644 index 0000000000..2b890b78df --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2022 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 "modules/pacing/prioritized_packet_queue.h" + +#include + +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "RTC/RtpPacket.hpp" +// #include "rtc_base/checks.h" + +namespace webrtc { +namespace { + +constexpr int kAudioPrioLevel = 0; + +int GetPriorityForType(RtpPacketMediaType type) { + // Lower number takes priority over higher. + switch (type) { + case RtpPacketMediaType::kAudio: + // Audio is always prioritized over other packet types. + return kAudioPrioLevel; + case RtpPacketMediaType::kRetransmission: + // Send retransmissions before new media. + return kAudioPrioLevel + 1; + case RtpPacketMediaType::kVideo: + case RtpPacketMediaType::kForwardErrorCorrection: + // Video has "normal" priority, in the old speak. + // Send redundancy concurrently to video. If it is delayed it might have a + // lower chance of being useful. + return kAudioPrioLevel + 2; + case RtpPacketMediaType::kPadding: + // Packets that are in themselves likely useless, only sent to keep the + // BWE high. + return kAudioPrioLevel + 3; + } + // RTC_CHECK_NOTREACHED(); +} + +} // namespace + +DataSize PrioritizedPacketQueue::QueuedPacket::PacketSize() const { + return DataSize::bytes(packet->GetPayloadLength() + packet->GetPayloadPadding()); +} + +PrioritizedPacketQueue::StreamQueue::StreamQueue(Timestamp creation_time) + : last_enqueue_time_(creation_time) {} + +bool PrioritizedPacketQueue::StreamQueue::EnqueuePacket(QueuedPacket packet, + int priority_level) { + bool first_packet_at_level = packets_[priority_level].empty(); + packets_[priority_level].push_back(std::move(packet)); + return first_packet_at_level; +} + +PrioritizedPacketQueue::QueuedPacket +PrioritizedPacketQueue::StreamQueue::DequePacket(int priority_level) { + // RTC_DCHECK(!packets_[priority_level].empty()); + QueuedPacket packet = std::move(packets_[priority_level].front()); + packets_[priority_level].pop_front(); + return packet; +} + +bool PrioritizedPacketQueue::StreamQueue::HasPacketsAtPrio( + int priority_level) const { + return !packets_[priority_level].empty(); +} + +bool PrioritizedPacketQueue::StreamQueue::IsEmpty() const { + for (const std::deque& queue : packets_) { + if (!queue.empty()) { + return false; + } + } + return true; +} + +Timestamp PrioritizedPacketQueue::StreamQueue::LeadingPacketEnqueueTime( + int priority_level) const { + // RTC_DCHECK(!packets_[priority_level].empty()); + return packets_[priority_level].begin()->enqueue_time; +} + +Timestamp PrioritizedPacketQueue::StreamQueue::LastEnqueueTime() const { + return last_enqueue_time_; +} + +PrioritizedPacketQueue::PrioritizedPacketQueue(Timestamp creation_time) + : queue_time_sum_(TimeDelta::Zero()), + pause_time_sum_(TimeDelta::Zero()), + size_packets_(0), + size_packets_per_media_type_({}), + size_payload_(DataSize::Zero()), + last_update_time_(creation_time), + paused_(false), + last_culling_time_(creation_time), + top_active_prio_level_(-1) {} + +void PrioritizedPacketQueue::Push(Timestamp enqueue_time, + std::unique_ptr packet) { + StreamQueue* stream_queue; + auto [it, inserted] = streams_.emplace(packet->GetSsrc(), nullptr); + if (inserted) { + it->second = absl::make_unique(enqueue_time); + } + stream_queue = it->second.get(); + + auto enqueue_time_iterator = + enqueue_times_.insert(enqueue_times_.end(), enqueue_time); + // RTC_DCHECK(packet->packet_type().has_value()); + RtpPacketMediaType packet_type = packet->GetPacketType(); + int prio_level = GetPriorityForType(packet_type); + // RTC_DCHECK_GE(prio_level, 0); + // RTC_DCHECK_LT(prio_level, kNumPriorityLevels); + QueuedPacket queued_packed = {.packet = std::move(packet), + .enqueue_time = enqueue_time, + .enqueue_time_iterator = enqueue_time_iterator}; + // In order to figure out how much time a packet has spent in the queue + // while not in a paused state, we subtract the total amount of time the + // queue has been paused so far, and when the packet is popped we subtract + // the total amount of time the queue has been paused at that moment. This + // way we subtract the total amount of time the packet has spent in the + // queue while in a paused state. + UpdateAverageQueueTime(enqueue_time); + queued_packed.enqueue_time -= pause_time_sum_; + ++size_packets_; + ++size_packets_per_media_type_[static_cast(packet_type)]; + size_payload_ += queued_packed.PacketSize(); + + if (stream_queue->EnqueuePacket(std::move(queued_packed), prio_level)) { + // Number packets at `prio_level` for this steam is now non-zero. + streams_by_prio_[prio_level].push_back(stream_queue); + } + if (top_active_prio_level_ < 0 || prio_level < top_active_prio_level_) { + top_active_prio_level_ = prio_level; + } + + static constexpr TimeDelta kTimeout = TimeDelta::Millis<500>(); + if (enqueue_time - last_culling_time_ > kTimeout) { + for (auto it = streams_.begin(); it != streams_.end();) { + if (it->second->IsEmpty() && + it->second->LastEnqueueTime() + kTimeout < enqueue_time) { + streams_.erase(it++); + } else { + ++it; + } + } + last_culling_time_ = enqueue_time; + } +} + +std::unique_ptr PrioritizedPacketQueue::Pop() { + if (size_packets_ == 0) { + return nullptr; + } + + // RTC_DCHECK_GE(top_active_prio_level_, 0); + StreamQueue& stream_queue = *streams_by_prio_[top_active_prio_level_].front(); + QueuedPacket packet = stream_queue.DequePacket(top_active_prio_level_); + --size_packets_; + //RTC_DCHECK(packet.packet->packet_type().has_value()); + RtpPacketMediaType packet_type = packet.packet->GetPacketType(); + --size_packets_per_media_type_[static_cast(packet_type)]; + // RTC_DCHECK_GE(size_packets_per_media_type_[static_cast(packet_type)], 0); + size_payload_ -= packet.PacketSize(); + + // Calculate the total amount of time spent by this packet in the queue + // while in a non-paused state. Note that the `pause_time_sum_ms_` was + // subtracted from `packet.enqueue_time_ms` when the packet was pushed, and + // by subtracting it now we effectively remove the time spent in in the + // queue while in a paused state. + TimeDelta time_in_non_paused_state = + last_update_time_ - packet.enqueue_time - pause_time_sum_; + queue_time_sum_ -= time_in_non_paused_state; + + // RTC_DCHECK(size_packets_ > 0 || queue_time_sum_ == TimeDelta::Zero()); + + // RTC_CHECK(packet.enqueue_time_iterator != enqueue_times_.end()); + enqueue_times_.erase(packet.enqueue_time_iterator); + + // Remove StreamQueue from head of fifo-queue for this prio level, and + // and add it to the end if it still has packets. + streams_by_prio_[top_active_prio_level_].pop_front(); + if (stream_queue.HasPacketsAtPrio(top_active_prio_level_)) { + streams_by_prio_[top_active_prio_level_].push_back(&stream_queue); + } else if (streams_by_prio_[top_active_prio_level_].empty()) { + // No stream queues have packets at this prio level, find top priority + // that is not empty. + if (size_packets_ == 0) { + top_active_prio_level_ = -1; + } else { + for (int i = 0; i < kNumPriorityLevels; ++i) { + if (!streams_by_prio_[i].empty()) { + top_active_prio_level_ = i; + break; + } + } + } + } + + return std::move(packet.packet); +} + +int PrioritizedPacketQueue::SizeInPackets() const { + return size_packets_; +} + +DataSize PrioritizedPacketQueue::SizeInPayloadBytes() const { + return size_payload_; +} + +bool PrioritizedPacketQueue::Empty() const { + return size_packets_ == 0; +} + +const std::array& +PrioritizedPacketQueue::SizeInPacketsPerRtpPacketMediaType() const { + return size_packets_per_media_type_; +} + +Timestamp PrioritizedPacketQueue::LeadingPacketEnqueueTime( + RtpPacketMediaType type) const { + const int priority_level = GetPriorityForType(type); + if (streams_by_prio_[priority_level].empty()) { + return Timestamp::MinusInfinity(); + } + return streams_by_prio_[priority_level].front()->LeadingPacketEnqueueTime( + priority_level); +} + +Timestamp PrioritizedPacketQueue::OldestEnqueueTime() const { + return enqueue_times_.empty() ? Timestamp::MinusInfinity() + : enqueue_times_.front(); +} + +TimeDelta PrioritizedPacketQueue::AverageQueueTime() const { + if (size_packets_ == 0) { + return TimeDelta::Zero(); + } + return queue_time_sum_ / size_packets_; +} + +void PrioritizedPacketQueue::UpdateAverageQueueTime(Timestamp now) { + // RTC_CHECK_GE(now, last_update_time_); + if (now == last_update_time_) { + return; + } + + TimeDelta delta = now - last_update_time_; + + if (paused_) { + pause_time_sum_ += delta; + } else { + queue_time_sum_ += delta * size_packets_; + } + + last_update_time_ = now; +} + +void PrioritizedPacketQueue::SetPauseState(bool paused, Timestamp now) { + UpdateAverageQueueTime(now); + paused_ = paused; +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h new file mode 100644 index 0000000000..13d1025aef --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2022 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. + */ + +#ifndef MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ +#define MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ + +#include + +#include +#include +#include +#include + +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "RTC/RtpPacket.hpp" +//#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" + +namespace webrtc { + +class PrioritizedPacketQueue { + public: + explicit PrioritizedPacketQueue(Timestamp creation_time); + PrioritizedPacketQueue(const PrioritizedPacketQueue&) = delete; + PrioritizedPacketQueue& operator=(const PrioritizedPacketQueue&) = delete; + + // Add a packet to the queue. The enqueue time is used for queue time stats + // and to report the leading packet enqueue time per packet type. + void Push(Timestamp enqueue_time, std::unique_ptr packet); + + // Remove the next packet from the queue. Packets a prioritized first + // according to packet type, in the following order: + // - audio, retransmissions, video / fec, padding + // For each packet type, we use one FIFO-queue per SSRC and emit from + // those queues in a round-robin fashion. + std::unique_ptr Pop(); + + // Number of packets in the queue. + int SizeInPackets() const; + + // Sum of all payload bytes in the queue, where the payload is calculated + // as `packet->payload_size() + packet->padding_size()`. + DataSize SizeInPayloadBytes() const; + + // Convenience method for `SizeInPackets() == 0`. + bool Empty() const; + + // Total packets in the queue per media type (RtpPacketMediaType values are + // used as lookup index). + const std::array& SizeInPacketsPerRtpPacketMediaType() + const; + + // The enqueue time of the next packet this queue will return via the Pop() + // method, for the given packet type. If queue has no packets, of that type, + // returns Timestamp::MinusInfinity(). + Timestamp LeadingPacketEnqueueTime(RtpPacketMediaType type) const; + + // Enqueue time of the oldest packet in the queue, + // Timestamp::MinusInfinity() if queue is empty. + Timestamp OldestEnqueueTime() const; + + // Average queue time for the packets currently in the queue. + // The queuing time is calculated from Push() to the last UpdateQueueTime() + // call - with any time spent in a paused state subtracted. + // Returns TimeDelta::Zero() for an empty queue. + TimeDelta AverageQueueTime() const; + + // Called during packet processing or when pause stats changes. Since the + // AverageQueueTime() method does not look at the wall time, this method + // needs to be called before querying queue time. + void UpdateAverageQueueTime(Timestamp now); + + // Set the pause state, while `paused` is true queuing time is not counted. + void SetPauseState(bool paused, Timestamp now); + + private: + static constexpr int kNumPriorityLevels = 4; + + class QueuedPacket { + public: + DataSize PacketSize() const; + + std::unique_ptr packet; + Timestamp enqueue_time; + std::list::iterator enqueue_time_iterator; + }; + + // Class containing packets for an RTP stream. + // For each priority level, packets are simply stored in a fifo queue. + class StreamQueue { + public: + explicit StreamQueue(Timestamp creation_time); + StreamQueue(StreamQueue&&) = default; + StreamQueue& operator=(StreamQueue&&) = default; + + StreamQueue(const StreamQueue&) = delete; + StreamQueue& operator=(const StreamQueue&) = delete; + + // Enqueue packet at the given priority level. Returns true if the packet + // count for that priority level went from zero to non-zero. + bool EnqueuePacket(QueuedPacket packet, int priority_level); + + QueuedPacket DequePacket(int priority_level); + + bool HasPacketsAtPrio(int priority_level) const; + bool IsEmpty() const; + Timestamp LeadingPacketEnqueueTime(int priority_level) const; + Timestamp LastEnqueueTime() const; + + private: + std::deque packets_[kNumPriorityLevels]; + Timestamp last_enqueue_time_; + }; + + // Cumulative sum, over all packets, of time spent in the queue. + TimeDelta queue_time_sum_; + // Cumulative sum of time the queue has spent in a paused state. + TimeDelta pause_time_sum_; + // Total number of packets stored in this queue. + int size_packets_; + // Total number of packets stored in this queue per RtpPacketMediaType. + std::array size_packets_per_media_type_; + // Sum of payload sizes for all packts stored in this queue. + DataSize size_payload_; + // The last time queue/pause time sums were updated. + Timestamp last_update_time_; + bool paused_; + + // Last time `streams_` was culled for inactive streams. + Timestamp last_culling_time_; + + // Map from SSRC to packet queues for the associated RTP stream. + std::unordered_map> streams_; + + // For each priority level, a queue of StreamQueues which have at least one + // packet pending for that prio level. + std::deque streams_by_prio_[kNumPriorityLevels]; + + // The first index into `stream_by_prio_` that is non-empty. + int top_active_prio_level_; + + // Ordered list of enqueue times. Additions are always increasing and added to + // the end. QueuedPacket instances have a iterators into this list for fast + // removal. + std::list enqueue_times_; +}; + +} // namespace webrtc + +#endif // MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h new file mode 100644 index 0000000000..4c692b171b --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2019 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. + */ + +#ifndef MODULES_PACING_RTP_PACKET_PACER_H_ +#define MODULES_PACING_RTP_PACKET_PACER_H_ + +#include + +#include + +#include "absl/types/optional.h" +#include "api/units/data_rate.h" +#include "api/units/data_size.h" +#include "api/units/time_delta.h" +#include "api/units/timestamp.h" +#include "modules/pacing/rtp_packet_sender.h" + +namespace webrtc { + +class RtpPacketPacer { + public: + virtual ~RtpPacketPacer() = default; + + virtual void CreateProbeClusters( + std::vector probe_cluster_configs) = 0; + + // Temporarily pause all sending. + virtual void Pause() = 0; + + // Resume sending packets. + virtual void Resume() = 0; + + virtual void SetCongested(bool congested) = 0; + + // Sets the pacing rates. Must be called once before packets can be sent. + virtual void SetPacingRates(DataRate pacing_rate, DataRate padding_rate) = 0; + + // Time since the oldest packet currently in the queue was added. + virtual TimeDelta OldestPacketWaitTime() const = 0; + + // Sum of payload + padding bytes of all packets currently in the pacer queue. + virtual DataSize QueueSizeData() const = 0; + + // Returns the time when the first packet was sent. + virtual absl::optional FirstSentPacketTime() const = 0; + + // Returns the expected number of milliseconds it will take to send the + // current packets in the queue, given the current size and bitrate, ignoring + // priority. + virtual TimeDelta ExpectedQueueTime() const = 0; + + // Set the average upper bound on pacer queuing delay. The pacer may send at + // a higher rate than what was configured via SetPacingRates() in order to + // keep ExpectedQueueTimeMs() below `limit_ms` on average. + virtual void SetQueueTimeLimit(TimeDelta limit) = 0; + + // Currently audio traffic is not accounted by pacer and passed through. + // With the introduction of audio BWE audio traffic will be accounted for + // the pacer budget calculation. The audio traffic still will be injected + // at high priority. + virtual void SetAccountForAudioPackets(bool account_for_audio) = 0; + virtual void SetIncludeOverhead() = 0; + virtual void SetTransportOverhead(DataSize overhead_per_packet) = 0; +}; + +} // namespace webrtc +#endif // MODULES_PACING_RTP_PACKET_PACER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h new file mode 100644 index 0000000000..63036244f0 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019 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. + */ + +#ifndef MODULES_RTP_RTCP_INCLUDE_RTP_PACKET_SENDER_H_ +#define MODULES_RTP_RTCP_INCLUDE_RTP_PACKET_SENDER_H_ + +#include +#include + +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" + +namespace webrtc { + +class RtpPacketSender { + public: + virtual ~RtpPacketSender() = default; + + // Insert a set of packets into queue, for eventual transmission. Based on the + // type of packets, they will be prioritized and scheduled relative to other + // packets and the current target send rate. + virtual void EnqueuePackets( + std::vector> packets) = 0; +}; + +} // namespace webrtc + +#endif // MODULES_RTP_RTCP_INCLUDE_RTP_PACKET_SENDER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 3bc3253376..7e3f0661ec 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -41,6 +41,11 @@ bool IsEnabled(const WebRtcKeyValueConfig& field_trials, return field_trials.Lookup(key).find("Enabled") == 0; } +bool IsNotDisabled(const WebRtcKeyValueConfig& field_trials, + absl::string_view key) { + return field_trials.Lookup(key).find("Disabled") != 1; +} + double ReadBackoffFactor(const WebRtcKeyValueConfig& key_value_config) { std::string experiment_string = key_value_config.Lookup(kBweBackOffFactorExperiment); @@ -74,7 +79,7 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, current_bitrate_(max_configured_bitrate_), latest_estimated_throughput_(current_bitrate_), link_capacity_(), - rate_control_state_(kRcHold), + rate_control_state_(RateControlState::kRcHold), time_last_bitrate_change_(Timestamp::MinusInfinity()), time_last_bitrate_decrease_(Timestamp::MinusInfinity()), time_first_throughput_estimate_(Timestamp::MinusInfinity()), @@ -89,28 +94,28 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, no_bitrate_increase_in_alr_( IsEnabled(*key_value_config, "WebRTC-DontIncreaseDelayBasedBweInAlr")), - smoothing_experiment_(false), estimate_bounded_backoff_( - IsEnabled(*key_value_config, "WebRTC-Bwe-EstimateBoundedBackoff")), - estimate_bounded_increase_( - IsEnabled(*key_value_config, "WebRTC-Bwe-EstimateBoundedIncrease")), + IsNotDisabled(*key_value_config, + "WebRTC-Bwe-EstimateBoundedBackoff")), initial_backoff_interval_("initial_backoff_interval"), - low_throughput_threshold_("low_throughput", DataRate::Zero()), - capacity_deviation_ratio_threshold_("cap_thr", 0.2), - capacity_limit_deviation_factor_("cap_lim", 1) { + link_capacity_fix_("link_capacity_fix") { + ParseFieldTrial( + {&disable_estimate_bounded_increase_, &estimate_bounded_increase_ratio_, + &ignore_throughput_limit_if_network_estimate_, + &ignore_network_estimate_decrease_, &increase_to_network_estimate_}, + key_value_config->Lookup("WebRTC-Bwe-EstimateBoundedIncrease")); // E.g - // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms, - // low_throughput:50kbps/ - ParseFieldTrial({&initial_backoff_interval_, &low_throughput_threshold_}, + // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/ + ParseFieldTrial({&initial_backoff_interval_, &link_capacity_fix_}, key_value_config->Lookup("WebRTC-BweAimdRateControlConfig")); if (initial_backoff_interval_) { MS_DEBUG_TAG(bwe, "Using aimd rate control with initial back-off interval: %s", ToString(*initial_backoff_interval_).c_str()); } - MS_DEBUG_TAG(bwe, "Using aimd rate control with back off factor: %f ", beta_); + /*MS_DEBUG_TAG(bwe, "Using aimd rate control with back off factor: %f ", beta_); ParseFieldTrial( {&capacity_deviation_ratio_threshold_, &capacity_limit_deviation_factor_}, - key_value_config->Lookup("WebRTC-Bwe-AimdRateControl-NetworkState")); + key_value_config->Lookup("WebRTC-Bwe-AimdRateControl-NetworkState"));*/ } AimdRateControl::~AimdRateControl() {} @@ -203,7 +208,7 @@ DataRate AimdRateControl::Update(const RateControlInput* input, } } - current_bitrate_ = ChangeBitrate(current_bitrate_, *input, at_time); + ChangeBitrate(*input, at_time); return current_bitrate_; } @@ -214,7 +219,7 @@ void AimdRateControl::SetInApplicationLimitedRegion(bool in_alr) { void AimdRateControl::SetEstimate(DataRate bitrate, Timestamp at_time) { bitrate_is_initialized_ = true; DataRate prev_bitrate = current_bitrate_; - current_bitrate_ = ClampBitrate(bitrate, bitrate); + current_bitrate_ = ClampBitrate(bitrate); time_last_bitrate_change_ = at_time; if (current_bitrate_ < prev_bitrate) { time_last_bitrate_decrease_ = at_time; @@ -245,23 +250,22 @@ double AimdRateControl::GetNearMaxIncreaseRateBpsPerSecond() const { } TimeDelta AimdRateControl::GetExpectedBandwidthPeriod() const { - const TimeDelta kMinPeriod = - smoothing_experiment_ ? TimeDelta::ms(500) : TimeDelta::seconds(2); + const TimeDelta kMinPeriod = TimeDelta::seconds(2); const TimeDelta kDefaultPeriod = TimeDelta::seconds(3); const TimeDelta kMaxPeriod = TimeDelta::seconds(50); double increase_rate_bps_per_second = GetNearMaxIncreaseRateBpsPerSecond(); if (!last_decrease_) - return smoothing_experiment_ ? kMinPeriod : kDefaultPeriod; + return kDefaultPeriod; double time_to_recover_decrease_seconds = last_decrease_->bps() / increase_rate_bps_per_second; TimeDelta period = TimeDelta::seconds(time_to_recover_decrease_seconds); return period.Clamped(kMinPeriod, kMaxPeriod); } -DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, - const RateControlInput& input, - Timestamp at_time) { +void AimdRateControl::ChangeBitrate(const RateControlInput& input, + Timestamp at_time) { + absl::optional new_bitrate; DataRate estimated_throughput = input.estimated_throughput.value_or(latest_estimated_throughput_); if (input.estimated_throughput) @@ -272,82 +276,87 @@ DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, // we will end up with a valid estimate. if (!bitrate_is_initialized_ && input.bw_state != BandwidthUsage::kBwOverusing) - return current_bitrate_; + return; ChangeState(input, at_time); switch (rate_control_state_) { - case kRcHold: + case RateControlState::kRcHold: break; - case kRcIncrease: + case RateControlState::kRcIncrease: { if (estimated_throughput > link_capacity_.UpperBound()) link_capacity_.Reset(); - // Do not increase the delay based estimate in alr since the estimator - // will not be able to get transport feedback necessary to detect if - // the new estimate is correct. - if (!(send_side_ && in_alr_ && no_bitrate_increase_in_alr_)) { - if (link_capacity_.has_estimate()) { + // We limit the new bitrate based on the troughput to avoid unlimited + // bitrate increases. We allow a bit more lag at very low rates to not too + // easily get stuck if the encoder produces uneven outputs. + DataRate increase_limit = + 1.5 * estimated_throughput + DataRate::kbps(10); + if (ignore_throughput_limit_if_network_estimate_ && network_estimate_ && + network_estimate_->link_capacity_upper.IsFinite()) { + // If we have a Network estimate, we do allow the estimate to increase. + increase_limit = network_estimate_->link_capacity_upper * + estimate_bounded_increase_ratio_.Get(); + } else if (send_side_ && in_alr_ && no_bitrate_increase_in_alr_) { + // Do not increase the delay based estimate in alr since the estimator + // will not be able to get transport feedback necessary to detect if + // the new estimate is correct. + // If we have previously increased above the limit (for instance due to + // probing), we don't allow further changes. + increase_limit = current_bitrate_; + } + + if (current_bitrate_ < increase_limit) { + DataRate increased_bitrate = DataRate::MinusInfinity(); + if (increase_to_network_estimate_ && network_estimate_ && + network_estimate_->link_capacity_upper.IsFinite()) { + increased_bitrate = increase_limit; + } else if (link_capacity_.has_estimate()) { // The link_capacity estimate is reset if the measured throughput // is too far from the estimate. We can therefore assume that our // target rate is reasonably close to link capacity and use additive // increase. DataRate additive_increase = AdditiveRateIncrease(at_time, time_last_bitrate_change_); - new_bitrate += additive_increase; + increased_bitrate = current_bitrate_ + additive_increase; } else { // If we don't have an estimate of the link capacity, use faster ramp // up to discover the capacity. DataRate multiplicative_increase = MultiplicativeRateIncrease( - at_time, time_last_bitrate_change_, new_bitrate); - new_bitrate += multiplicative_increase; + at_time, time_last_bitrate_change_, current_bitrate_); + increased_bitrate = current_bitrate_ + multiplicative_increase; } + new_bitrate = std::min(increased_bitrate, increase_limit); } - time_last_bitrate_change_ = at_time; break; + } - case kRcDecrease: - // TODO(srte): Remove when |estimate_bounded_backoff_| has been validated. - if (network_estimate_ && capacity_deviation_ratio_threshold_ && - !estimate_bounded_backoff_) { - estimated_throughput = std::max(estimated_throughput, - network_estimate_->link_capacity_lower); - } - 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. - new_bitrate = estimated_throughput * beta_; - if (new_bitrate > current_bitrate_) { - // Avoid increasing the rate when over-using. - if (link_capacity_.has_estimate()) { - new_bitrate = beta_ * link_capacity_.estimate(); - } - } - if (estimate_bounded_backoff_ && network_estimate_) { - new_bitrate = std::max( - new_bitrate, network_estimate_->link_capacity_lower * beta_); - } - } else { - new_bitrate = estimated_throughput; + case RateControlState::kRcDecrease: { + DataRate decreased_bitrate = DataRate::PlusInfinity(); + + // Set bit rate to something slightly lower than the measured throughput + // to get rid of any self-induced delay. + decreased_bitrate = estimated_throughput * beta_; + if (decreased_bitrate > current_bitrate_ && !link_capacity_fix_) { + // TODO(terelius): The link_capacity estimate may be based on old + // throughput measurements. Relying on them may lead to unnecessary + // BWE drops. if (link_capacity_.has_estimate()) { - new_bitrate = std::max(new_bitrate, link_capacity_.estimate()); + decreased_bitrate = beta_ * link_capacity_.estimate(); } - new_bitrate = std::min(new_bitrate, low_throughput_threshold_.Get()); } - new_bitrate = std::min(new_bitrate, current_bitrate_); + // Avoid increasing the rate when over-using. + if (decreased_bitrate < current_bitrate_) { + new_bitrate = decreased_bitrate; + } if (bitrate_is_initialized_ && estimated_throughput < current_bitrate_) { - constexpr double kDegradationFactor = 0.9; - if (smoothing_experiment_ && - new_bitrate < kDegradationFactor * beta_ * current_bitrate_) { - // If bitrate decreases more than a normal back off after overuse, it - // indicates a real network degradation. We do not let such a decrease - // to determine the bandwidth estimation period. - last_decrease_ = absl::nullopt; + if (!new_bitrate.has_value()) { + last_decrease_ = DataRate::Zero(); } else { - last_decrease_ = current_bitrate_ - new_bitrate; + last_decrease_ = current_bitrate_ - *new_bitrate; } } if (estimated_throughput < link_capacity_.LowerBound()) { @@ -359,38 +368,34 @@ DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, bitrate_is_initialized_ = true; link_capacity_.OnOveruseDetected(estimated_throughput); // Stay on hold until the pipes are cleared. - rate_control_state_ = kRcHold; + rate_control_state_ = RateControlState::kRcHold; time_last_bitrate_change_ = at_time; time_last_bitrate_decrease_ = at_time; break; - + } default: MS_THROW_ERROR("unknown rate control state"); } - return ClampBitrate(new_bitrate, estimated_throughput); + + current_bitrate_ = ClampBitrate(new_bitrate.value_or(current_bitrate_)); } -DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate, - DataRate estimated_throughput) const { - // Allow the estimate to increase as long as alr is not detected to ensure - // that there is no BWE values that can make the estimate stuck at a too - // low bitrate. If an encoder can not produce the bitrate necessary to - // fully use the capacity, alr will sooner or later trigger. - if (!(send_side_ && no_bitrate_increase_in_alr_)) { - // Don't change the bit rate if the send side is too far off. - // We allow a bit more lag at very low rates to not too easily get stuck if - // the encoder produces uneven outputs. - const DataRate max_bitrate = - 1.5 * estimated_throughput + DataRate::kbps(10); - if (new_bitrate > current_bitrate_ && new_bitrate > max_bitrate) { - new_bitrate = std::max(current_bitrate_, max_bitrate); +DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const { + if (!disable_estimate_bounded_increase_ && network_estimate_ && + network_estimate_->link_capacity_upper.IsFinite()) { + DataRate upper_bound = network_estimate_->link_capacity_upper * + estimate_bounded_increase_ratio_.Get(); + if (ignore_network_estimate_decrease_) { + upper_bound = std::max(upper_bound, current_bitrate_); } + new_bitrate = std::min(upper_bound, new_bitrate); } - - if (network_estimate_ && - (estimate_bounded_increase_ || capacity_limit_deviation_factor_)) { - DataRate upper_bound = network_estimate_->link_capacity_upper; - new_bitrate = std::min(new_bitrate, upper_bound); + if (estimate_bounded_backoff_ && network_estimate_ && + network_estimate_->link_capacity_lower.IsFinite() && + new_bitrate < current_bitrate_) { + new_bitrate = std::min( + current_bitrate_, + std::max(new_bitrate, network_estimate_->link_capacity_lower * beta_)); } new_bitrate = std::max(new_bitrate, min_configured_bitrate_); return new_bitrate; @@ -422,18 +427,18 @@ void AimdRateControl::ChangeState(const RateControlInput& input, Timestamp at_time) { switch (input.bw_state) { case BandwidthUsage::kBwNormal: - if (rate_control_state_ == kRcHold) { + if (rate_control_state_ == RateControlState::kRcHold) { time_last_bitrate_change_ = at_time; - rate_control_state_ = kRcIncrease; + rate_control_state_ = RateControlState::kRcIncrease; } break; case BandwidthUsage::kBwOverusing: - if (rate_control_state_ != kRcDecrease) { - rate_control_state_ = kRcDecrease; + if (rate_control_state_ != RateControlState::kRcDecrease) { + rate_control_state_ = RateControlState::kRcDecrease; } break; case BandwidthUsage::kBwUnderusing: - rate_control_state_ = kRcHold; + rate_control_state_ = RateControlState::kRcHold; break; default: MS_THROW_ERROR("unknown input.bw_state"); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h index cefea2f2a5..6e4ead24a4 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -65,6 +65,8 @@ class AimdRateControl { TimeDelta GetExpectedBandwidthPeriod() const; private: + enum class RateControlState { kRcHold, kRcIncrease, kRcDecrease }; + friend class GoogCcStatePrinter; // Update the target bitrate based on, among other things, the current rate // control state, the current target bitrate and the estimated throughput. @@ -73,14 +75,9 @@ class AimdRateControl { // in the "decrease" state the bitrate will be decreased to slightly below the // current throughput. When in the "hold" state the bitrate will be kept // constant to allow built up queues to drain. - DataRate ChangeBitrate(DataRate current_bitrate, - const RateControlInput& input, - Timestamp at_time); - // Clamps new_bitrate to within the configured min bitrate and a linear - // function of the throughput, so that the new bitrate can't grow too - // large compared to the bitrate actually being received by the other end. - DataRate ClampBitrate(DataRate new_bitrate, - DataRate estimated_throughput) const; + void ChangeBitrate(const RateControlInput& input, Timestamp at_time); + + DataRate ClampBitrate(DataRate new_bitrate) const; DataRate MultiplicativeRateIncrease(Timestamp at_time, Timestamp last_ms, DataRate current_bitrate) const; @@ -107,20 +104,22 @@ class AimdRateControl { // Allow the delay based estimate to only increase as long as application // limited region (alr) is not detected. const bool no_bitrate_increase_in_alr_; - const bool smoothing_experiment_; // Use estimated link capacity lower bound if it is higher than the // acknowledged rate when backing off due to overuse. const bool estimate_bounded_backoff_; - // Use estimated link capacity upper bound as upper limit for increasing - // bitrate over the acknowledged rate. - const bool estimate_bounded_increase_; + // If false, uses estimated link capacity upper bound * + // `estimate_bounded_increase_ratio_` as upper limit for the estimate. + FieldTrialFlag disable_estimate_bounded_increase_{"Disabled"}; + FieldTrialParameter estimate_bounded_increase_ratio_{"ratio", 1.0}; + FieldTrialParameter ignore_throughput_limit_if_network_estimate_{ + "ignore_acked", false}; + FieldTrialParameter increase_to_network_estimate_{"immediate_incr", + false}; + FieldTrialParameter ignore_network_estimate_decrease_{"ignore_decr", + false}; absl::optional last_decrease_; FieldTrialOptional initial_backoff_interval_; - FieldTrialParameter low_throughput_threshold_; - // Deprecated, enable |estimate_bounded_backoff_| instead. - FieldTrialOptional capacity_deviation_ratio_threshold_; - // Deprecated, enable |estimate_bounded_increase_| instead. - FieldTrialOptional capacity_limit_deviation_factor_; + FieldTrialFlag link_capacity_fix_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc index daa9c861d2..fce739060d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc @@ -124,14 +124,7 @@ bool InterArrival::PacketInOrder(uint32_t timestamp) { // that in IsNewerTimestamp() in module_common_types.h. uint32_t timestamp_diff = timestamp - current_timestamp_group_.first_timestamp; - - const static uint32_t int_middle = 0x80000000; - - if (timestamp_diff == int_middle) { - return timestamp > current_timestamp_group_.first_timestamp; - } - - return timestamp_diff < int_middle; + return timestamp_diff < 0x80000000; } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h index 8ce1c145d1..cc1ed08d8f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h @@ -35,6 +35,10 @@ class InterArrival { double timestamp_to_ms_coeff, bool enable_burst_grouping); + InterArrival() = delete; + InterArrival(const InterArrival&) = delete; + InterArrival& operator=(const InterArrival&) = delete; + // This function returns true if a delta was computed, or false if the current // group is still incomplete or if only one group has been completed. // |timestamp| is the timestamp. @@ -87,8 +91,6 @@ class InterArrival { double timestamp_to_ms_coeff_; bool burst_grouping_; int num_consecutive_reordered_packets_; - - RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(InterArrival); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 8d08edf630..40ff2af2b1 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -214,5 +214,16 @@ enum class RtpPacketSendResult { kPacketNotFound // SSRC/sequence number does not map to an available packet. }; +// NOTE! `kNumMediaTypes` must be kept in sync with RtpPacketMediaType! +static constexpr size_t kNumMediaTypes = 5; +enum class RtpPacketMediaType : size_t { + kAudio, // Audio media packets. + kVideo, // Video media packets. + kRetransmission, // Retransmisions, sent as response to NACK. + kForwardErrorCorrection, // FEC packets. + kPadding = kNumMediaTypes - 1, // RTX or plain padding sent to maintain BWE. + // Again, don't forget to udate `kNumMediaTypes` if you add another value! +}; + } // namespace webrtc #endif // MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc new file mode 100644 index 0000000000..bd6e69bbed --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016 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 "rtc_base/rate_limiter.h" + +#include + +#include "DepLibUV.hpp" +#include "absl/types/optional.h" +// #include "system_wrappers/include/clock.h" + +namespace webrtc { + +RateLimiter::RateLimiter(Clock* clock, int64_t max_window_ms) + : current_rate_(max_window_ms, RateStatistics::kBpsScale), + window_size_ms_(max_window_ms), + max_rate_bps_(std::numeric_limits::max()) {} + +RateLimiter::~RateLimiter() {} + +// Usage note: This class is intended be usable in a scenario where different +// threads may call each of the the different method. For instance, a network +// thread trying to send data calling TryUseRate(), the bandwidth estimator +// calling SetMaxRate() and a timed maintenance thread periodically updating +// the RTT. +bool RateLimiter::TryUseRate(size_t packet_size_bytes) { + //MutexLock lock(&lock_); + int64_t now_ms = DepLibUV::GetTimeMsInt64(); + absl::optional current_rate = current_rate_.Rate(now_ms); + if (current_rate) { + // If there is a current rate, check if adding bytes would cause maximum + // bitrate target to be exceeded. If there is NOT a valid current rate, + // allow allocating rate even if target is exceeded. This prevents + // problems + // at very low rates, where for instance retransmissions would never be + // allowed due to too high bitrate caused by a single packet. + + size_t bitrate_addition_bps = + (packet_size_bytes * 8 * 1000) / window_size_ms_; + if (*current_rate + bitrate_addition_bps > max_rate_bps_) + return false; + } + + current_rate_.Update(packet_size_bytes, now_ms); + return true; +} + +void RateLimiter::SetMaxRate(uint32_t max_rate_bps) { + // MutexLock lock(&lock_); + max_rate_bps_ = max_rate_bps; +} + +// Set the window size over which to measure the current bitrate. +// For retransmissions, this is typically the RTT. +bool RateLimiter::SetWindowSize(int64_t window_size_ms) { + // MutexLock lock(&lock_); + window_size_ms_ = window_size_ms; + return current_rate_.SetWindowSize(window_size_ms, + DepLibUV::GetTimeMsInt64()); +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h new file mode 100644 index 0000000000..e27657b01b --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2016 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. + */ + +#ifndef RTC_BASE_RATE_LIMITER_H_ +#define RTC_BASE_RATE_LIMITER_H_ + +#include +#include + +#include "rtc_base/rate_statistics.h" + +namespace webrtc { + +class Clock; + +// Class used to limit a bitrate, making sure the average does not exceed a +// maximum as measured over a sliding window. This class is thread safe; all +// methods will acquire (the same) lock befeore executing. +class RateLimiter { + public: + RateLimiter(Clock* clock, int64_t max_window_ms); + + RateLimiter() = delete; + RateLimiter(const RateLimiter&) = delete; + RateLimiter& operator=(const RateLimiter&) = delete; + + ~RateLimiter(); + + // Try to use rate to send bytes. Returns true on success and if so updates + // current rate. + bool TryUseRate(size_t packet_size_bytes); + + // Set the maximum bitrate, in bps, that this limiter allows to send. + void SetMaxRate(uint32_t max_rate_bps); + + // Set the window size over which to measure the current bitrate. + // For example, irt retransmissions, this is typically the RTT. + // Returns true on success and false if window_size_ms is out of range. + bool SetWindowSize(int64_t window_size_ms); + + private: + RateStatistics current_rate_; + int64_t window_size_ms_; + uint32_t max_rate_bps_; +}; + +} // namespace webrtc + +#endif // RTC_BASE_RATE_LIMITER_H_ diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 610646fd9f..69d8256aeb 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -8,6 +8,7 @@ libwebrtc_sources = [ 'libwebrtc/rtc_base/experiments/rate_control_settings.cc', 'libwebrtc/rtc_base/experiments/struct_parameters_parser.cc', 'libwebrtc/rtc_base/network/sent_packet.cc', + 'libwebrtc/rtc_base/rate_limiter.cc', 'libwebrtc/call/rtp_transport_controller_send.cc', 'libwebrtc/api/transport/bitrate_settings.cc', 'libwebrtc/api/transport/field_trial_based_config.cc', @@ -21,6 +22,8 @@ libwebrtc_sources = [ 'libwebrtc/api/network_state_predictor.cc', 'libwebrtc/modules/pacing/interval_budget.cc', 'libwebrtc/modules/pacing/bitrate_prober.cc', + 'libwebrtc/modules/pacing/pacing_controller.cc', + 'libwebrtc/modules/pacing/prioritized_packet_queue.cc', 'libwebrtc/modules/pacing/paced_sender.cc', 'libwebrtc/modules/remote_bitrate_estimator/overuse_detector.cc', 'libwebrtc/modules/remote_bitrate_estimator/overuse_estimator.cc', @@ -38,7 +41,6 @@ libwebrtc_sources = [ 'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc', 'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc', - 'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc', diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 0dece98d5b..2e0d1f48de 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -4,6 +4,8 @@ #include "common.hpp" #include "Utils.hpp" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" +// FIXME: temp just to compile +#include "libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include #include #include @@ -153,6 +155,10 @@ namespace RTC { return (const uint8_t*)this->header; } + // FIXME: temp just to compile + const webrtc::RtpPacketMediaType GetPacketType() const { + return webrtc::RtpPacketMediaType::kAudio; + } size_t GetSize() const { From fe738e3d39cc7186e3e1a1ff79a44e17ab1d858a Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 14 Nov 2022 16:51:33 +0200 Subject: [PATCH 04/70] Revert "First failed attempt to backport Pacer, save to preserve." This reverts commit f01bd515731520378b26cff0352fb24ccbd4ced2. --- worker/deps/libwebrtc/libwebrtc.gyp | 2 +- .../libwebrtc/api/bitrate_constraints.h | 41 ++ .../api/transport/bitrate_settings.h | 18 +- .../libwebrtc/api/transport/network_types.h | 10 +- .../call/rtp_transport_controller_send.cc | 158 ++-- .../call/rtp_transport_controller_send.h | 43 +- .../rtp_transport_controller_send_interface.h | 8 +- .../congestion_window_pushback_controller.cc | 14 +- .../goog_cc/median_slope_estimator.cc | 88 +++ .../goog_cc/median_slope_estimator.h | 72 ++ .../goog_cc/probe_bitrate_estimator.cc | 5 + .../goog_cc/probe_bitrate_estimator.h | 3 + .../goog_cc/trendline_estimator.h | 2 + .../modules/pacing/bitrate_prober.cc | 162 +++-- .../libwebrtc/modules/pacing/bitrate_prober.h | 50 +- .../libwebrtc/modules/pacing/paced_sender.cc | 461 ++++++------ .../libwebrtc/modules/pacing/paced_sender.h | 264 +++---- .../modules/pacing/pacing_controller.cc | 686 ------------------ .../modules/pacing/pacing_controller.h | 237 ------ .../pacing/prioritized_packet_queue.cc | 272 ------- .../modules/pacing/prioritized_packet_queue.h | 159 ---- .../modules/pacing/rtp_packet_pacer.h | 74 -- .../modules/pacing/rtp_packet_sender.h | 34 - .../aimd_rate_control.cc | 193 +++-- .../aimd_rate_control.h | 33 +- .../remote_bitrate_estimator/inter_arrival.cc | 9 +- .../remote_bitrate_estimator/inter_arrival.h | 6 +- .../rtp_rtcp/include/rtp_rtcp_defines.h | 11 - .../libwebrtc/rtc_base/rate_limiter.cc | 69 -- .../libwebrtc/rtc_base/rate_limiter.h | 56 -- worker/deps/libwebrtc/meson.build | 4 +- worker/include/RTC/RtpPacket.hpp | 6 - 32 files changed, 838 insertions(+), 2412 deletions(-) create mode 100644 worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc create mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h delete mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc delete mode 100644 worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h diff --git a/worker/deps/libwebrtc/libwebrtc.gyp b/worker/deps/libwebrtc/libwebrtc.gyp index 6d469fbaac..bc786cf165 100644 --- a/worker/deps/libwebrtc/libwebrtc.gyp +++ b/worker/deps/libwebrtc/libwebrtc.gyp @@ -85,7 +85,7 @@ 'libwebrtc/api/transport/network_control.h', 'libwebrtc/api/transport/field_trial_based_config.h', 'libwebrtc/api/transport/goog_cc_factory.h', - 'libwebrtc/api/transport/bitrate_settings.cc', + 'libwebrtc/api/bitrate_constraints.h', 'libwebrtc/api/units/frequency.h', 'libwebrtc/api/units/data_size.h', 'libwebrtc/api/units/time_delta.h', diff --git a/worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h b/worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h new file mode 100644 index 0000000000..98e89c0858 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/api/bitrate_constraints.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018 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. + */ + +#ifndef API_BITRATE_CONSTRAINTS_H_ +#define API_BITRATE_CONSTRAINTS_H_ + +#include + +namespace webrtc { +// TODO(srte): BitrateConstraints and BitrateSettings should be merged. +// Both represent the same kind data, but are using different default +// initializer and representation of unset values. +struct BitrateConstraints { + int min_bitrate_bps = 0; + int start_bitrate_bps = kDefaultStartBitrateBps; + int max_bitrate_bps = -1; + + private: + static constexpr int kDefaultStartBitrateBps = 300000; +}; + +// Like std::min, but considers non-positive values to be unset. +template +static T MinPositive(T a, T b) { + if (a <= 0) { + return b; + } + if (b <= 0) { + return a; + } + return std::min(a, b); +} +} // namespace webrtc +#endif // API_BITRATE_CONSTRAINTS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h b/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h index cc7e548966..7a09c2e839 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/bitrate_settings.h @@ -11,13 +11,11 @@ #ifndef API_TRANSPORT_BITRATE_SETTINGS_H_ #define API_TRANSPORT_BITRATE_SETTINGS_H_ -#include - -#include "absl/types/optional.h" +#include namespace webrtc { -// Configuration of send bitrate. The `start_bitrate_bps` value is +// Configuration of send bitrate. The |start_bitrate_bps| value is // used for multiple purposes, both as a prior in the bandwidth // estimator, and for initial configuration of the encoder. We may // want to create separate apis for those, and use a smaller struct @@ -32,18 +30,6 @@ struct BitrateSettings { absl::optional max_bitrate_bps; }; -// TODO(srte): BitrateConstraints and BitrateSettings should be merged. -// Both represent the same kind data, but are using different default -// initializer and representation of unset values. -struct BitrateConstraints { - int min_bitrate_bps = 0; - int start_bitrate_bps = kDefaultStartBitrateBps; - int max_bitrate_bps = -1; - - private: - static constexpr int kDefaultStartBitrateBps = 300000; -}; - } // namespace webrtc #endif // API_TRANSPORT_BITRATE_SETTINGS_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index 0cef4b4cf8..bd76166aa9 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -210,11 +210,11 @@ struct PacerConfig { }; struct ProbeClusterConfig { - Timestamp at_time = Timestamp::PlusInfinity(); - DataRate target_data_rate = DataRate::Zero(); - TimeDelta target_duration = TimeDelta::Zero(); - int32_t target_probe_count = 0; - int32_t id = 0; + Timestamp at_time = Timestamp::PlusInfinity(); + DataRate target_data_rate = DataRate::Zero(); + TimeDelta target_duration = TimeDelta::Zero(); + int32_t target_probe_count = 0; + int32_t id = 0; }; struct TargetTransferRate { diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc index 3bd7a3db14..f99aaa2846 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc @@ -30,11 +30,8 @@ namespace webrtc { namespace { -static const int64_t kRetransmitWindowSizeMs = 500; static const size_t kMaxOverheadBytes = 500; -constexpr TimeDelta kPacerQueueUpdateInterval = TimeDelta::Millis<25>(); - TargetRateConstraints ConvertConstraints(int min_bitrate_bps, int max_bitrate_bps, int start_bitrate_bps) { @@ -54,33 +51,15 @@ TargetRateConstraints ConvertConstraints(const BitrateConstraints& contraints) { contraints.max_bitrate_bps, contraints.start_bitrate_bps); } - -bool IsEnabled(const WebRtcKeyValueConfig& trials, absl::string_view key) { - return absl::StartsWith(trials.Lookup(key), "Enabled"); -} - -bool IsDisabled(const WebRtcKeyValueConfig& trials, absl::string_view key) { - return absl::StartsWith(trials.Lookup(key), "Disabled"); -} - } // namespace -RtpTransportControllerSend::PacerSettings::PacerSettings( - const WebRtcKeyValueConfig& trials) - : holdback_window("holdback_window", TimeDelta::ms(5)), - holdback_packets("holdback_packets", 3) { - ParseFieldTrial({&holdback_window, &holdback_packets}, - trials.Lookup("WebRTC-TaskQueuePacer")); -} - RtpTransportControllerSend::RtpTransportControllerSend( PacketRouter* packet_router, NetworkStatePredictorFactoryInterface* predictor_factory, NetworkControllerFactoryInterface* controller_factory, - const BitrateConstraints& bitrate_config, - const WebRtcKeyValueConfig& trials) + const BitrateConstraints& bitrate_config) : packet_router_(packet_router), - pacer_(packet_router_, trials), + pacer_(packet_router_), observer_(nullptr), controller_factory_override_(controller_factory), process_interval_(controller_factory_override_->GetProcessInterval()), @@ -95,7 +74,7 @@ RtpTransportControllerSend::RtpTransportControllerSend( // RTC_DCHECK(bitrate_config.start_bitrate_bps > 0); MS_ASSERT(bitrate_config.start_bitrate_bps > 0, "start bitrate must be > 0"); - pacer_.SetPacingRates(DataRate::bps(bitrate_config.start_bitrate_bps), DataRate::bps(0)); + pacer_.SetPacingRates(bitrate_config.start_bitrate_bps, 0); } RtpTransportControllerSend::~RtpTransportControllerSend() { @@ -105,7 +84,7 @@ void RtpTransportControllerSend::UpdateControlState() { absl::optional update = control_handler_->GetUpdate(); if (!update) return; - retransmission_rate_limiter_.SetMaxRate(update->target_rate.bps()); + // We won't create control_handler_ until we have an observers. // RTC_DCHECK(observer_ != nullptr); MS_ASSERT(observer_ != nullptr, "no observer"); @@ -113,31 +92,22 @@ void RtpTransportControllerSend::UpdateControlState() { observer_->OnTargetTransferRate(*update); } -void RtpTransportControllerSend::UpdateCongestedState() { - bool congested = transport_feedback_adapter_.GetOutstandingData() >= - congestion_window_size_; - if (congested != is_congested_) { - is_congested_ = congested; - pacer_.SetCongested(congested); - } -} - PacketRouter* RtpTransportControllerSend::packet_router() { return this->packet_router_; } NetworkStateEstimateObserver* RtpTransportControllerSend::network_state_estimate_observer() { - return this->network_state_estimate_observer(); + return this; } TransportFeedbackObserver* RtpTransportControllerSend::transport_feedback_observer() { - return this->transport_feedback_observer(); + return this; } -RtpPacketSender* RtpTransportControllerSend::packet_sender() { - return &this->pacer_; +PacedSender* RtpTransportControllerSend::packet_sender() { + return &pacer_; } void RtpTransportControllerSend::SetAllocatedSendBitrateLimits( @@ -161,9 +131,6 @@ void RtpTransportControllerSend::SetPacingFactor(float pacing_factor) { streams_config_.pacing_factor = pacing_factor; UpdateStreamsConfig(); } -/*void RtpTransportControllerSend::SetQueueTimeLimit(int limit_ms) { - pacer_.SetQueueTimeLimit(TimeDelta::ms(limit_ms)); -}*/ void RtpTransportControllerSend::RegisterTargetTransferRateObserver( TargetTransferRateObserver* observer) { @@ -191,17 +158,16 @@ void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) { } else { pacer_.Pause(); } - is_congested_ = false; - pacer_.SetCongested(false); + pacer_.UpdateOutstandingData(0); control_handler_->SetNetworkAvailability(network_available_); PostUpdates(controller_->OnNetworkAvailability(msg)); UpdateControlState(); } -/*RtcpBandwidthObserver* RtpTransportControllerSend::GetBandwidthObserver() { +RtcpBandwidthObserver* RtpTransportControllerSend::GetBandwidthObserver() { return this; -}*/ +} void RtpTransportControllerSend::EnablePeriodicAlrProbing(bool enable) { streams_config_.requests_alr_probing = enable; @@ -209,55 +175,17 @@ void RtpTransportControllerSend::EnablePeriodicAlrProbing(bool enable) { } void RtpTransportControllerSend::OnSentPacket( - const rtc::SentPacket& sent_packet, size_t size) -{ - MS_DEBUG_DEV("<<<<< size:%zu", size); - - absl::optional packet_msg = transport_feedback_adapter_.ProcessSentPacket(sent_packet); - if (packet_msg) - { - // Only update outstanding data if: - // 1. Packet feadback is used. - // 2. The packet has not yet received an acknowledgement. - // 3. It is not a retransmission of an earlier packet. - UpdateCongestedState(); - if (controller_) - PostUpdates(controller_->OnSentPacket(*packet_msg)); - } -} + const rtc::SentPacket& sent_packet, size_t size) { + MS_DEBUG_DEV("<<<<< size:%zu", size); -void RtpTransportControllerSend::UpdateBitrateConstraints( - const BitrateConstraints& updated) { - TargetRateConstraints msg = ConvertConstraints(updated); - PostUpdates(controller_->OnTargetRateConstraints(msg)); - }; - -/*void RtpTransportControllerSend::SetSdpBitrateParameters( - const BitrateConstraints& constraints) { - absl::optional updated = - bitrate_configurator_.UpdateWithSdpParameters(constraints); - if (updated.has_value()) { - UpdateBitrateConstraints(*updated); - } else { - RTC_LOG(LS_VERBOSE) - << "WebRTC.RtpTransportControllerSend.SetSdpBitrateParameters: " - "nothing to update"; - } + absl::optional packet_msg = + transport_feedback_adapter_.ProcessSentPacket(sent_packet); + if (packet_msg) + PostUpdates(controller_->OnSentPacket(*packet_msg)); + pacer_.UpdateOutstandingData( + transport_feedback_adapter_.GetOutstandingData().bytes()); } -void RtpTransportControllerSend::SetClientBitratePreferences( - const BitrateSettings& preferences) { - absl::optional updated = - bitrate_configurator_.UpdateWithClientPreferences(preferences); - if (updated.has_value()) { - UpdateBitrateConstraints(*updated); - } else { - RTC_LOG(LS_VERBOSE) - << "WebRTC.RtpTransportControllerSend.SetClientBitratePreferences: " - "nothing to update"; - } -}*/ - void RtpTransportControllerSend::OnTransportOverheadChanged( size_t transport_overhead_bytes_per_packet) { MS_DEBUG_DEV("<<<<< transport_overhead_bytes_per_packet:%zu", transport_overhead_bytes_per_packet); @@ -266,9 +194,6 @@ void RtpTransportControllerSend::OnTransportOverheadChanged( MS_ERROR("transport overhead exceeds: %zu", kMaxOverheadBytes); return; } - - pacer_.SetTransportOverhead( - DataSize::bytes(transport_overhead_bytes_per_packet)); } void RtpTransportControllerSend::OnReceivedEstimatedBitrate(uint32_t bitrate) { @@ -301,7 +226,7 @@ void RtpTransportControllerSend::OnAddPacket( const RtpPacketSendInfo& packet_info) { transport_feedback_adapter_.AddPacket( packet_info, - send_side_bwe_with_overhead_ ? transport_overhead_bytes_per_packet_ + send_side_bwe_with_overhead_ ? transport_overhead_bytes_per_packet_.load() : 0, Timestamp::ms(DepLibUV::GetTimeMsInt64())); } @@ -315,14 +240,14 @@ void RtpTransportControllerSend::OnTransportFeedback( feedback, Timestamp::ms(DepLibUV::GetTimeMsInt64())); if (feedback_msg) PostUpdates(controller_->OnTransportPacketsFeedback(*feedback_msg)); - - UpdateCongestedState(); + pacer_.UpdateOutstandingData( + transport_feedback_adapter_.GetOutstandingData().bytes()); } void RtpTransportControllerSend::OnRemoteNetworkEstimate( NetworkStateEstimate estimate) { estimate.update_time = Timestamp::ms(DepLibUV::GetTimeMsInt64()); - PostUpdates(controller_->OnNetworkStateEstimate(estimate)); + controller_->OnNetworkStateEstimate(estimate); } void RtpTransportControllerSend::Process() @@ -372,21 +297,28 @@ void RtpTransportControllerSend::UpdateStreamsConfig() { } void RtpTransportControllerSend::PostUpdates(NetworkControlUpdate update) { - if (update.congestion_window) { - congestion_window_size_ = *update.congestion_window; - UpdateCongestedState(); - } - if (update.pacer_config) { - pacer_.SetPacingRates(update.pacer_config->data_rate(), - update.pacer_config->pad_rate()); - } - if (!update.probe_cluster_configs.empty()) { - pacer_.CreateProbeClusters(update.probe_cluster_configs); - } - if (update.target_rate) { - control_handler_->SetTargetRate(*update.target_rate); - UpdateControlState(); - } + if (update.congestion_window) { + if (update.congestion_window->IsFinite()) + pacer_.SetCongestionWindow(update.congestion_window->bytes()); + else + pacer_.SetCongestionWindow(PacedSender::kNoCongestionWindow); + } + if (update.pacer_config) { + pacer_.SetPacingRates(update.pacer_config->data_rate().bps(), + update.pacer_config->pad_rate().bps()); + } + + // TODO: REMOVE: this removes any probation. + // update.probe_cluster_configs.clear(); + + for (const auto& probe : update.probe_cluster_configs) { + int64_t bitrate_bps = probe.target_data_rate.bps(); + pacer_.CreateProbeCluster(bitrate_bps, probe.id); + } + if (update.target_rate) { + control_handler_->SetTargetRate(*update.target_rate); + UpdateControlState(); + } } void RtpTransportControllerSend::OnReceivedRtcpReceiverReportBlocks( diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h index 6a1bb53db4..7ffc321717 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h @@ -18,11 +18,9 @@ #include "call/rtp_transport_controller_send_interface.h" #include "modules/congestion_controller/rtp/control_handler.h" #include "modules/congestion_controller/rtp/transport_feedback_adapter.h" -#include "modules/pacing/paced_sender.h" -#include "modules/pacing/pacing_controller.h" -#include "modules/pacing/packet_router.h" #include "rtc_base/constructor_magic.h" -#include "rtc_base/rate_limiter.h" +#include "modules/pacing/packet_router.h" +#include "modules/pacing/paced_sender.h" #include #include @@ -45,19 +43,14 @@ class RtpTransportControllerSend final PacketRouter* packet_router, NetworkStatePredictorFactoryInterface* predictor_factory, NetworkControllerFactoryInterface* controller_factory, - const BitrateConstraints& bitrate_config, - const WebRtcKeyValueConfig& trials); + const BitrateConstraints& bitrate_config); ~RtpTransportControllerSend() override; - RtpTransportControllerSend(const RtpTransportControllerSend&) = delete; - RtpTransportControllerSend& operator=(const RtpTransportControllerSend&) = - delete; - PacketRouter* packet_router() override; NetworkStateEstimateObserver* network_state_estimate_observer() override; TransportFeedbackObserver* transport_feedback_observer() override; - RtpPacketSender* packet_sender() override; + PacedSender* packet_sender() override; void SetAllocatedSendBitrateLimits(int min_send_bitrate_bps, int max_padding_bitrate_bps, @@ -74,7 +67,7 @@ class RtpTransportControllerSend final void OnSentPacket(const rtc::SentPacket& sent_packet, size_t size) override; void OnTransportOverheadChanged( - size_t transport_overhead_bytes_per_packet) override; + size_t transport_overhead_per_packet) override; // Implements RtcpBandwidthObserver interface void OnReceivedEstimatedBitrate(uint32_t bitrate) override; @@ -92,24 +85,15 @@ class RtpTransportControllerSend final void Process(); private: - struct PacerSettings { - explicit PacerSettings(const WebRtcKeyValueConfig& trials); + void MaybeCreateControllers(); - FieldTrialParameter holdback_window; - FieldTrialParameter holdback_packets; - }; - - void MaybeCreateControllers(); void UpdateControllerWithTimeInterval(); - void UpdateBitrateConstraints(const BitrateConstraints& updated); void UpdateStreamsConfig(); void OnReceivedRtcpReceiverReportBlocks(const ReportBlockList& report_blocks, int64_t now_ms); - void PostUpdates(NetworkControlUpdate update); void UpdateControlState(); - void UpdateCongestedState(); const FieldTrialBasedConfig trial_based_config_; @@ -139,20 +123,15 @@ class RtpTransportControllerSend final // const bool add_pacing_to_cwin_; // Transport overhead is written by OnNetworkRouteChanged and read by // AddPacket. + // TODO(srte): Remove atomic when feedback adapter runs on task queue. + std::atomic transport_overhead_bytes_per_packet_; - size_t transport_overhead_bytes_per_packet_; bool network_available_; - DataSize congestion_window_size_; - bool is_congested_; - - // Protected by internal locks. - RateLimiter retransmission_rate_limiter_; - - // TODO(perkj): `task_queue_` is supposed to replace `process_thread_`. - // `task_queue_` is defined last to ensure all pending tasks are cancelled + // TODO(perkj): |task_queue_| is supposed to replace |process_thread_|. + // |task_queue_| is defined last to ensure all pending tasks are cancelled // and deleted before any other members. - const WebRtcKeyValueConfig& field_trials_; + RTC_DISALLOW_COPY_AND_ASSIGN(RtpTransportControllerSend); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h index b5eb2e3548..1575f45b78 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h @@ -11,6 +11,7 @@ #ifndef CALL_RTP_TRANSPORT_CONTROLLER_SEND_INTERFACE_H_ #define CALL_RTP_TRANSPORT_CONTROLLER_SEND_INTERFACE_H_ +#include "api/bitrate_constraints.h" #include "api/transport/bitrate_settings.h" // #include "call/rtp_config.h" // #include "modules/rtp_rtcp/include/report_block_data.h" @@ -18,14 +19,13 @@ #include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" // #include "modules/rtp_rtcp/source/rtp_packet_received.h" -#include "modules/pacing/pacing_controller.h" #include "RTC/RtpPacket.hpp" #include -#include -#include #include #include +#include +#include #include #include @@ -76,7 +76,7 @@ class RtpTransportControllerSendInterface { virtual NetworkStateEstimateObserver* network_state_estimate_observer() = 0; virtual TransportFeedbackObserver* transport_feedback_observer() = 0; - virtual PacingController* packet_sender() = 0; + virtual PacedSender* packet_sender() = 0; // SetAllocatedSendBitrateLimits sets bitrates limits imposed by send codec // settings. diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc index a43cc9bd8b..53b9bd4c96 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc @@ -25,10 +25,7 @@ CongestionWindowPushbackController::CongestionWindowPushbackController( .find("Enabled") == 0), min_pushback_target_bitrate_bps_( RateControlSettings::ParseFromKeyValueConfig(key_value_config) - .CongestionWindowMinPushbackTargetBitrateBps()), - current_data_window_( - RateControlSettings::ParseFromKeyValueConfig(key_value_config) - .CongestionWindowInitialDataWindow()) {} + .CongestionWindowMinPushbackTargetBitrateBps()) {} CongestionWindowPushbackController::CongestionWindowPushbackController( const WebRtcKeyValueConfig* key_value_config, @@ -47,6 +44,15 @@ void CongestionWindowPushbackController::UpdatePacingQueue( pacing_bytes_ = pacing_bytes; } +void CongestionWindowPushbackController::UpdateMaxOutstandingData( + size_t max_outstanding_bytes) { + DataSize data_window = DataSize::bytes(max_outstanding_bytes); + if (current_data_window_) { + data_window = (data_window + current_data_window_.value()) / 2; + } + current_data_window_ = data_window; +} + void CongestionWindowPushbackController::SetDataWindow(DataSize data_window) { current_data_window_ = data_window; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc new file mode 100644 index 0000000000..07648b9751 --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2016 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 "modules/congestion_controller/goog_cc/median_slope_estimator.h" + +#include + +namespace webrtc { + +constexpr unsigned int kDeltaCounterMax = 1000; + +MedianSlopeEstimator::MedianSlopeEstimator(size_t window_size, + double threshold_gain) + : window_size_(window_size), + threshold_gain_(threshold_gain), + num_of_deltas_(0), + accumulated_delay_(0), + delay_hist_(), + median_filter_(0.5), + trendline_(0) {} + +MedianSlopeEstimator::~MedianSlopeEstimator() {} + +MedianSlopeEstimator::DelayInfo::DelayInfo(int64_t time, + double delay, + size_t slope_count) + : time(time), delay(delay) { + slopes.reserve(slope_count); +} + +MedianSlopeEstimator::DelayInfo::~DelayInfo() = default; + +void MedianSlopeEstimator::Update(double recv_delta_ms, + double send_delta_ms, + int64_t arrival_time_ms) { + const double delta_ms = recv_delta_ms - send_delta_ms; + ++num_of_deltas_; + if (num_of_deltas_ > kDeltaCounterMax) + num_of_deltas_ = kDeltaCounterMax; + + accumulated_delay_ += delta_ms; + // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, + // accumulated_delay_); + + // If the window is full, remove the |window_size_| - 1 slopes that belong to + // the oldest point. + if (delay_hist_.size() == window_size_) { + // for (double slope : delay_hist_.front().slopes) { + // const bool success = median_filter_.Erase(slope); + // RTC_CHECK(success); + // } + delay_hist_.pop_front(); + } + // Add |window_size_| - 1 new slopes. + for (auto& old_delay : delay_hist_) { + if (arrival_time_ms - old_delay.time != 0) { + // The C99 standard explicitly states that casts and assignments must + // perform the associated conversions. This means that |slope| will be + // a 64-bit double even if the division is computed using, e.g., 80-bit + // extended precision. I believe this also holds in C++ even though the + // C++11 standard isn't as explicit. Furthermore, there are good reasons + // to believe that compilers couldn't perform optimizations that break + // this assumption even if they wanted to. + double slope = (accumulated_delay_ - old_delay.delay) / + static_cast(arrival_time_ms - old_delay.time); + median_filter_.Insert(slope); + // We want to avoid issues with different rounding mode / precision + // which we might get if we recomputed the slope when we remove it. + old_delay.slopes.push_back(slope); + } + } + delay_hist_.emplace_back(arrival_time_ms, accumulated_delay_, + window_size_ - 1); + // Recompute the median slope. + if (delay_hist_.size() == window_size_) + trendline_ = median_filter_.GetPercentileValue(); + + // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trendline_); +} + +} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h new file mode 100644 index 0000000000..674a82829a --- /dev/null +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2016 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. + */ +#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ +#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ + +#include "rtc_base/constructor_magic.h" +#include "rtc_base/numerics/percentile_filter.h" + +#include +#include +#include +#include + +namespace webrtc { + +class MedianSlopeEstimator { + public: + // |window_size| is the number of points required to compute a trend line. + // |threshold_gain| is used to scale the trendline slope for comparison to + // the old threshold. Once the old estimator has been removed (or the + // thresholds been merged into the estimators), we can just set the + // threshold instead of setting a gain. + MedianSlopeEstimator(size_t window_size, double threshold_gain); + ~MedianSlopeEstimator(); + + // Update the estimator with a new sample. The deltas should represent deltas + // between timestamp groups as defined by the InterArrival class. + void Update(double recv_delta_ms, + double send_delta_ms, + int64_t arrival_time_ms); + + // Returns the estimated trend k multiplied by some gain. + // 0 < k < 1 -> the delay increases, queues are filling up + // k == 0 -> the delay does not change + // k < 0 -> the delay decreases, queues are being emptied + double trendline_slope() const { return trendline_ * threshold_gain_; } + + // Returns the number of deltas which the current estimator state is based on. + unsigned int num_of_deltas() const { return num_of_deltas_; } + + private: + struct DelayInfo { + DelayInfo(int64_t time, double delay, size_t slope_count); + ~DelayInfo(); + int64_t time; + double delay; + std::vector slopes; + }; + // Parameters. + const size_t window_size_; + const double threshold_gain_; + // Used by the existing threshold. + unsigned int num_of_deltas_; + // Theil-Sen robust line fitting + double accumulated_delay_; + std::deque delay_hist_; + PercentileFilter median_filter_; + double trendline_; + + RTC_DISALLOW_COPY_AND_ASSIGN(MedianSlopeEstimator); +}; + +} // namespace webrtc + +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc index 3e24dcdcd4..6022dbdd99 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc @@ -200,6 +200,7 @@ absl::optional ProbeBitrateEstimator::HandleProbeAndEstimateBitrate( //RTC_DCHECK_GT(send_rate, receive_rate); res = kTargetUtilizationFraction * receive_rate; } + last_estimate_ = res; estimated_data_rate_ = res; return res; } @@ -211,6 +212,10 @@ ProbeBitrateEstimator::FetchAndResetLastEstimatedBitrate() { return estimated_data_rate; } +absl::optional ProbeBitrateEstimator::last_estimate() const { + return last_estimate_; +} + void ProbeBitrateEstimator::EraseOldClusters(Timestamp timestamp) { for (auto it = clusters_.begin(); it != clusters_.end();) { if (it->second.last_receive + kMaxClusterHistory < timestamp) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h index d826cbc08d..b3eb21c7b0 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.h @@ -33,6 +33,8 @@ class ProbeBitrateEstimator { absl::optional FetchAndResetLastEstimatedBitrate(); + absl::optional last_estimate() const; + private: struct AggregatedCluster { int num_probes = 0; @@ -50,6 +52,7 @@ class ProbeBitrateEstimator { std::map clusters_; absl::optional estimated_data_rate_; + absl::optional last_estimate_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index a7fef47fc0..6ae5b263bd 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -60,6 +60,8 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { // threshold instead of setting a gain.|network_state_predictor| is used to // bettter predict network state. TrendlineEstimator(size_t window_size, + double smoothing_coef, + double threshold_gain, NetworkStatePredictor* network_state_predictor); ~TrendlineEstimator() override; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc index 4779009bb2..1d3ce9806f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.cc @@ -42,16 +42,26 @@ namespace webrtc { namespace { -constexpr TimeDelta kProbeClusterTimeout = TimeDelta::Seconds<5>(); +// The min probe packet size is scaled with the bitrate we're probing at. +// This defines the max min probe packet size, meaning that on high bitrates +// we have a min probe packet size of 200 bytes. +constexpr size_t kMinProbePacketSize = 200; + +constexpr int64_t kProbeClusterTimeoutMs = 5000; } // namespace BitrateProberConfig::BitrateProberConfig( const WebRtcKeyValueConfig* key_value_config) - : min_probe_delta("min_probe_delta", TimeDelta::Millis<2>()), - max_probe_delay("max_probe_delay", TimeDelta::Millis<10>()), - min_packet_size("min_packet_size", DataSize::Bytes<200>()) { - ParseFieldTrial({&min_probe_delta, &max_probe_delay, &min_packet_size}, + : min_probe_packets_sent("min_probe_packets_sent", 5), + min_probe_delta("min_probe_delta", TimeDelta::ms(1)), + min_probe_duration("min_probe_duration", TimeDelta::ms(15)), + max_probe_delay("max_probe_delay", TimeDelta::ms(3)) { + ParseFieldTrial({&min_probe_packets_sent, &min_probe_delta, + &min_probe_duration, &max_probe_delay}, + key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); + ParseFieldTrial({&min_probe_packets_sent, &min_probe_delta, + &min_probe_duration, &max_probe_delay}, key_value_config->Lookup("WebRTC-Bwe-ProbingBehavior")); } @@ -64,7 +74,7 @@ BitrateProber::~BitrateProber() { BitrateProber::BitrateProber(const WebRtcKeyValueConfig& field_trials) : probing_state_(ProbingState::kDisabled), - next_probe_time_(Timestamp::PlusInfinity()), + next_probe_time_ms_(-1), total_probe_count_(0), total_failed_probe_count_(0), config_(&field_trials) { @@ -89,16 +99,18 @@ void BitrateProber::SetEnabled(bool enable) { TODO_PRINT_PROBING_STATE(); } -void BitrateProber::OnIncomingPacket(DataSize packet_size) { +bool BitrateProber::IsProbing() const { + return probing_state_ == ProbingState::kActive; +} + +void BitrateProber::OnIncomingPacket(size_t packet_size) { // Don't initialize probing unless we have something large enough to start // probing. - // Note that the pacer can send several packets at once when sending a probe, - // and thus, packets can be smaller than needed for a probe. if (probing_state_ == ProbingState::kInactive && !clusters_.empty() && packet_size >= - std::min(RecommendedMinProbeSize(), config_.min_packet_size.Get())) { + std::min(RecommendedMinProbeSize(), kMinProbePacketSize)) { // Send next probe right away. - next_probe_time_ = Timestamp::MinusInfinity(); + next_probe_time_ms_ = -1; probing_state_ = ProbingState::kActive; } @@ -106,32 +118,33 @@ void BitrateProber::OnIncomingPacket(DataSize packet_size) { TODO_PRINT_PROBING_STATE(); } -void BitrateProber::CreateProbeCluster(const ProbeClusterConfig& cluster_config) { +void BitrateProber::CreateProbeCluster(int bitrate_bps, + int64_t now_ms, + int cluster_id) { // RTC_DCHECK(probing_state_ != ProbingState::kDisabled); // RTC_DCHECK_GT(bitrate_bps, 0); MS_ASSERT(probing_state_ != ProbingState::kDisabled, "probing disabled"); - MS_ASSERT(cluster_config.target_data_rate.bps() > 0, "bitrate must be > 0"); + MS_ASSERT(bitrate_bps > 0, "bitrate must be > 0"); total_probe_count_++; while (!clusters_.empty() && - cluster_config.at_time - clusters_.front().requested_at > - kProbeClusterTimeout) { + now_ms - clusters_.front().time_created_ms > kProbeClusterTimeoutMs) { clusters_.pop(); total_failed_probe_count_++; } ProbeCluster cluster; - cluster.requested_at = cluster_config.at_time; - cluster.pace_info.probe_cluster_min_probes = - cluster_config.target_probe_count; + cluster.time_created_ms = now_ms; + cluster.pace_info.probe_cluster_min_probes = config_.min_probe_packets_sent; cluster.pace_info.probe_cluster_min_bytes = - (cluster_config.target_data_rate * cluster_config.target_duration) - .bytes(); + static_cast(static_cast(bitrate_bps) * + config_.min_probe_duration->ms() / 8000); + // RTC_DCHECK_GE(cluster.pace_info.probe_cluster_min_bytes, 0); + MS_ASSERT(cluster.pace_info.probe_cluster_min_bytes >= 0, "cluster min bytes must be >= 0"); - MS_ASSERT(cluster.pace_info.probe_cluster_min_bytes >= 0, "cluster min bytes must be >= 0"); - cluster.pace_info.send_bitrate_bps = cluster_config.target_data_rate.bps(); - cluster.pace_info.probe_cluster_id = cluster_config.id; + cluster.pace_info.send_bitrate_bps = bitrate_bps; + cluster.pace_info.probe_cluster_id = cluster_id; clusters_.push(cluster); MS_DEBUG_DEV("probe cluster [bitrate:%d, min bytes:%d, min probes:%d]", @@ -146,73 +159,75 @@ void BitrateProber::CreateProbeCluster(const ProbeClusterConfig& cluster_config) // TODO (ibc): We need to send probation even if there is no real packets, so add // this code (taken from `OnIncomingPacket()` above) also here. -/* if (probing_state_ == ProbingState::kInactive && !clusters_.empty()) { + if (probing_state_ == ProbingState::kInactive && !clusters_.empty()) { // Send next probe right away. next_probe_time_ms_ = -1; probing_state_ = ProbingState::kActive; - }*/ + } // TODO: jeje TODO_PRINT_PROBING_STATE(); } -Timestamp BitrateProber::NextProbeTime(Timestamp now) const { - // TODO: jeje - TODO_PRINT_PROBING_STATE(); +int BitrateProber::TimeUntilNextProbe(int64_t now_ms) { + // TODO: jeje + TODO_PRINT_PROBING_STATE(); + // Probing is not active or probing is already complete. - if (probing_state_ != ProbingState::kActive || clusters_.empty()) { - return Timestamp::PlusInfinity(); + if (probing_state_ != ProbingState::kActive || clusters_.empty()) + return -1; + + int time_until_probe_ms = 0; + if (next_probe_time_ms_ >= 0) { + time_until_probe_ms = next_probe_time_ms_ - now_ms; + if (time_until_probe_ms < -config_.max_probe_delay->ms()) { + MS_WARN_TAG(bwe, "probe delay too high [next_ms:%" PRIi64 ", now_ms:%" PRIi64 "]", + next_probe_time_ms_, + now_ms); + return -1; + } } - return next_probe_time_; + return std::max(time_until_probe_ms, 0); } -absl::optional BitrateProber::CurrentCluster(Timestamp now) { - if (clusters_.empty() || probing_state_ != ProbingState::kActive) { - return absl::nullopt; - } - - if (next_probe_time_.IsFinite() && - now - next_probe_time_ > config_.max_probe_delay.Get()) { - MS_WARN_TAG(bwe, "probe delay too high [next_ms:%" PRIi64 ", now_ms:%" PRIi64 "], discarding probe cluster.", - next_probe_time_.ms(), - now.ms()); - clusters_.pop(); - if (clusters_.empty()) { - probing_state_ = ProbingState::kSuspended; - return absl::nullopt; - } - } +PacedPacketInfo BitrateProber::CurrentCluster() const { + // RTC_DCHECK(!clusters_.empty()); + // RTC_DCHECK(probing_state_ == ProbingState::kActive); + MS_ASSERT(!clusters_.empty(), "clusters is empty"); + MS_ASSERT(probing_state_ == ProbingState::kActive, "probing not active"); - PacedPacketInfo info = clusters_.front().pace_info; - info.probe_cluster_bytes_sent = clusters_.front().sent_bytes; - return info; + return clusters_.front().pace_info; } -DataSize BitrateProber::RecommendedMinProbeSize() const { - if (clusters_.empty()) { - return DataSize::Zero(); - } - DataRate send_rate = - DataRate::bps(clusters_.front().pace_info.send_bitrate_bps); - return send_rate * config_.min_probe_delta; +// Probe size is recommended based on the probe bitrate required. We choose +// a minimum of twice |kMinProbeDeltaMs| interval to allow scheduling to be +// feasible. +size_t BitrateProber::RecommendedMinProbeSize() const { + // RTC_DCHECK(!clusters_.empty()); + MS_ASSERT(!clusters_.empty(), "clusters is empty"); + + return clusters_.front().pace_info.send_bitrate_bps * 2 * + config_.min_probe_delta->ms() / (8 * 1000); } -void BitrateProber::ProbeSent(Timestamp now, DataSize size) { +void BitrateProber::ProbeSent(int64_t now_ms, size_t bytes) { // RTC_DCHECK(probing_state_ == ProbingState::kActive); - // RTC_DCHECK(!size.IsZero()); + // RTC_DCHECK_GT(bytes, 0); + MS_ASSERT(probing_state_ == ProbingState::kActive, "probing not active"); + MS_ASSERT(bytes > 0, "bytes must be > 0"); if (!clusters_.empty()) { ProbeCluster* cluster = &clusters_.front(); if (cluster->sent_probes == 0) { - // RTC_DCHECK(cluster->started_at.IsInfinite()); + // RTC_DCHECK_EQ(cluster->time_started_ms, -1); + MS_ASSERT(cluster->time_started_ms == -1, "cluster started time must not be -1"); - MS_ASSERT(cluster->started_at.IsInfinite(), "cluster started time must not be -1"); - cluster->started_at = now; + cluster->time_started_ms = now_ms; } - cluster->sent_bytes += size.bytes(); + cluster->sent_bytes += static_cast(bytes); cluster->sent_probes += 1; - next_probe_time_ = CalculateNextProbeTime(*cluster); + next_probe_time_ms_ = GetNextProbeTime(*cluster); if (cluster->sent_bytes >= cluster->pace_info.probe_cluster_min_bytes && cluster->sent_probes >= cluster->pace_info.probe_cluster_min_probes) { // RTC_HISTOGRAM_COUNTS_100000("WebRTC.BWE.Probing.ProbeClusterSizeInBytes", @@ -232,21 +247,18 @@ void BitrateProber::ProbeSent(Timestamp now, DataSize size) { } } -Timestamp BitrateProber::CalculateNextProbeTime( - const ProbeCluster& cluster) const { +int64_t BitrateProber::GetNextProbeTime(const ProbeCluster& cluster) { // RTC_CHECK_GT(cluster.pace_info.send_bitrate_bps, 0); - // RTC_CHECK(cluster.started_at.IsFinite()); - MS_ASSERT(cluster.pace_info.send_bitrate_bps > 0, "cluster.pace_info.send_bitrate_bps must be > 0"); - MS_ASSERT(cluster.started_at.IsFinite(), "cluster.time_started_ms must be > 0"); + // RTC_CHECK_GE(cluster.time_started_ms, 0); + MS_ASSERT(cluster.pace_info.send_bitrate_bps > 0, "cluster.pace_info.send_bitrate_bps must be > 0"); + MS_ASSERT(cluster.time_started_ms > 0, "cluster.time_started_ms must be > 0"); // Compute the time delta from the cluster start to ensure probe bitrate stays // close to the target bitrate. Result is in milliseconds. - DataSize sent_bytes = DataSize::bytes(cluster.sent_bytes); - DataRate send_bitrate = - DataRate::bps(cluster.pace_info.send_bitrate_bps); - - TimeDelta delta = sent_bytes / send_bitrate; - return cluster.started_at + delta; + int64_t delta_ms = + (8000ll * cluster.sent_bytes + cluster.pace_info.send_bitrate_bps / 2) / + cluster.pace_info.send_bitrate_bps; + return cluster.time_started_ms + delta_ms; } } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h index 4fc128999b..ed42c531d8 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/bitrate_prober.h @@ -27,15 +27,15 @@ struct BitrateProberConfig { BitrateProberConfig& operator=(const BitrateProberConfig&) = default; ~BitrateProberConfig() = default; + // The minimum number probing packets used. + FieldTrialParameter min_probe_packets_sent; // A minimum interval between probes to allow scheduling to be feasible. FieldTrialParameter min_probe_delta; - // Maximum amount of time each probe can be delayed. + // The minimum probing duration. + FieldTrialParameter min_probe_duration; + // Maximum amount of time each probe can be delayed. Probe cluster is reset + // and retried from the start when this limit is reached. FieldTrialParameter max_probe_delay; - // This is used to start sending a probe after a large enough packet. - // The min packet size is scaled with the bitrate we're probing at. - // This defines the max min packet size, meaning that on high bitrates - // a packet of at least this size is needed to trigger sending a probe. - FieldTrialParameter min_packet_size; }; // Note that this class isn't thread-safe by itself and therefore relies @@ -50,33 +50,33 @@ class BitrateProber { // Returns true if the prober is in a probing session, i.e., it currently // wants packets to be sent out according to the time returned by // TimeUntilNextProbe(). - bool is_probing() const { return probing_state_ == ProbingState::kActive; } + bool IsProbing() const; // Initializes a new probing session if the prober is allowed to probe. Does // not initialize the prober unless the packet size is large enough to probe // with. - void OnIncomingPacket(DataSize packet_size); + void OnIncomingPacket(size_t packet_size); - // Create a cluster used to probe. - void CreateProbeCluster(const ProbeClusterConfig& cluster_config); - // Returns the time at which the next probe should be sent to get accurate - // probing. If probing is not desired at this time, Timestamp::PlusInfinity() - // will be returned. - // TODO(bugs.webrtc.org/11780): Remove `now` argument when old mode is gone. - Timestamp NextProbeTime(Timestamp now) const; + // Create a cluster used to probe for |bitrate_bps| with |num_probes| number + // of probes. + void CreateProbeCluster(int bitrate_bps, int64_t now_ms, int cluster_id); + + // Returns the number of milliseconds until the next probe should be sent to + // get accurate probing. + int TimeUntilNextProbe(int64_t now_ms); // Information about the current probing cluster. - absl::optional CurrentCluster(Timestamp now); + PacedPacketInfo CurrentCluster() const; // Returns the minimum number of bytes that the prober recommends for - // the next probe, or zero if not probing. A probe can consist of multiple - // packets that are sent back to back. - DataSize RecommendedMinProbeSize() const; + // the next probe. + size_t RecommendedMinProbeSize() const; // Called to report to the prober that a probe has been sent. In case of // multiple packets per probe, this call would be made at the end of sending - // the last packet in probe. `size` is the total size of all packets in probe. - void ProbeSent(Timestamp now, DataSize size); + // the last packet in probe. |probe_size| is the total size of all packets + // in probe. + void ProbeSent(int64_t now_ms, size_t probe_size); private: enum class ProbingState { @@ -99,12 +99,12 @@ class BitrateProber { int sent_probes = 0; int sent_bytes = 0; - Timestamp requested_at = Timestamp::MinusInfinity(); - Timestamp started_at = Timestamp::MinusInfinity(); + int64_t time_created_ms = -1; + int64_t time_started_ms = -1; int retries = 0; }; - Timestamp CalculateNextProbeTime(const ProbeCluster& cluster) const; + int64_t GetNextProbeTime(const ProbeCluster& cluster); ProbingState probing_state_; @@ -114,7 +114,7 @@ class BitrateProber { std::queue clusters_; // Time the next probe should be sent when in kActive state. - Timestamp next_probe_time_; + int64_t next_probe_time_ms_; int total_probe_count_; int total_failed_probe_count_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc index 704869648c..1c638428b2 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 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 @@ -8,317 +8,286 @@ * be found in the AUTHORS file in the root of the source tree. */ +#define MS_CLASS "webrtc::PacedSender" +// #define MS_LOG_DEV_LEVEL 3 + #include "modules/pacing/paced_sender.h" +#include "modules/pacing/bitrate_prober.h" +#include "modules/pacing/interval_budget.h" +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "system_wrappers/source/field_trial.h" // webrtc::field_trial. + +#include "DepLibUV.hpp" +#include "Logger.hpp" +#include "RTC/RtpPacket.hpp" +#include #include #include -#include "absl/memory/memory.h" -// #include "api/task_queue/pending_task_safety_flag.h" -#include "api/transport/network_types.h" -// #include "rtc_base/checks.h" -#include "rtc_base/experiments/field_trial_parser.h" -#include "rtc_base/experiments/field_trial_units.h" -#include "rtc_base/system/unused.h" -// #include "rtc_base/trace_event.h" - namespace webrtc { - namespace { +// Time limit in milliseconds between packet bursts. +const int64_t kDefaultMinPacketLimitMs = 5; +const int64_t kCongestedPacketIntervalMs = 500; +const int64_t kPausedProcessIntervalMs = kCongestedPacketIntervalMs; +const int64_t kMaxElapsedTimeMs = 2000; -constexpr const char* kBurstyPacerFieldTrial = "WebRTC-BurstyPacer"; - -constexpr const char* kSlackedPacedSenderFieldTrial = - "WebRTC-SlackedPacedSender"; +// Upper cap on process interval, in case process has not been called in a long +// time. +const int64_t kMaxIntervalTimeMs = 30; } // namespace +const float PacedSender::kDefaultPaceMultiplier = 2.5f; + +PacedSender::PacedSender(PacketRouter* packet_router, + const WebRtcKeyValueConfig* field_trials) + : packet_router_(packet_router), + fallback_field_trials_( + !field_trials ? absl::make_unique() : nullptr), + field_trials_(field_trials ? field_trials : fallback_field_trials_.get()), + min_packet_limit_ms_("", kDefaultMinPacketLimitMs), + paused_(false), + media_budget_(0), + padding_budget_(0), + prober_(*field_trials_), + probing_send_failure_(false), + pacing_bitrate_kbps_(0), + time_last_process_us_(DepLibUV::GetTimeUsInt64()), + first_sent_packet_ms_(-1), + packet_counter_(0), + account_for_audio_(false) { + ParseFieldTrial({&min_packet_limit_ms_}, + webrtc::field_trial::FindFullName("WebRTC-Pacer-MinPacketLimitMs")); + UpdateBudgetWithElapsedTime(min_packet_limit_ms_); +} -const int PacedSender::kNoPacketHoldback = -1; +void PacedSender::CreateProbeCluster(int bitrate_bps, int cluster_id) { + // TODO: REMOVE + // MS_DEBUG_DEV("---- bitrate_bps:%d, cluster_id:%d", bitrate_bps, cluster_id); -PacedSender::BurstyPacerFlags::BurstyPacerFlags( - const WebRtcKeyValueConfig& field_trials) - : burst("burst") { - ParseFieldTrial({&burst}, field_trials.Lookup(kBurstyPacerFieldTrial)); + prober_.CreateProbeCluster(bitrate_bps, DepLibUV::GetTimeMsInt64(), cluster_id); } -PacedSender::SlackedPacerFlags::SlackedPacerFlags( - const WebRtcKeyValueConfig& field_trials) - : allow_low_precision("Enabled"), - max_low_precision_expected_queue_time("max_queue_time"), - send_burst_interval("send_burst_interval") { - ParseFieldTrial({&allow_low_precision, &max_low_precision_expected_queue_time, - &send_burst_interval}, - field_trials.Lookup(kSlackedPacedSenderFieldTrial)); -} +void PacedSender::Pause() { + if (!paused_) + MS_DEBUG_DEV("paused"); -PacedSender::PacedSender( - Clock* clock, - PacingController::PacketSender* packet_sender, - const WebRtcKeyValueConfig& field_trials, - TimeDelta max_hold_back_window, - int max_hold_back_window_in_packets) - : clock_(clock), - bursty_pacer_flags_(field_trials), - slacked_pacer_flags_(field_trials), - max_hold_back_window_(slacked_pacer_flags_.allow_low_precision - ? PacingController::kMinSleepTime - : max_hold_back_window), - max_hold_back_window_in_packets_(slacked_pacer_flags_.allow_low_precision - ? 0 - : max_hold_back_window_in_packets), - pacing_controller_(packet_sender, field_trials), - next_process_time_(Timestamp::MinusInfinity()), - is_started_(false), - is_shutdown_(false), - packet_size_(/*alpha=*/0.95), - include_overhead_(false) { - // RTC_DCHECK_GE(max_hold_back_window_, PacingController::kMinSleepTime); - // There are multiple field trials that can affect burst. If multiple bursts - // are specified we pick the largest of the values. - absl::optional burst = bursty_pacer_flags_.burst.GetOptional(); - if (slacked_pacer_flags_.allow_low_precision && - slacked_pacer_flags_.send_burst_interval) { - TimeDelta slacked_burst = slacked_pacer_flags_.send_burst_interval.Value(); - if (!burst.has_value() || burst.value() < slacked_burst) { - burst = slacked_burst; - } - } - if (burst.has_value()) { - pacing_controller_.SetSendBurstInterval(burst.value()); - } + paused_ = true; } -PacedSender::~PacedSender() { - is_shutdown_ = true; -} +void PacedSender::Resume() { + if (paused_) + MS_DEBUG_DEV("resumed"); -void PacedSender::EnsureStarted() { - is_started_ = true; - MaybeProcessPackets(Timestamp::MinusInfinity()); + paused_ = false; } -void PacedSender::CreateProbeClusters( - std::vector probe_cluster_configs) { - pacing_controller_.CreateProbeClusters(probe_cluster_configs); - MaybeProcessPackets(Timestamp::MinusInfinity()); +void PacedSender::SetCongestionWindow(int64_t congestion_window_bytes) { + congestion_window_bytes_ = congestion_window_bytes; } -void PacedSender::Pause() { - pacing_controller_.Pause(); +void PacedSender::UpdateOutstandingData(int64_t outstanding_bytes) { + outstanding_bytes_ = outstanding_bytes; } -void PacedSender::Resume() { - pacing_controller_.Resume(); - MaybeProcessPackets(Timestamp::MinusInfinity()); +bool PacedSender::Congested() const { + if (congestion_window_bytes_ == kNoCongestionWindow) + return false; + return outstanding_bytes_ >= congestion_window_bytes_; } -void PacedSender::SetCongested(bool congested) { - pacing_controller_.SetCongested(congested); - MaybeProcessPackets(Timestamp::MinusInfinity()); -} +void PacedSender::SetProbingEnabled(bool enabled) { + // RTC_CHECK_EQ(0, packet_counter_); + MS_ASSERT(packet_counter_ == 0, "packet counter must be 0"); -void PacedSender::SetPacingRates(DataRate pacing_rate, - DataRate padding_rate) { - pacing_controller_.SetPacingRates(pacing_rate, padding_rate); - MaybeProcessPackets(Timestamp::MinusInfinity()); + prober_.SetEnabled(enabled); } -void PacedSender::EnqueuePackets( - std::vector> packets) { - for (auto& packet : packets) { - /* TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc"), - "PacedSender::EnqueuePackets::Loop", - "sequence_number", packet->SequenceNumber(), - "rtp_timestamp", packet->Timestamp());*/ - - size_t packet_size = packet->payload_size() + packet->padding_size(); - if (include_overhead_) { - packet_size += packet->headers_size(); - } - packet_size_.Apply(1, packet_size); - RTC_DCHECK_GE(packet->capture_time(), Timestamp::Zero()); - pacing_controller_.EnqueuePacket(std::move(packet)); - } - MaybeProcessPackets(Timestamp::MinusInfinity()); -} +void PacedSender::SetPacingRates(uint32_t pacing_rate_bps, + uint32_t padding_rate_bps) { + // RTC_DCHECK(pacing_rate_bps > 0); + MS_ASSERT(pacing_rate_bps > 0, "pacing rate must be > 0"); -void PacedSender::SetAccountForAudioPackets(bool account_for_audio) { - pacing_controller_.SetAccountForAudioPackets(account_for_audio); - MaybeProcessPackets(Timestamp::MinusInfinity()); -} + pacing_bitrate_kbps_ = pacing_rate_bps / 1000; + padding_budget_.set_target_rate_kbps(padding_rate_bps / 1000); -void PacedSender::SetIncludeOverhead() { - include_overhead_ = true; - pacing_controller_.SetIncludeOverhead(); - MaybeProcessPackets(Timestamp::MinusInfinity()); + // TODO: REMOVE + // MS_DEBUG_DEV("[pacer_updated pacing_kbps:%" PRIu32 ", padding_budget_kbps:%" PRIu32 "]", + // pacing_bitrate_kbps_, + // padding_rate_bps / 1000); } -void PacedSender::SetTransportOverhead(DataSize overhead_per_packet) { - pacing_controller_.SetTransportOverhead(overhead_per_packet); - MaybeProcessPackets(Timestamp::MinusInfinity()); -} +void PacedSender::InsertPacket(size_t bytes) { + // RTC_DCHECK(pacing_bitrate_kbps_ > 0) + // << "SetPacingRate must be called before InsertPacket."; + MS_ASSERT(pacing_bitrate_kbps_ > 0, "SetPacingRates() must be called before InsertPacket()"); -void PacedSender::SetQueueTimeLimit(TimeDelta limit) { - pacing_controller_.SetQueueTimeLimit(limit); - MaybeProcessPackets(Timestamp::MinusInfinity()); -} + prober_.OnIncomingPacket(bytes); -TimeDelta PacedSender::ExpectedQueueTime() const { - return GetStats().expected_queue_time; -} + packet_counter_++; -DataSize PacedSender::QueueSizeData() const { - return GetStats().queue_size; + // MS_NOTE: Since we don't send media packets within ::Process(), + // we use this callback to acknowledge sent packets. + OnPacketSent(bytes); } -absl::optional PacedSender::FirstSentPacketTime() const { - return GetStats().first_sent_packet_time; +void PacedSender::SetAccountForAudioPackets(bool account_for_audio) { + account_for_audio_ = account_for_audio; } -TimeDelta PacedSender::OldestPacketWaitTime() const { - Timestamp oldest_packet = GetStats().oldest_packet_enqueue_time; - if (oldest_packet.IsInfinite()) { - return TimeDelta::Zero(); +int64_t PacedSender::TimeUntilNextProcess() { + int64_t elapsed_time_us = + DepLibUV::GetTimeUsInt64() - time_last_process_us_; + int64_t elapsed_time_ms = (elapsed_time_us + 500) / 1000; + // When paused we wake up every 500 ms to send a padding packet to ensure + // we won't get stuck in the paused state due to no feedback being received. + if (paused_) + return std::max(kPausedProcessIntervalMs - elapsed_time_ms, 0); + + if (prober_.IsProbing()) { + int64_t ret = prober_.TimeUntilNextProbe(DepLibUV::GetTimeMsInt64()); + if (ret > 0 || (ret == 0 && !probing_send_failure_)) + return ret; } + return std::max(min_packet_limit_ms_ - elapsed_time_ms, 0); +} - // (webrtc:9716): The clock is not always monotonic. - Timestamp current = clock_->CurrentTime(); - if (current < oldest_packet) { - return TimeDelta::Zero(); +int64_t PacedSender::UpdateTimeAndGetElapsedMs(int64_t now_us) { + int64_t elapsed_time_ms = (now_us - time_last_process_us_ + 500) / 1000; + time_last_process_us_ = now_us; + if (elapsed_time_ms > kMaxElapsedTimeMs) { + MS_WARN_TAG(bwe, "elapsed time (%" PRIi64 " ms) longer than expected," + " limiting to %" PRIi64 " ms", + elapsed_time_ms, + kMaxElapsedTimeMs); + elapsed_time_ms = kMaxElapsedTimeMs; } - - return current - oldest_packet; + return elapsed_time_ms; } -void PacedSender::OnStatsUpdated(const Stats& stats) { - current_stats_ = stats; -} +void PacedSender::Process() { + int64_t now_us = DepLibUV::GetTimeUsInt64(); + int64_t elapsed_time_ms = UpdateTimeAndGetElapsedMs(now_us); -void PacedSender::MaybeProcessPackets( - Timestamp scheduled_process_time) { -/* RTC_DCHECK_RUN_ON(&task_queue_); + if (paused_) + return; - TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("webrtc"), - "PacedSender::MaybeProcessPackets");*/ + if (elapsed_time_ms > 0) { + int target_bitrate_kbps = pacing_bitrate_kbps_; + media_budget_.set_target_rate_kbps(target_bitrate_kbps); + UpdateBudgetWithElapsedTime(elapsed_time_ms); + } - if (is_shutdown_ || !is_started_) { + if (!prober_.IsProbing()) return; + + PacedPacketInfo pacing_info; + absl::optional recommended_probe_size; + + pacing_info = prober_.CurrentCluster(); + recommended_probe_size = prober_.RecommendedMinProbeSize(); + + size_t bytes_sent = 0; + // MS_NOTE: Let's not use a useless vector. + RTC::RtpPacket* padding_packet{ nullptr }; + + // Check if we should send padding. + while (true) + { + size_t padding_bytes_to_add = + PaddingBytesToAdd(recommended_probe_size, bytes_sent); + + if (padding_bytes_to_add == 0) + break; + + // TODO: REMOVE + // MS_DEBUG_DEV( + // "[recommended_probe_size:%zu, padding_bytes_to_add:%zu]", + // *recommended_probe_size, padding_bytes_to_add); + + padding_packet = + packet_router_->GeneratePadding(padding_bytes_to_add); + + // TODO: REMOVE. + // MS_DEBUG_DEV("sending padding packet [size:%zu]", padding_packet->GetSize()); + + packet_router_->SendPacket(padding_packet, pacing_info); + bytes_sent += padding_packet->GetSize(); + + if (recommended_probe_size && bytes_sent > *recommended_probe_size) + break; } - Timestamp next_send_time = pacing_controller_.NextSendTime(); - // RTC_DCHECK(next_send_time.IsFinite()); - const Timestamp now = clock_->CurrentTime(); - TimeDelta early_execute_margin = - pacing_controller_.IsProbing() - ? PacingController::kMaxEarlyProbeProcessing - : TimeDelta::Zero(); - - // Process packets and update stats. - while (next_send_time <= now + early_execute_margin) { - pacing_controller_.ProcessPackets(); - next_send_time = pacing_controller_.NextSendTime(); - // RTC_DCHECK(next_send_time.IsFinite()); - - // Probing state could change. Get margin after process packets. - early_execute_margin = pacing_controller_.IsProbing() - ? PacingController::kMaxEarlyProbeProcessing - : TimeDelta::Zero(); + if (bytes_sent != 0) + { + auto now = DepLibUV::GetTimeUsInt64(); + + OnPaddingSent(now, bytes_sent); + prober_.ProbeSent((now + 500) / 1000, bytes_sent); } - UpdateStats(); +} - // Ignore retired scheduled task, otherwise reset `next_process_time_`. - if (scheduled_process_time.IsFinite()) { - if (scheduled_process_time != next_process_time_) { - return; - } - next_process_time_ = Timestamp::MinusInfinity(); +size_t PacedSender::PaddingBytesToAdd( + absl::optional recommended_probe_size, + size_t bytes_sent) { + + // Don't add padding if congested, even if requested for probing. + if (Congested()) { + return 0; } - // Do not hold back in probing. - TimeDelta hold_back_window = TimeDelta::Zero(); - if (!pacing_controller_.IsProbing()) { - hold_back_window = max_hold_back_window_; - DataRate pacing_rate = pacing_controller_.pacing_rate(); - if (max_hold_back_window_in_packets_ != kNoPacketHoldback && - !pacing_rate.IsZero() && - packet_size_.filtered() != rtc::ExpFilter::kValueUndefined) { - TimeDelta avg_packet_send_time = - DataSize::Bytes(packet_size_.filtered()) / pacing_rate; - hold_back_window = - std::min(hold_back_window, - avg_packet_send_time * max_hold_back_window_in_packets_); + // MS_NOTE: This does not apply to mediasoup. + // We can not send padding unless a normal packet has first been sent. If we + // do, timestamps get messed up. + // if (packet_counter_ == 0) { + // return 0; + // } + + if (recommended_probe_size) { + if (*recommended_probe_size > bytes_sent) { + return *recommended_probe_size - bytes_sent; } + return 0; } - // Calculate next process time. - TimeDelta time_to_next_process = - std::max(hold_back_window, next_send_time - now - early_execute_margin); - next_send_time = now + time_to_next_process; - - // If no in flight task or in flight task is later than `next_send_time`, - // schedule a new one. Previous in flight task will be retired. - if (next_process_time_.IsMinusInfinity() || - next_process_time_ > next_send_time) { - // Prefer low precision if allowed and not probing. - TaskQueueBase::DelayPrecision precision = - slacked_pacer_flags_.allow_low_precision && - !pacing_controller_.IsProbing() - ? TaskQueueBase::DelayPrecision::kLow - : TaskQueueBase::DelayPrecision::kHigh; - // Check for cases where we need high precision. - if (precision == TaskQueueBase::DelayPrecision::kLow) { - auto& packets_per_type = - pacing_controller_.SizeInPacketsPerRtpPacketMediaType(); - bool audio_or_retransmission_packets_in_queue = - packets_per_type[static_cast(RtpPacketMediaType::kAudio)] > - 0 || - packets_per_type[static_cast( - RtpPacketMediaType::kRetransmission)] > 0; - bool queue_time_too_large = - slacked_pacer_flags_.max_low_precision_expected_queue_time && - pacing_controller_.ExpectedQueueTime() >= - slacked_pacer_flags_.max_low_precision_expected_queue_time - .Value(); - if (audio_or_retransmission_packets_in_queue || queue_time_too_large) { - precision = TaskQueueBase::DelayPrecision::kHigh; - } - } + return padding_budget_.bytes_remaining(); +} - task_queue_.TaskQueueForDelayedTasks()->PostDelayedTaskWithPrecision( - precision, - task_queue_.MaybeSafeTask( - safety_.flag(), - [this, next_send_time]() { MaybeProcessPackets(next_send_time); }), - time_to_next_process.RoundUpTo(TimeDelta::Millis(1))); - next_process_time_ = next_send_time; - } +void PacedSender::OnPacketSent(size_t size) { + if (first_sent_packet_ms_ == -1) + first_sent_packet_ms_ = DepLibUV::GetTimeMsInt64(); + + // Update media bytes sent. + UpdateBudgetWithBytesSent(size); } -int64_t PacedSender::TimeUntilNextProcess() { - Timestamp next_send_time = pacing_controller_.NextSendTime(); - TimeDelta sleep_time = - std::max(TimeDelta::Zero(), next_send_time - clock_->CurrentTime()); - if (process_mode_ == PacingController::ProcessMode::kDynamic) { - return std::max(sleep_time, PacingController::kMinSleepTime).ms(); - } - return sleep_time.ms(); +PacedPacketInfo PacedSender::GetPacingInfo() { + PacedPacketInfo pacing_info; + + if (prober_.IsProbing()) { + pacing_info = prober_.CurrentCluster(); + } + + return pacing_info; } -void PacedSender::Process() { - pacing_controller_.ProcessPackets(); + +void PacedSender::OnPaddingSent(int64_t now, size_t bytes_sent) { + if (bytes_sent > 0) { + UpdateBudgetWithBytesSent(bytes_sent); + } } -void PacedSender::UpdateStats() { - Stats new_stats; - new_stats.expected_queue_time = pacing_controller_.ExpectedQueueTime(); - new_stats.first_sent_packet_time = pacing_controller_.FirstSentPacketTime(); - new_stats.oldest_packet_enqueue_time = - pacing_controller_.OldestPacketEnqueueTime(); - new_stats.queue_size = pacing_controller_.QueueSizeData(); - OnStatsUpdated(new_stats); +void PacedSender::UpdateBudgetWithElapsedTime(int64_t delta_time_ms) { + delta_time_ms = std::min(kMaxIntervalTimeMs, delta_time_ms); + media_budget_.IncreaseBudget(delta_time_ms); + padding_budget_.IncreaseBudget(delta_time_ms); } -PacedSender::Stats PacedSender::GetStats() const { - return current_stats_; +void PacedSender::UpdateBudgetWithBytesSent(size_t bytes_sent) { + outstanding_bytes_ += bytes_sent; + media_budget_.UseBudget(bytes_sent); + padding_budget_.UseBudget(bytes_sent); } } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h index de741e8b6c..4364f3bed4 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/pacing/paced_sender.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 The WebRTC project authors. All Rights Reserved. + * Copyright (c) 2012 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 @@ -8,191 +8,127 @@ * be found in the AUTHORS file in the root of the source tree. */ -#ifndef MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ -#define MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ +#ifndef MODULES_PACING_PACED_SENDER_H_ +#define MODULES_PACING_PACED_SENDER_H_ +#include "api/transport/field_trial_based_config.h" +#include "api/transport/network_types.h" +#include "api/transport/webrtc_key_value_config.h" +#include "modules/pacing/bitrate_prober.h" +#include "modules/pacing/interval_budget.h" +#include "modules/pacing/packet_router.h" +#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" +#include "rtc_base/experiments/field_trial_parser.h" + +#include "RTC/RtpPacket.hpp" + +#include #include #include - +#include #include -#include - -#include "absl/types/optional.h" -//#include "api/field_trials_view.h" -//#include "api/sequence_checker.h" -//#include "api/task_queue/task_queue_factory.h" -#include "api/units/data_size.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "modules/pacing/pacing_controller.h" -#include "modules/pacing/rtp_packet_pacer.h" -#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" -//#include "modules/utility/maybe_worker_thread.h" -#include "rtc_base/experiments/field_trial_parser.h" -#include "rtc_base/numerics/exp_filter.h" -//#include "rtc_base/thread_annotations.h" namespace webrtc { -class Clock; -class PacedSender : public RtpPacketPacer, public RtpPacketSender { +class PacedSender { public: - static const int kNoPacketHoldback; - - // The `hold_back_window` parameter sets a lower bound on time to sleep if - // there is currently a pacer queue and packets can't immediately be - // processed. Increasing this reduces thread wakeups at the expense of higher - // latency. - PacedSender(Clock* clock, - PacingController::PacketSender* packet_sender, - const WebRtcKeyValueConfig& field_trials, - TimeDelta max_hold_back_window, - int max_hold_back_window_in_packets); - - ~PacedSender() override; + static constexpr int64_t kNoCongestionWindow = -1; - // Ensure that necessary delayed tasks are scheduled. - void EnsureStarted(); + // Pacing-rate relative to our target send rate. + // Multiplicative factor that is applied to the target bitrate to calculate + // the number of bytes that can be transmitted per interval. + // Increasing this factor will result in lower delays in cases of bitrate + // overshoots from the encoder. + static const float kDefaultPaceMultiplier; - // Methods implementing RtpPacketSender. + PacedSender(PacketRouter* packet_router, + const WebRtcKeyValueConfig* field_trials = nullptr); - // Adds the packet to the queue and calls - // PacingController::PacketSender::SendPacket() when it's time to send. - void EnqueuePackets( - std::vector> packets) override; + virtual ~PacedSender() = default; - // Methods implementing RtpPacketPacer. - - void CreateProbeClusters( - std::vector probe_cluster_configs) override; + virtual void CreateProbeCluster(int bitrate_bps, int cluster_id); // Temporarily pause all sending. - void Pause() override; + void Pause(); // Resume sending packets. - void Resume() override; + void Resume(); + + void SetCongestionWindow(int64_t congestion_window_bytes); + void UpdateOutstandingData(int64_t outstanding_bytes); - void SetCongested(bool congested) override; + // Enable bitrate probing. Enabled by default, mostly here to simplify + // testing. Must be called before any packets are being sent to have an + // effect. + void SetProbingEnabled(bool enabled); // Sets the pacing rates. Must be called once before packets can be sent. - void SetPacingRates(DataRate pacing_rate, DataRate padding_rate) override; + void SetPacingRates(uint32_t pacing_rate_bps, uint32_t padding_rate_bps); + + // Adds the packet information to the queue and calls TimeToSendPacket + // when it's time to send. + // MS_NOTE: defined in "modules/rtp_rtcp/include/rtp_packet_sender.h" + void InsertPacket(size_t bytes); - // Currently audio traffic is not accounted for by pacer and passed through. - // With the introduction of audio BWE, audio traffic will be accounted for - // in the pacer budget calculation. The audio traffic will still be injected + // Currently audio traffic is not accounted by pacer and passed through. + // With the introduction of audio BWE audio traffic will be accounted for + // the pacer budget calculation. The audio traffic still will be injected // at high priority. - void SetAccountForAudioPackets(bool account_for_audio) override; - - void SetIncludeOverhead() override; - void SetTransportOverhead(DataSize overhead_per_packet) override; - - // Returns the time since the oldest queued packet was enqueued. - TimeDelta OldestPacketWaitTime() const override; - - // Returns total size of all packets in the pacer queue. - DataSize QueueSizeData() const override; - - // Returns the time when the first packet was sent; - absl::optional FirstSentPacketTime() const override; - - // Returns the number of milliseconds it will take to send the current - // packets in the queue, given the current size and bitrate, ignoring prio. - TimeDelta ExpectedQueueTime() const override; - - // Set the max desired queuing delay, pacer will override the pacing rate - // specified by SetPacingRates() if needed to achieve this goal. - void SetQueueTimeLimit(TimeDelta limit) override; - - protected: - // Exposed as protected for test. - struct Stats { - Stats() - : oldest_packet_enqueue_time(Timestamp::MinusInfinity()), - queue_size(DataSize::Zero()), - expected_queue_time(TimeDelta::Zero()) {} - Timestamp oldest_packet_enqueue_time; - DataSize queue_size; - TimeDelta expected_queue_time; - absl::optional first_sent_packet_time; - }; - void OnStatsUpdated(const Stats& stats); + void SetAccountForAudioPackets(bool account_for_audio); + + // Returns the number of milliseconds until the module want a worker thread + // to call Process. + int64_t TimeUntilNextProcess(); + + // Process any pending packets in the queue(s). + void Process(); + + void OnPacketSent(size_t size); + PacedPacketInfo GetPacingInfo(); private: - // Check if it is time to send packets, or schedule a delayed task if not. - // Use Timestamp::MinusInfinity() to indicate that this call has _not_ - // been scheduled by the pacing controller. If this is the case, check if - // can execute immediately otherwise schedule a delay task that calls this - // method again with desired (finite) scheduled process time. - void MaybeProcessPackets(Timestamp scheduled_process_time); - - void UpdateStats(); - Stats GetStats() const; - - Clock* const clock_; - struct BurstyPacerFlags { - // Parses `kBurstyPacerFieldTrial`. Example: - // --force-fieldtrials=WebRTC-BurstyPacer/burst:20ms/ - explicit BurstyPacerFlags(const WebRtcKeyValueConfig& field_trials); - // If set, the pacer is allowed to build up a packet "debt" that correspond - // to approximately the send rate during the specified interval. - FieldTrialOptional burst; - }; - const BurstyPacerFlags bursty_pacer_flags_; - struct SlackedPacerFlags { - // Parses `kSlackedPacedSenderFieldTrial`. Example: - // --force-fieldtrials=WebRTC-SlackedPacedSender/Enabled,max_queue_time:75ms/ - explicit SlackedPacerFlags(const WebRtcKeyValueConfig& field_trials); - // When "Enabled", delayed tasks invoking MaybeProcessPackets() are - // scheduled using low precision instead of high precision, resulting in - // less idle wake ups and packets being sent in bursts if the `task_queue_` - // implementation supports slack. When probing, high precision is used - // regardless to ensure good bandwidth estimation. - FieldTrialFlag allow_low_precision; - // Controlled via the "max_queue_time" experiment argument. If set, uses - // high precision scheduling of MaybeProcessPackets() whenever the expected - // queue time is greater than or equal to this value. - FieldTrialOptional max_low_precision_expected_queue_time; - // Controlled via "send_burst_interval" experiment argument. If set, the - // pacer is allowed to build up a packet "debt" that correspond to - // approximately the send rate during the specified interval. - FieldTrialOptional send_burst_interval; - }; - const SlackedPacerFlags slacked_pacer_flags_; - // The holdback window prevents too frequent delayed MaybeProcessPackets() - // calls. These are only applicable if `allow_low_precision` is false. - const TimeDelta max_hold_back_window_; - const int max_hold_back_window_in_packets_; - - PacingController pacing_controller_; - - // We want only one (valid) delayed process task in flight at a time. - // If the value of `next_process_time_` is finite, it is an id for a - // delayed task that will call MaybeProcessPackets() with that time - // as parameter. - // Timestamp::MinusInfinity() indicates no valid pending task. - Timestamp next_process_time_; - - // Indicates if this task queue is started. If not, don't allow - // posting delayed tasks yet. - bool is_started_; - - // Indicates if this task queue is shutting down. If so, don't allow - // posting any more delayed tasks as that can cause the task queue to - // never drain. - bool is_shutdown_; - - // Filtered size of enqueued packets, in bytes. - rtc::ExpFilter packet_size_; - bool include_overhead_; - - // Returns the number of milliseconds until the module want a worker thread - // to call Process. - int64_t TimeUntilNextProcess(); - - // Process any pending packets in the queue(s). - void Process(); - - Stats current_stats_; + int64_t UpdateTimeAndGetElapsedMs(int64_t now_us); + + // Updates the number of bytes that can be sent for the next time interval. + void UpdateBudgetWithElapsedTime(int64_t delta_time_in_ms); + void UpdateBudgetWithBytesSent(size_t bytes); + + size_t PaddingBytesToAdd(absl::optional recommended_probe_size, + size_t bytes_sent); + + void OnPaddingSent(int64_t now_us, size_t bytes_sent); + + bool Congested() const; + + PacketRouter* const packet_router_; + const std::unique_ptr fallback_field_trials_; + const WebRtcKeyValueConfig* field_trials_; + + FieldTrialParameter min_packet_limit_ms_; + + bool paused_; + // This is the media budget, keeping track of how many bits of media + // we can pace out during the current interval. + IntervalBudget media_budget_; + // This is the padding budget, keeping track of how many bits of padding we're + // allowed to send out during the current interval. This budget will be + // utilized when there's no media to send. + IntervalBudget padding_budget_; + + BitrateProber prober_; + bool probing_send_failure_; + + uint32_t pacing_bitrate_kbps_; + + int64_t time_last_process_us_; + int64_t first_sent_packet_ms_; + + uint64_t packet_counter_; + + int64_t congestion_window_bytes_ = kNoCongestionWindow; + int64_t outstanding_bytes_ = 0; + + bool account_for_audio_; }; } // namespace webrtc -#endif // MODULES_PACING_TASK_QUEUE_PACED_SENDER_H_ +#endif // MODULES_PACING_PACED_SENDER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc deleted file mode 100644 index 5471dddf78..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.cc +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Copyright (c) 2019 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 "modules/pacing/pacing_controller.h" - -#include -#include -#include -#include - -#include "absl/strings/match.h" -#include "modules/pacing/bitrate_prober.h" -#include "modules/pacing/interval_budget.h" -// #include "rtc_base/checks.h" -#include "DepLibUV.hpp" -#include "rtc_base/experiments/field_trial_parser.h" -// #include "rtc_base/logging.h" -// #include "rtc_base/time_utils.h" -// #include "system_wrappers/include/clock.h" - -namespace webrtc { -namespace { -// Time limit in milliseconds between packet bursts. -constexpr TimeDelta kDefaultMinPacketLimit = TimeDelta::Millis<5>(); -constexpr TimeDelta kCongestedPacketInterval = TimeDelta::Millis<500>(); -// TODO(sprang): Consider dropping this limit. -// The maximum debt level, in terms of time, capped when sending packets. -constexpr TimeDelta kMaxDebtInTime = TimeDelta::Millis<500>(); -constexpr TimeDelta kMaxElapsedTime = TimeDelta::Seconds<2>(); -constexpr TimeDelta kTargetPaddingDuration = TimeDelta::Millis<5>(); - -bool IsDisabled(const WebRtcKeyValueConfig& field_trials, absl::string_view key) { - return absl::StartsWith(field_trials.Lookup(key), "Disabled"); -} - -bool IsEnabled(const WebRtcKeyValueConfig& field_trials, absl::string_view key) { - return absl::StartsWith(field_trials.Lookup(key), "Enabled"); -} - -} // namespace - -const TimeDelta PacingController::kMaxExpectedQueueLength = - TimeDelta::ms(2000); -const TimeDelta PacingController::kPausedProcessInterval = - kCongestedPacketInterval; -const TimeDelta PacingController::kMinSleepTime = TimeDelta::ms(1); -const TimeDelta PacingController::kMaxEarlyProbeProcessing = - TimeDelta::ms(1); - -PacingController::PacingController(PacketSender* packet_sender, - const WebRtcKeyValueConfig& field_trials) - : packet_sender_(packet_sender), - field_trials_(field_trials), - drain_large_queues_( - !IsDisabled(field_trials_, "WebRTC-Pacer-DrainQueue")), - send_padding_if_silent_( - IsEnabled(field_trials_, "WebRTC-Pacer-PadInSilence")), - pace_audio_(IsEnabled(field_trials_, "WebRTC-Pacer-BlockAudio")), - ignore_transport_overhead_( - IsEnabled(field_trials_, "WebRTC-Pacer-IgnoreTransportOverhead")), - fast_retransmissions_( - IsEnabled(field_trials_, "WebRTC-Pacer-FastRetransmissions")), - min_packet_limit_(kDefaultMinPacketLimit), - transport_overhead_per_packet_(DataSize::Zero()), - send_burst_interval_(TimeDelta::Zero()), - last_timestamp_(Timestamp::ms(DepLibUV::GetTimeMsInt64())), - paused_(false), - media_debt_(DataSize::Zero()), - padding_debt_(DataSize::Zero()), - pacing_rate_(DataRate::Zero()), - adjusted_media_rate_(DataRate::Zero()), - padding_rate_(DataRate::Zero()), - prober_(field_trials_), - probing_send_failure_(false), - last_process_time_(Timestamp::ms(DepLibUV::GetTimeMsInt64())), - last_send_time_(last_process_time_), - seen_first_packet_(false), - packet_queue_(/*creation_time=*/last_process_time_), - congested_(false), - queue_time_limit_(kMaxExpectedQueueLength), - account_for_audio_(false), - include_overhead_(false) { - if (!drain_large_queues_) { -/* RTC_LOG(LS_WARNING) << "Pacer queues will not be drained," - "pushback experiment must be enabled.";*/ - } - FieldTrialParameter min_packet_limit_ms("", min_packet_limit_.ms()); - ParseFieldTrial({&min_packet_limit_ms}, - field_trials_.Lookup("WebRTC-Pacer-MinPacketLimitMs")); - min_packet_limit_ = TimeDelta::ms(min_packet_limit_ms.Get()); - UpdateBudgetWithElapsedTime(min_packet_limit_); -} - -PacingController::~PacingController() = default; - -void PacingController::CreateProbeCluster(DataRate bitrate, int cluster_id) { - - ProbeClusterConfig config; - config.at_time = CurrentTime(); - config.target_data_rate = bitrate; - config.target_duration = TimeDelta::ms(15); - config.target_probe_count = 5; - config.id = cluster_id; - - prober_.CreateProbeCluster(config); -} - -void PacingController::CreateProbeClusters( - std::vector probe_cluster_configs) { - for (const ProbeClusterConfig probe_cluster_config : probe_cluster_configs) { - prober_.CreateProbeCluster(probe_cluster_config); - } -} - -void PacingController::Pause() { - if (!paused_) - // RTC_LOG(LS_INFO) << "PacedSender paused."; - paused_ = true; - packet_queue_.SetPauseState(true, CurrentTime()); -} - -void PacingController::Resume() { - if (paused_) - // RTC_LOG(LS_INFO) << "PacedSender resumed."; - paused_ = false; - packet_queue_.SetPauseState(false, CurrentTime()); -} - -bool PacingController::IsPaused() const { - return paused_; -} - -void PacingController::SetCongested(bool congested) { - if (congested_ && !congested) { - UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(CurrentTime())); - } - congested_ = congested; -} - -bool PacingController::IsProbing() const { - return prober_.is_probing(); -} - -Timestamp PacingController::CurrentTime() const { - Timestamp time = Timestamp::ms(DepLibUV::GetTimeMsInt64()); - if (time < last_timestamp_) { -/* RTC_LOG(LS_WARNING) - << "Non-monotonic clock behavior observed. Previous timestamp: " - << last_timestamp_.ms() << ", new timestamp: " << time.ms(); - RTC_DCHECK_GE(time, last_timestamp_);*/ - time = last_timestamp_; - } - last_timestamp_ = time; - return time; -} - -void PacingController::SetProbingEnabled(bool enabled) { - // RTC_CHECK(!seen_first_packet_); - prober_.SetEnabled(enabled); -} - -void PacingController::SetPacingRates(DataRate pacing_rate, - DataRate padding_rate) { - static constexpr DataRate kMaxRate = DataRate::KilobitsPerSec<100000>(); - // RTC_CHECK_GT(pacing_rate, DataRate::Zero()); - // RTC_CHECK_GE(padding_rate, DataRate::Zero()); - if (padding_rate > pacing_rate) { -/* RTC_LOG(LS_WARNING) << "Padding rate " << padding_rate.kbps() - << "kbps is higher than the pacing rate " - << pacing_rate.kbps() << "kbps, capping.";*/ - padding_rate = pacing_rate; - } - - if (pacing_rate > kMaxRate || padding_rate > kMaxRate) { -/* RTC_LOG(LS_WARNING) << "Very high pacing rates ( > " << kMaxRate.kbps() - << " kbps) configured: pacing = " << pacing_rate.kbps() - << " kbps, padding = " << padding_rate.kbps() - << " kbps.";*/ - } - pacing_rate_ = pacing_rate; - padding_rate_ = padding_rate; - MaybeUpdateMediaRateDueToLongQueue(CurrentTime()); - -/* RTC_LOG(LS_VERBOSE) << "bwe:pacer_updated pacing_kbps=" << pacing_rate_.kbps() - << " padding_budget_kbps=" << padding_rate.kbps();*/ -} - -void PacingController::EnqueuePacket(std::unique_ptr packet) { - // RTC_DCHECK(pacing_rate_ > DataRate::Zero()) << "SetPacingRate must be called before InsertPacket."; - // RTC_CHECK(packet->GetPacketType()); - - prober_.OnIncomingPacket(DataSize::bytes(packet->GetPayloadLength())); - - const Timestamp now = CurrentTime(); - if (packet_queue_.Empty()) { - // If queue is empty, we need to "fast-forward" the last process time, - // so that we don't use passed time as budget for sending the first new - // packet. - Timestamp target_process_time = now; - Timestamp next_send_time = NextSendTime(); - if (next_send_time.IsFinite()) { - // There was already a valid planned send time, such as a keep-alive. - // Use that as last process time only if it's prior to now. - target_process_time = std::min(now, next_send_time); - } - UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(target_process_time)); - } - packet_queue_.Push(now, std::move(packet)); - seen_first_packet_ = true; - - // Queue length has increased, check if we need to change the pacing rate. - MaybeUpdateMediaRateDueToLongQueue(now); -} - -void PacingController::SetAccountForAudioPackets(bool account_for_audio) { - account_for_audio_ = account_for_audio; -} - -void PacingController::SetIncludeOverhead() { - include_overhead_ = true; -} - -void PacingController::SetTransportOverhead(DataSize overhead_per_packet) { - if (ignore_transport_overhead_) - return; - transport_overhead_per_packet_ = overhead_per_packet; -} - -void PacingController::SetSendBurstInterval(TimeDelta burst_interval) { - send_burst_interval_ = burst_interval; -} - -TimeDelta PacingController::ExpectedQueueTime() const { - // RTC_DCHECK_GT(adjusted_media_rate_, DataRate::Zero()); - return QueueSizeData() / adjusted_media_rate_; -} - -size_t PacingController::QueueSizePackets() const { - return rtc::checked_cast(packet_queue_.SizeInPackets()); -} - -const std::array& -PacingController::SizeInPacketsPerRtpPacketMediaType() const { - return packet_queue_.SizeInPacketsPerRtpPacketMediaType(); -} - -DataSize PacingController::QueueSizeData() const { - DataSize size = packet_queue_.SizeInPayloadBytes(); - if (include_overhead_) { - size += static_cast(packet_queue_.SizeInPackets()) * - transport_overhead_per_packet_; - } - return size; -} - -DataSize PacingController::CurrentBufferLevel() const { - return std::max(media_debt_, padding_debt_); -} - -absl::optional PacingController::FirstSentPacketTime() const { - return first_sent_packet_time_; -} - -Timestamp PacingController::OldestPacketEnqueueTime() const { - return packet_queue_.OldestEnqueueTime(); -} - -TimeDelta PacingController::UpdateTimeAndGetElapsed(Timestamp now) { - // If no previous processing, or last process was "in the future" because of - // early probe processing, then there is no elapsed time to add budget for. - if (last_process_time_.IsMinusInfinity() || now < last_process_time_) { - return TimeDelta::Zero(); - } - TimeDelta elapsed_time = now - last_process_time_; - last_process_time_ = now; - if (elapsed_time > kMaxElapsedTime) { -/* RTC_LOG(LS_WARNING) << "Elapsed time (" << elapsed_time.ms() - << " ms) longer than expected, limiting to " - << kMaxElapsedTime.ms();*/ - elapsed_time = kMaxElapsedTime; - } - return elapsed_time; -} - -bool PacingController::ShouldSendKeepalive(Timestamp now) const { - if (send_padding_if_silent_ || paused_ || congested_ || !seen_first_packet_) { - // We send a padding packet every 500 ms to ensure we won't get stuck in - // congested state due to no feedback being received. - if (now - last_send_time_ >= kCongestedPacketInterval) { - return true; - } - } - return false; -} - -Timestamp PacingController::NextSendTime() const { - const Timestamp now = CurrentTime(); - Timestamp next_send_time = Timestamp::PlusInfinity(); - - if (paused_) { - return last_send_time_ + kPausedProcessInterval; - } - - // If probing is active, that always takes priority. - if (prober_.is_probing() && !probing_send_failure_) { - Timestamp probe_time = prober_.NextProbeTime(now); - if (!probe_time.IsPlusInfinity()) { - return probe_time.IsMinusInfinity() ? now : probe_time; - } - } - - // If queue contains a packet which should not be paced, its target send time - // is the time at which it was enqueued. - Timestamp unpaced_send_time = NextUnpacedSendTime(); - if (unpaced_send_time.IsFinite()) { - return unpaced_send_time; - } - - if (congested_ || !seen_first_packet_) { - // We need to at least send keep-alive packets with some interval. - return last_send_time_ + kCongestedPacketInterval; - } - - if (adjusted_media_rate_ > DataRate::Zero() && !packet_queue_.Empty()) { - // If packets are allowed to be sent in a burst, the - // debt is allowed to grow up to one packet more than what can be sent - // during 'send_burst_period_'. - TimeDelta drain_time = media_debt_ / adjusted_media_rate_; - next_send_time = - last_process_time_ + - ((send_burst_interval_ > drain_time) ? TimeDelta::Zero() : drain_time); - } else if (padding_rate_ > DataRate::Zero() && packet_queue_.Empty()) { - // If we _don't_ have pending packets, check how long until we have - // bandwidth for padding packets. Both media and padding debts must - // have been drained to do this. - // RTC_DCHECK_GT(adjusted_media_rate_, DataRate::Zero()); - TimeDelta drain_time = std::max(media_debt_ / adjusted_media_rate_, - padding_debt_ / padding_rate_); - - if (drain_time.IsZero() && - (!media_debt_.IsZero() || !padding_debt_.IsZero())) { - // We have a non-zero debt, but drain time is smaller than tick size of - // TimeDelta, round it up to the smallest possible non-zero delta. - drain_time = TimeDelta::Micros<1>(); - } - next_send_time = last_process_time_ + drain_time; - } else { - // Nothing to do. - next_send_time = last_process_time_ + kPausedProcessInterval; - } - - if (send_padding_if_silent_) { - next_send_time = - std::min(next_send_time, last_send_time_ + kPausedProcessInterval); - } - - return next_send_time; -} - -void PacingController::ProcessPackets() { - const Timestamp now = CurrentTime(); - Timestamp target_send_time = now; - - if (ShouldSendKeepalive(now)) { - DataSize keepalive_data_sent = DataSize::Zero(); - // We can not send padding unless a normal packet has first been sent. If - // we do, timestamps get messed up. - if (seen_first_packet_) { - std::vector> keepalive_packets = - packet_sender_->GeneratePadding(DataSize::bytes(1)); - for (auto& packet : keepalive_packets) { - keepalive_data_sent += - DataSize::bytes(packet->GetPayloadLength() + packet->GetPayloadPadding()); - packet_sender_->SendPacket(std::move(packet), PacedPacketInfo()); - for (auto& packet : packet_sender_->FetchFec()) { - EnqueuePacket(std::move(packet)); - } - } - } - OnPacketSent(RtpPacketMediaType::kPadding, keepalive_data_sent, now); - } - - if (paused_) { - return; - } - - TimeDelta early_execute_margin = - prober_.is_probing() ? kMaxEarlyProbeProcessing : TimeDelta::Zero(); - - target_send_time = NextSendTime(); - if (now + early_execute_margin < target_send_time) { - // We are too early, but if queue is empty still allow draining some debt. - // Probing is allowed to be sent up to kMinSleepTime early. - UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(now)); - return; - } - - TimeDelta elapsed_time = UpdateTimeAndGetElapsed(target_send_time); - - if (elapsed_time > TimeDelta::Zero()) { - UpdateBudgetWithElapsedTime(elapsed_time); - } - - PacedPacketInfo pacing_info; - DataSize recommended_probe_size = DataSize::Zero(); - bool is_probing = prober_.is_probing(); - if (is_probing) { - // Probe timing is sensitive, and handled explicitly by BitrateProber, so - // use actual send time rather than target. - pacing_info = prober_.CurrentCluster(now).value_or(PacedPacketInfo()); - if (pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe) { - recommended_probe_size = prober_.RecommendedMinProbeSize(); - // RTC_DCHECK_GT(recommended_probe_size, DataSize::Zero()); - } else { - // No valid probe cluster returned, probe might have timed out. - is_probing = false; - } - } - - DataSize data_sent = DataSize::Zero(); - // Circuit breaker, making sure main loop isn't forever. - static constexpr int kMaxIterations = 1 << 16; - int iteration = 0; - int packets_sent = 0; - int padding_packets_generated = 0; - for (; iteration < kMaxIterations; ++iteration) { - // Fetch packet, so long as queue is not empty or budget is not - // exhausted. - std::unique_ptr rtp_packet = - GetPendingPacket(pacing_info, target_send_time, now); - if (rtp_packet == nullptr) { - // No packet available to send, check if we should send padding. - DataSize padding_to_add = PaddingToAdd(recommended_probe_size, data_sent); - if (padding_to_add > DataSize::Zero()) { - std::vector> padding_packets = - packet_sender_->GeneratePadding(padding_to_add); - if (!padding_packets.empty()) { - padding_packets_generated += padding_packets.size(); - for (auto& packet : padding_packets) { - EnqueuePacket(std::move(packet)); - } - // Continue loop to send the padding that was just added. - continue; - } else { - // Can't generate padding, still update padding budget for next send - // time. - UpdatePaddingBudgetWithSentData(padding_to_add); - } - } - // Can't fetch new packet and no padding to send, exit send loop. - break; - } else { - // RTC_DCHECK(rtp_packet); - // RTC_DCHECK(rtp_packet->packet_type().has_value()); - const RtpPacketMediaType packet_type = rtp_packet->GetPacketType(); - DataSize packet_size = DataSize::bytes(rtp_packet->GetPayloadLength() + - rtp_packet->GetPayloadPadding()); - - if (include_overhead_) { - packet_size += DataSize::bytes(rtp_packet->GetSize() - rtp_packet->GetPayloadLength() - rtp_packet->GetPayloadPadding()) + - transport_overhead_per_packet_; - } - - packet_sender_->SendPacket(std::move(rtp_packet), pacing_info); - for (auto& packet : packet_sender_->FetchFec()) { - EnqueuePacket(std::move(packet)); - } - data_sent += packet_size; - ++packets_sent; - - // Send done, update send time. - OnPacketSent(packet_type, packet_size, now); - - if (is_probing) { - pacing_info.probe_cluster_bytes_sent += packet_size.bytes(); - // If we are currently probing, we need to stop the send loop when we - // have reached the send target. - if (data_sent >= recommended_probe_size) { - break; - } - } - - // Update target send time in case that are more packets that we are late - // in processing. - target_send_time = NextSendTime(); - if (target_send_time > now) { - // Exit loop if not probing. - if (!is_probing) { - break; - } - target_send_time = now; - } - UpdateBudgetWithElapsedTime(UpdateTimeAndGetElapsed(target_send_time)); - } - } - - if (iteration >= kMaxIterations) { - // Circuit break activated. Log warning, adjust send time and return. - // TODO(sprang): Consider completely clearing state. -/* RTC_LOG(LS_ERROR) << "PacingController exceeded max iterations in " - "send-loop: packets sent = " - << packets_sent << ", padding packets generated = " - << padding_packets_generated - << ", bytes sent = " << data_sent.bytes();*/ - last_send_time_ = now; - last_process_time_ = now; - return; - } - - if (is_probing) { - probing_send_failure_ = data_sent == DataSize::Zero(); - if (!probing_send_failure_) { - prober_.ProbeSent(CurrentTime(), data_sent); - } - } - - // Queue length has probably decreased, check if pacing rate needs to updated. - // Poll the time again, since we might have enqueued new fec/padding packets - // with a later timestamp than `now`. - MaybeUpdateMediaRateDueToLongQueue(CurrentTime()); -} - -DataSize PacingController::PaddingToAdd(DataSize recommended_probe_size, - DataSize data_sent) const { - if (!packet_queue_.Empty()) { - // Actual payload available, no need to add padding. - return DataSize::Zero(); - } - - if (congested_) { - // Don't add padding if congested, even if requested for probing. - return DataSize::Zero(); - } - - if (!seen_first_packet_) { - // We can not send padding unless a normal packet has first been sent. If - // we do, timestamps get messed up. - return DataSize::Zero(); - } - - if (!recommended_probe_size.IsZero()) { - if (recommended_probe_size > data_sent) { - return recommended_probe_size - data_sent; - } - return DataSize::Zero(); - } - - if (padding_rate_ > DataRate::Zero() && padding_debt_ == DataSize::Zero()) { - return kTargetPaddingDuration * padding_rate_; - } - return DataSize::Zero(); -} - -std::unique_ptr PacingController::GetPendingPacket( - const PacedPacketInfo& pacing_info, - Timestamp target_send_time, - Timestamp now) { - const bool is_probe = - pacing_info.probe_cluster_id != PacedPacketInfo::kNotAProbe; - // If first packet in probe, insert a small padding packet so we have a - // more reliable start window for the rate estimation. - if (is_probe && pacing_info.probe_cluster_bytes_sent == 0) { - auto padding = packet_sender_->GeneratePadding(DataSize::bytes(1)); - // If no RTP modules sending media are registered, we may not get a - // padding packet back. - if (!padding.empty()) { - // We should never get more than one padding packets with a requested - // size of 1 byte. - // RTC_DCHECK_EQ(padding.size(), 1u); - return std::move(padding[0]); - } - } - - if (packet_queue_.Empty()) { - return nullptr; - } - - // First, check if there is any reason _not_ to send the next queued packet. - // Unpaced packets and probes are exempted from send checks. - if (NextUnpacedSendTime().IsInfinite() && !is_probe) { - if (congested_) { - // Don't send anything if congested. - return nullptr; - } - - if (now <= target_send_time && send_burst_interval_.IsZero()) { - // We allow sending slightly early if we think that we would actually - // had been able to, had we been right on time - i.e. the current debt - // is not more than would be reduced to zero at the target sent time. - // If we allow packets to be sent in a burst, packet are allowed to be - // sent early. - TimeDelta flush_time = media_debt_ / adjusted_media_rate_; - if (now + flush_time > target_send_time) { - return nullptr; - } - } - } - - return packet_queue_.Pop(); -} - -void PacingController::OnPacketSent(RtpPacketMediaType packet_type, - DataSize packet_size, - Timestamp send_time) { - if (!first_sent_packet_time_ && packet_type != RtpPacketMediaType::kPadding) { - first_sent_packet_time_ = send_time; - } - - bool audio_packet = packet_type == RtpPacketMediaType::kAudio; - if ((!audio_packet || account_for_audio_) && packet_size > DataSize::Zero()) { - UpdateBudgetWithSentData(packet_size); - } - - last_send_time_ = send_time; -} - -void PacingController::UpdateBudgetWithElapsedTime(TimeDelta delta) { - media_debt_ -= std::min(media_debt_, adjusted_media_rate_ * delta); - padding_debt_ -= std::min(padding_debt_, padding_rate_ * delta); -} - -void PacingController::UpdateBudgetWithSentData(DataSize size) { - media_debt_ += size; - media_debt_ = std::min(media_debt_, adjusted_media_rate_ * kMaxDebtInTime); - UpdatePaddingBudgetWithSentData(size); -} - -void PacingController::UpdatePaddingBudgetWithSentData(DataSize size) { - padding_debt_ += size; - padding_debt_ = std::min(padding_debt_, padding_rate_ * kMaxDebtInTime); -} - -void PacingController::SetQueueTimeLimit(TimeDelta limit) { - queue_time_limit_ = limit; -} - -void PacingController::MaybeUpdateMediaRateDueToLongQueue(Timestamp now) { - adjusted_media_rate_ = pacing_rate_; - if (!drain_large_queues_) { - return; - } - - DataSize queue_size_data = QueueSizeData(); - if (queue_size_data > DataSize::Zero()) { - // Assuming equal size packets and input/output rate, the average packet - // has avg_time_left_ms left to get queue_size_bytes out of the queue, if - // time constraint shall be met. Determine bitrate needed for that. - packet_queue_.UpdateAverageQueueTime(now); - TimeDelta avg_time_left = - std::max(TimeDelta::ms(1), - queue_time_limit_ - packet_queue_.AverageQueueTime()); - DataRate min_rate_needed = queue_size_data / avg_time_left; - if (min_rate_needed > pacing_rate_) { - adjusted_media_rate_ = min_rate_needed; - // RTC_LOG(LS_VERBOSE) << "bwe:large_pacing_queue pacing_rate_kbps=" << pacing_rate_.kbps(); - } - } -} - -Timestamp PacingController::NextUnpacedSendTime() const { - if (!pace_audio_) { - Timestamp leading_audio_send_time = - packet_queue_.LeadingPacketEnqueueTime(RtpPacketMediaType::kAudio); - if (leading_audio_send_time.IsFinite()) { - return leading_audio_send_time; - } - } - if (fast_retransmissions_) { - Timestamp leading_retransmission_send_time = - packet_queue_.LeadingPacketEnqueueTime( - RtpPacketMediaType::kRetransmission); - if (leading_retransmission_send_time.IsFinite()) { - return leading_retransmission_send_time; - } - } - return Timestamp::MinusInfinity(); -} - -} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h deleted file mode 100644 index e7baaaffdc..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/pacing_controller.h +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ - -#ifndef MODULES_PACING_PACING_CONTROLLER_H_ -#define MODULES_PACING_PACING_CONTROLLER_H_ - -#include -#include - -#include -#include -#include -#include - -#include "absl/types/optional.h" -// #include "api/field_trials_view.h" -// #include "api/function_view.h" -#include "api/transport/field_trial_based_config.h" -#include "api/transport/network_types.h" -#include "modules/pacing/bitrate_prober.h" -#include "modules/pacing/interval_budget.h" -#include "modules/pacing/prioritized_packet_queue.h" -#include "modules/pacing/rtp_packet_sender.h" -// #include "modules/pacing/rtp_packet_pacer.h" -// #include "modules/rtp_rtcp/include/rtp_packet_sender.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -//#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" -#include "rtc_base/experiments/field_trial_parser.h" -//#include "rtc_base/thread_annotations.h" - -namespace webrtc { - -// This class implements a leaky-bucket packet pacing algorithm. It handles the -// logic of determining which packets to send when, but the actual timing of -// the processing is done externally (e.g. RtpPacketPacer). Furthermore, the -// forwarding of packets when they are ready to be sent is also handled -// externally, via the PacingController::PacketSender interface. -class PacingController { - public: - class PacketSender: RtpPacketSender { - public: - virtual ~PacketSender() = default; - virtual void SendPacket(std::unique_ptr packet, - const PacedPacketInfo& cluster_info) = 0; - // Should be called after each call to SendPacket(). - virtual std::vector> FetchFec() = 0; - virtual std::vector> GeneratePadding( - DataSize size) = 0; - - // TODO(bugs.webrtc.org/11340): Make pure virtual once downstream projects - // have been updated. - virtual void OnAbortedRetransmissions( - uint32_t ssrc, - std::vector sequence_numbers) {} - virtual absl::optional GetRtxSsrcForMedia(uint32_t ssrc) const { - return absl::nullopt; - } - }; - - // Expected max pacer delay. If ExpectedQueueTime() is higher than - // this value, the packet producers should wait (eg drop frames rather than - // encoding them). Bitrate sent may temporarily exceed target set by - // UpdateBitrate() so that this limit will be upheld. - static const TimeDelta kMaxExpectedQueueLength; - // If no media or paused, wake up at least every `kPausedProcessIntervalMs` in - // order to send a keep-alive packet so we don't get stuck in a bad state due - // to lack of feedback. - static const TimeDelta kPausedProcessInterval; - - static const TimeDelta kMinSleepTime; - - // Allow probes to be processed slightly ahead of inteded send time. Currently - // set to 1ms as this is intended to allow times be rounded down to the - // nearest millisecond. - static const TimeDelta kMaxEarlyProbeProcessing; - - PacingController(PacketSender* packet_sender, - const WebRtcKeyValueConfig& field_trials); - - ~PacingController(); - - // Adds the packet to the queue and calls PacketRouter::SendPacket() when - // it's time to send. - void EnqueuePacket(std::unique_ptr packet); - - // ABSL_DEPRECATED("Use CreateProbeClusters instead") - void CreateProbeCluster(DataRate bitrate, int cluster_id); - void CreateProbeClusters( - std::vector probe_cluster_configs); - - void Pause(); // Temporarily pause all sending. - void Resume(); // Resume sending packets. - bool IsPaused() const; - - void SetCongested(bool congested); - - // Sets the pacing rates. Must be called once before packets can be sent. - void SetPacingRates(DataRate pacing_rate, DataRate padding_rate); - DataRate pacing_rate() const { return adjusted_media_rate_; } - - // Currently audio traffic is not accounted by pacer and passed through. - // With the introduction of audio BWE audio traffic will be accounted for - // the pacer budget calculation. The audio traffic still will be injected - // at high priority. - void SetAccountForAudioPackets(bool account_for_audio); - void SetIncludeOverhead(); - - void SetTransportOverhead(DataSize overhead_per_packet); - // The pacer is allowed to send enqued packets in bursts and can build up a - // packet "debt" that correspond to approximately the send rate during - // 'burst_interval'. - void SetSendBurstInterval(TimeDelta burst_interval); - - // Returns the time when the oldest packet was queued. - Timestamp OldestPacketEnqueueTime() const; - - // Number of packets in the pacer queue. - size_t QueueSizePackets() const; - // Number of packets in the pacer queue per media type (RtpPacketMediaType - // values are used as lookup index). - const std::array& SizeInPacketsPerRtpPacketMediaType() - const; - // Totals size of packets in the pacer queue. - DataSize QueueSizeData() const; - - // Current buffer level, i.e. max of media and padding debt. - DataSize CurrentBufferLevel() const; - - // Returns the time when the first packet was sent. - absl::optional FirstSentPacketTime() const; - - // Returns the number of milliseconds it will take to send the current - // packets in the queue, given the current size and bitrate, ignoring prio. - TimeDelta ExpectedQueueTime() const; - - void SetQueueTimeLimit(TimeDelta limit); - - // Enable bitrate probing. Enabled by default, mostly here to simplify - // testing. Must be called before any packets are being sent to have an - // effect. - void SetProbingEnabled(bool enabled); - - // Returns the next time we expect ProcessPackets() to be called. - Timestamp NextSendTime() const; - - // Check queue of pending packets and send them or padding packets, if budget - // is available. - void ProcessPackets(); - - bool IsProbing() const; - - private: - TimeDelta UpdateTimeAndGetElapsed(Timestamp now); - bool ShouldSendKeepalive(Timestamp now) const; - - // Updates the number of bytes that can be sent for the next time interval. - void UpdateBudgetWithElapsedTime(TimeDelta delta); - void UpdateBudgetWithSentData(DataSize size); - void UpdatePaddingBudgetWithSentData(DataSize size); - - DataSize PaddingToAdd(DataSize recommended_probe_size, - DataSize data_sent) const; - - std::unique_ptr GetPendingPacket( - const PacedPacketInfo& pacing_info, - Timestamp target_send_time, - Timestamp now); - void OnPacketSent(RtpPacketMediaType packet_type, - DataSize packet_size, - Timestamp send_time); - void MaybeUpdateMediaRateDueToLongQueue(Timestamp now); - - Timestamp CurrentTime() const; - - // Helper methods for packet that may not be paced. Returns a finite Timestamp - // if a packet type is configured to not be paced and the packet queue has at - // least one packet of that type. Otherwise returns - // Timestamp::MinusInfinity(). - Timestamp NextUnpacedSendTime() const; - - PacketSender* const packet_sender_; - const WebRtcKeyValueConfig& field_trials_; - - const bool drain_large_queues_; - const bool send_padding_if_silent_; - const bool pace_audio_; - const bool ignore_transport_overhead_; - const bool fast_retransmissions_; - - TimeDelta min_packet_limit_; - DataSize transport_overhead_per_packet_; - TimeDelta send_burst_interval_; - - // TODO(webrtc:9716): Remove this when we are certain clocks are monotonic. - // The last millisecond timestamp returned by `clock_`. - mutable Timestamp last_timestamp_; - bool paused_; - - // Amount of outstanding data for media and padding. - DataSize media_debt_; - DataSize padding_debt_; - - // The target pacing rate, signaled via SetPacingRates(). - DataRate pacing_rate_; - // The media send rate, which might adjusted from pacing_rate_, e.g. if the - // pacing queue is growing too long. - DataRate adjusted_media_rate_; - // The padding target rate. We aim to fill up to this rate with padding what - // is not already used by media. - DataRate padding_rate_; - - BitrateProber prober_; - bool probing_send_failure_; - - Timestamp last_process_time_; - Timestamp last_send_time_; - absl::optional first_sent_packet_time_; - bool seen_first_packet_; - - PrioritizedPacketQueue packet_queue_; - - bool congested_; - - TimeDelta queue_time_limit_; - bool account_for_audio_; - bool include_overhead_; -}; -} // namespace webrtc - -#endif // MODULES_PACING_PACING_CONTROLLER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc b/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc deleted file mode 100644 index 2b890b78df..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.cc +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2022 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 "modules/pacing/prioritized_packet_queue.h" - -#include - -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "RTC/RtpPacket.hpp" -// #include "rtc_base/checks.h" - -namespace webrtc { -namespace { - -constexpr int kAudioPrioLevel = 0; - -int GetPriorityForType(RtpPacketMediaType type) { - // Lower number takes priority over higher. - switch (type) { - case RtpPacketMediaType::kAudio: - // Audio is always prioritized over other packet types. - return kAudioPrioLevel; - case RtpPacketMediaType::kRetransmission: - // Send retransmissions before new media. - return kAudioPrioLevel + 1; - case RtpPacketMediaType::kVideo: - case RtpPacketMediaType::kForwardErrorCorrection: - // Video has "normal" priority, in the old speak. - // Send redundancy concurrently to video. If it is delayed it might have a - // lower chance of being useful. - return kAudioPrioLevel + 2; - case RtpPacketMediaType::kPadding: - // Packets that are in themselves likely useless, only sent to keep the - // BWE high. - return kAudioPrioLevel + 3; - } - // RTC_CHECK_NOTREACHED(); -} - -} // namespace - -DataSize PrioritizedPacketQueue::QueuedPacket::PacketSize() const { - return DataSize::bytes(packet->GetPayloadLength() + packet->GetPayloadPadding()); -} - -PrioritizedPacketQueue::StreamQueue::StreamQueue(Timestamp creation_time) - : last_enqueue_time_(creation_time) {} - -bool PrioritizedPacketQueue::StreamQueue::EnqueuePacket(QueuedPacket packet, - int priority_level) { - bool first_packet_at_level = packets_[priority_level].empty(); - packets_[priority_level].push_back(std::move(packet)); - return first_packet_at_level; -} - -PrioritizedPacketQueue::QueuedPacket -PrioritizedPacketQueue::StreamQueue::DequePacket(int priority_level) { - // RTC_DCHECK(!packets_[priority_level].empty()); - QueuedPacket packet = std::move(packets_[priority_level].front()); - packets_[priority_level].pop_front(); - return packet; -} - -bool PrioritizedPacketQueue::StreamQueue::HasPacketsAtPrio( - int priority_level) const { - return !packets_[priority_level].empty(); -} - -bool PrioritizedPacketQueue::StreamQueue::IsEmpty() const { - for (const std::deque& queue : packets_) { - if (!queue.empty()) { - return false; - } - } - return true; -} - -Timestamp PrioritizedPacketQueue::StreamQueue::LeadingPacketEnqueueTime( - int priority_level) const { - // RTC_DCHECK(!packets_[priority_level].empty()); - return packets_[priority_level].begin()->enqueue_time; -} - -Timestamp PrioritizedPacketQueue::StreamQueue::LastEnqueueTime() const { - return last_enqueue_time_; -} - -PrioritizedPacketQueue::PrioritizedPacketQueue(Timestamp creation_time) - : queue_time_sum_(TimeDelta::Zero()), - pause_time_sum_(TimeDelta::Zero()), - size_packets_(0), - size_packets_per_media_type_({}), - size_payload_(DataSize::Zero()), - last_update_time_(creation_time), - paused_(false), - last_culling_time_(creation_time), - top_active_prio_level_(-1) {} - -void PrioritizedPacketQueue::Push(Timestamp enqueue_time, - std::unique_ptr packet) { - StreamQueue* stream_queue; - auto [it, inserted] = streams_.emplace(packet->GetSsrc(), nullptr); - if (inserted) { - it->second = absl::make_unique(enqueue_time); - } - stream_queue = it->second.get(); - - auto enqueue_time_iterator = - enqueue_times_.insert(enqueue_times_.end(), enqueue_time); - // RTC_DCHECK(packet->packet_type().has_value()); - RtpPacketMediaType packet_type = packet->GetPacketType(); - int prio_level = GetPriorityForType(packet_type); - // RTC_DCHECK_GE(prio_level, 0); - // RTC_DCHECK_LT(prio_level, kNumPriorityLevels); - QueuedPacket queued_packed = {.packet = std::move(packet), - .enqueue_time = enqueue_time, - .enqueue_time_iterator = enqueue_time_iterator}; - // In order to figure out how much time a packet has spent in the queue - // while not in a paused state, we subtract the total amount of time the - // queue has been paused so far, and when the packet is popped we subtract - // the total amount of time the queue has been paused at that moment. This - // way we subtract the total amount of time the packet has spent in the - // queue while in a paused state. - UpdateAverageQueueTime(enqueue_time); - queued_packed.enqueue_time -= pause_time_sum_; - ++size_packets_; - ++size_packets_per_media_type_[static_cast(packet_type)]; - size_payload_ += queued_packed.PacketSize(); - - if (stream_queue->EnqueuePacket(std::move(queued_packed), prio_level)) { - // Number packets at `prio_level` for this steam is now non-zero. - streams_by_prio_[prio_level].push_back(stream_queue); - } - if (top_active_prio_level_ < 0 || prio_level < top_active_prio_level_) { - top_active_prio_level_ = prio_level; - } - - static constexpr TimeDelta kTimeout = TimeDelta::Millis<500>(); - if (enqueue_time - last_culling_time_ > kTimeout) { - for (auto it = streams_.begin(); it != streams_.end();) { - if (it->second->IsEmpty() && - it->second->LastEnqueueTime() + kTimeout < enqueue_time) { - streams_.erase(it++); - } else { - ++it; - } - } - last_culling_time_ = enqueue_time; - } -} - -std::unique_ptr PrioritizedPacketQueue::Pop() { - if (size_packets_ == 0) { - return nullptr; - } - - // RTC_DCHECK_GE(top_active_prio_level_, 0); - StreamQueue& stream_queue = *streams_by_prio_[top_active_prio_level_].front(); - QueuedPacket packet = stream_queue.DequePacket(top_active_prio_level_); - --size_packets_; - //RTC_DCHECK(packet.packet->packet_type().has_value()); - RtpPacketMediaType packet_type = packet.packet->GetPacketType(); - --size_packets_per_media_type_[static_cast(packet_type)]; - // RTC_DCHECK_GE(size_packets_per_media_type_[static_cast(packet_type)], 0); - size_payload_ -= packet.PacketSize(); - - // Calculate the total amount of time spent by this packet in the queue - // while in a non-paused state. Note that the `pause_time_sum_ms_` was - // subtracted from `packet.enqueue_time_ms` when the packet was pushed, and - // by subtracting it now we effectively remove the time spent in in the - // queue while in a paused state. - TimeDelta time_in_non_paused_state = - last_update_time_ - packet.enqueue_time - pause_time_sum_; - queue_time_sum_ -= time_in_non_paused_state; - - // RTC_DCHECK(size_packets_ > 0 || queue_time_sum_ == TimeDelta::Zero()); - - // RTC_CHECK(packet.enqueue_time_iterator != enqueue_times_.end()); - enqueue_times_.erase(packet.enqueue_time_iterator); - - // Remove StreamQueue from head of fifo-queue for this prio level, and - // and add it to the end if it still has packets. - streams_by_prio_[top_active_prio_level_].pop_front(); - if (stream_queue.HasPacketsAtPrio(top_active_prio_level_)) { - streams_by_prio_[top_active_prio_level_].push_back(&stream_queue); - } else if (streams_by_prio_[top_active_prio_level_].empty()) { - // No stream queues have packets at this prio level, find top priority - // that is not empty. - if (size_packets_ == 0) { - top_active_prio_level_ = -1; - } else { - for (int i = 0; i < kNumPriorityLevels; ++i) { - if (!streams_by_prio_[i].empty()) { - top_active_prio_level_ = i; - break; - } - } - } - } - - return std::move(packet.packet); -} - -int PrioritizedPacketQueue::SizeInPackets() const { - return size_packets_; -} - -DataSize PrioritizedPacketQueue::SizeInPayloadBytes() const { - return size_payload_; -} - -bool PrioritizedPacketQueue::Empty() const { - return size_packets_ == 0; -} - -const std::array& -PrioritizedPacketQueue::SizeInPacketsPerRtpPacketMediaType() const { - return size_packets_per_media_type_; -} - -Timestamp PrioritizedPacketQueue::LeadingPacketEnqueueTime( - RtpPacketMediaType type) const { - const int priority_level = GetPriorityForType(type); - if (streams_by_prio_[priority_level].empty()) { - return Timestamp::MinusInfinity(); - } - return streams_by_prio_[priority_level].front()->LeadingPacketEnqueueTime( - priority_level); -} - -Timestamp PrioritizedPacketQueue::OldestEnqueueTime() const { - return enqueue_times_.empty() ? Timestamp::MinusInfinity() - : enqueue_times_.front(); -} - -TimeDelta PrioritizedPacketQueue::AverageQueueTime() const { - if (size_packets_ == 0) { - return TimeDelta::Zero(); - } - return queue_time_sum_ / size_packets_; -} - -void PrioritizedPacketQueue::UpdateAverageQueueTime(Timestamp now) { - // RTC_CHECK_GE(now, last_update_time_); - if (now == last_update_time_) { - return; - } - - TimeDelta delta = now - last_update_time_; - - if (paused_) { - pause_time_sum_ += delta; - } else { - queue_time_sum_ += delta * size_packets_; - } - - last_update_time_ = now; -} - -void PrioritizedPacketQueue::SetPauseState(bool paused, Timestamp now) { - UpdateAverageQueueTime(now); - paused_ = paused; -} - -} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h deleted file mode 100644 index 13d1025aef..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/prioritized_packet_queue.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2022 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. - */ - -#ifndef MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ -#define MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ - -#include - -#include -#include -#include -#include - -#include "api/units/data_size.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" -#include "RTC/RtpPacket.hpp" -//#include "modules/rtp_rtcp/source/rtp_packet_to_send.h" - -namespace webrtc { - -class PrioritizedPacketQueue { - public: - explicit PrioritizedPacketQueue(Timestamp creation_time); - PrioritizedPacketQueue(const PrioritizedPacketQueue&) = delete; - PrioritizedPacketQueue& operator=(const PrioritizedPacketQueue&) = delete; - - // Add a packet to the queue. The enqueue time is used for queue time stats - // and to report the leading packet enqueue time per packet type. - void Push(Timestamp enqueue_time, std::unique_ptr packet); - - // Remove the next packet from the queue. Packets a prioritized first - // according to packet type, in the following order: - // - audio, retransmissions, video / fec, padding - // For each packet type, we use one FIFO-queue per SSRC and emit from - // those queues in a round-robin fashion. - std::unique_ptr Pop(); - - // Number of packets in the queue. - int SizeInPackets() const; - - // Sum of all payload bytes in the queue, where the payload is calculated - // as `packet->payload_size() + packet->padding_size()`. - DataSize SizeInPayloadBytes() const; - - // Convenience method for `SizeInPackets() == 0`. - bool Empty() const; - - // Total packets in the queue per media type (RtpPacketMediaType values are - // used as lookup index). - const std::array& SizeInPacketsPerRtpPacketMediaType() - const; - - // The enqueue time of the next packet this queue will return via the Pop() - // method, for the given packet type. If queue has no packets, of that type, - // returns Timestamp::MinusInfinity(). - Timestamp LeadingPacketEnqueueTime(RtpPacketMediaType type) const; - - // Enqueue time of the oldest packet in the queue, - // Timestamp::MinusInfinity() if queue is empty. - Timestamp OldestEnqueueTime() const; - - // Average queue time for the packets currently in the queue. - // The queuing time is calculated from Push() to the last UpdateQueueTime() - // call - with any time spent in a paused state subtracted. - // Returns TimeDelta::Zero() for an empty queue. - TimeDelta AverageQueueTime() const; - - // Called during packet processing or when pause stats changes. Since the - // AverageQueueTime() method does not look at the wall time, this method - // needs to be called before querying queue time. - void UpdateAverageQueueTime(Timestamp now); - - // Set the pause state, while `paused` is true queuing time is not counted. - void SetPauseState(bool paused, Timestamp now); - - private: - static constexpr int kNumPriorityLevels = 4; - - class QueuedPacket { - public: - DataSize PacketSize() const; - - std::unique_ptr packet; - Timestamp enqueue_time; - std::list::iterator enqueue_time_iterator; - }; - - // Class containing packets for an RTP stream. - // For each priority level, packets are simply stored in a fifo queue. - class StreamQueue { - public: - explicit StreamQueue(Timestamp creation_time); - StreamQueue(StreamQueue&&) = default; - StreamQueue& operator=(StreamQueue&&) = default; - - StreamQueue(const StreamQueue&) = delete; - StreamQueue& operator=(const StreamQueue&) = delete; - - // Enqueue packet at the given priority level. Returns true if the packet - // count for that priority level went from zero to non-zero. - bool EnqueuePacket(QueuedPacket packet, int priority_level); - - QueuedPacket DequePacket(int priority_level); - - bool HasPacketsAtPrio(int priority_level) const; - bool IsEmpty() const; - Timestamp LeadingPacketEnqueueTime(int priority_level) const; - Timestamp LastEnqueueTime() const; - - private: - std::deque packets_[kNumPriorityLevels]; - Timestamp last_enqueue_time_; - }; - - // Cumulative sum, over all packets, of time spent in the queue. - TimeDelta queue_time_sum_; - // Cumulative sum of time the queue has spent in a paused state. - TimeDelta pause_time_sum_; - // Total number of packets stored in this queue. - int size_packets_; - // Total number of packets stored in this queue per RtpPacketMediaType. - std::array size_packets_per_media_type_; - // Sum of payload sizes for all packts stored in this queue. - DataSize size_payload_; - // The last time queue/pause time sums were updated. - Timestamp last_update_time_; - bool paused_; - - // Last time `streams_` was culled for inactive streams. - Timestamp last_culling_time_; - - // Map from SSRC to packet queues for the associated RTP stream. - std::unordered_map> streams_; - - // For each priority level, a queue of StreamQueues which have at least one - // packet pending for that prio level. - std::deque streams_by_prio_[kNumPriorityLevels]; - - // The first index into `stream_by_prio_` that is non-empty. - int top_active_prio_level_; - - // Ordered list of enqueue times. Additions are always increasing and added to - // the end. QueuedPacket instances have a iterators into this list for fast - // removal. - std::list enqueue_times_; -}; - -} // namespace webrtc - -#endif // MODULES_PACING_PRIORITIZED_PACKET_QUEUE_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h deleted file mode 100644 index 4c692b171b..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_pacer.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ - -#ifndef MODULES_PACING_RTP_PACKET_PACER_H_ -#define MODULES_PACING_RTP_PACKET_PACER_H_ - -#include - -#include - -#include "absl/types/optional.h" -#include "api/units/data_rate.h" -#include "api/units/data_size.h" -#include "api/units/time_delta.h" -#include "api/units/timestamp.h" -#include "modules/pacing/rtp_packet_sender.h" - -namespace webrtc { - -class RtpPacketPacer { - public: - virtual ~RtpPacketPacer() = default; - - virtual void CreateProbeClusters( - std::vector probe_cluster_configs) = 0; - - // Temporarily pause all sending. - virtual void Pause() = 0; - - // Resume sending packets. - virtual void Resume() = 0; - - virtual void SetCongested(bool congested) = 0; - - // Sets the pacing rates. Must be called once before packets can be sent. - virtual void SetPacingRates(DataRate pacing_rate, DataRate padding_rate) = 0; - - // Time since the oldest packet currently in the queue was added. - virtual TimeDelta OldestPacketWaitTime() const = 0; - - // Sum of payload + padding bytes of all packets currently in the pacer queue. - virtual DataSize QueueSizeData() const = 0; - - // Returns the time when the first packet was sent. - virtual absl::optional FirstSentPacketTime() const = 0; - - // Returns the expected number of milliseconds it will take to send the - // current packets in the queue, given the current size and bitrate, ignoring - // priority. - virtual TimeDelta ExpectedQueueTime() const = 0; - - // Set the average upper bound on pacer queuing delay. The pacer may send at - // a higher rate than what was configured via SetPacingRates() in order to - // keep ExpectedQueueTimeMs() below `limit_ms` on average. - virtual void SetQueueTimeLimit(TimeDelta limit) = 0; - - // Currently audio traffic is not accounted by pacer and passed through. - // With the introduction of audio BWE audio traffic will be accounted for - // the pacer budget calculation. The audio traffic still will be injected - // at high priority. - virtual void SetAccountForAudioPackets(bool account_for_audio) = 0; - virtual void SetIncludeOverhead() = 0; - virtual void SetTransportOverhead(DataSize overhead_per_packet) = 0; -}; - -} // namespace webrtc -#endif // MODULES_PACING_RTP_PACKET_PACER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h b/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h deleted file mode 100644 index 63036244f0..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/pacing/rtp_packet_sender.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 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. - */ - -#ifndef MODULES_RTP_RTCP_INCLUDE_RTP_PACKET_SENDER_H_ -#define MODULES_RTP_RTCP_INCLUDE_RTP_PACKET_SENDER_H_ - -#include -#include - -#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h" - -namespace webrtc { - -class RtpPacketSender { - public: - virtual ~RtpPacketSender() = default; - - // Insert a set of packets into queue, for eventual transmission. Based on the - // type of packets, they will be prioritized and scheduled relative to other - // packets and the current target send rate. - virtual void EnqueuePackets( - std::vector> packets) = 0; -}; - -} // namespace webrtc - -#endif // MODULES_RTP_RTCP_INCLUDE_RTP_PACKET_SENDER_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 7e3f0661ec..3bc3253376 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -41,11 +41,6 @@ bool IsEnabled(const WebRtcKeyValueConfig& field_trials, return field_trials.Lookup(key).find("Enabled") == 0; } -bool IsNotDisabled(const WebRtcKeyValueConfig& field_trials, - absl::string_view key) { - return field_trials.Lookup(key).find("Disabled") != 1; -} - double ReadBackoffFactor(const WebRtcKeyValueConfig& key_value_config) { std::string experiment_string = key_value_config.Lookup(kBweBackOffFactorExperiment); @@ -79,7 +74,7 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, current_bitrate_(max_configured_bitrate_), latest_estimated_throughput_(current_bitrate_), link_capacity_(), - rate_control_state_(RateControlState::kRcHold), + rate_control_state_(kRcHold), time_last_bitrate_change_(Timestamp::MinusInfinity()), time_last_bitrate_decrease_(Timestamp::MinusInfinity()), time_first_throughput_estimate_(Timestamp::MinusInfinity()), @@ -94,28 +89,28 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, no_bitrate_increase_in_alr_( IsEnabled(*key_value_config, "WebRTC-DontIncreaseDelayBasedBweInAlr")), + smoothing_experiment_(false), estimate_bounded_backoff_( - IsNotDisabled(*key_value_config, - "WebRTC-Bwe-EstimateBoundedBackoff")), + IsEnabled(*key_value_config, "WebRTC-Bwe-EstimateBoundedBackoff")), + estimate_bounded_increase_( + IsEnabled(*key_value_config, "WebRTC-Bwe-EstimateBoundedIncrease")), initial_backoff_interval_("initial_backoff_interval"), - link_capacity_fix_("link_capacity_fix") { - ParseFieldTrial( - {&disable_estimate_bounded_increase_, &estimate_bounded_increase_ratio_, - &ignore_throughput_limit_if_network_estimate_, - &ignore_network_estimate_decrease_, &increase_to_network_estimate_}, - key_value_config->Lookup("WebRTC-Bwe-EstimateBoundedIncrease")); + low_throughput_threshold_("low_throughput", DataRate::Zero()), + capacity_deviation_ratio_threshold_("cap_thr", 0.2), + capacity_limit_deviation_factor_("cap_lim", 1) { // E.g - // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/ - ParseFieldTrial({&initial_backoff_interval_, &link_capacity_fix_}, + // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms, + // low_throughput:50kbps/ + ParseFieldTrial({&initial_backoff_interval_, &low_throughput_threshold_}, key_value_config->Lookup("WebRTC-BweAimdRateControlConfig")); if (initial_backoff_interval_) { MS_DEBUG_TAG(bwe, "Using aimd rate control with initial back-off interval: %s", ToString(*initial_backoff_interval_).c_str()); } - /*MS_DEBUG_TAG(bwe, "Using aimd rate control with back off factor: %f ", beta_); + MS_DEBUG_TAG(bwe, "Using aimd rate control with back off factor: %f ", beta_); ParseFieldTrial( {&capacity_deviation_ratio_threshold_, &capacity_limit_deviation_factor_}, - key_value_config->Lookup("WebRTC-Bwe-AimdRateControl-NetworkState"));*/ + key_value_config->Lookup("WebRTC-Bwe-AimdRateControl-NetworkState")); } AimdRateControl::~AimdRateControl() {} @@ -208,7 +203,7 @@ DataRate AimdRateControl::Update(const RateControlInput* input, } } - ChangeBitrate(*input, at_time); + current_bitrate_ = ChangeBitrate(current_bitrate_, *input, at_time); return current_bitrate_; } @@ -219,7 +214,7 @@ void AimdRateControl::SetInApplicationLimitedRegion(bool in_alr) { void AimdRateControl::SetEstimate(DataRate bitrate, Timestamp at_time) { bitrate_is_initialized_ = true; DataRate prev_bitrate = current_bitrate_; - current_bitrate_ = ClampBitrate(bitrate); + current_bitrate_ = ClampBitrate(bitrate, bitrate); time_last_bitrate_change_ = at_time; if (current_bitrate_ < prev_bitrate) { time_last_bitrate_decrease_ = at_time; @@ -250,22 +245,23 @@ double AimdRateControl::GetNearMaxIncreaseRateBpsPerSecond() const { } TimeDelta AimdRateControl::GetExpectedBandwidthPeriod() const { - const TimeDelta kMinPeriod = TimeDelta::seconds(2); + const TimeDelta kMinPeriod = + smoothing_experiment_ ? TimeDelta::ms(500) : TimeDelta::seconds(2); const TimeDelta kDefaultPeriod = TimeDelta::seconds(3); const TimeDelta kMaxPeriod = TimeDelta::seconds(50); double increase_rate_bps_per_second = GetNearMaxIncreaseRateBpsPerSecond(); if (!last_decrease_) - return kDefaultPeriod; + return smoothing_experiment_ ? kMinPeriod : kDefaultPeriod; double time_to_recover_decrease_seconds = last_decrease_->bps() / increase_rate_bps_per_second; TimeDelta period = TimeDelta::seconds(time_to_recover_decrease_seconds); return period.Clamped(kMinPeriod, kMaxPeriod); } -void AimdRateControl::ChangeBitrate(const RateControlInput& input, - Timestamp at_time) { - absl::optional new_bitrate; +DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, + const RateControlInput& input, + Timestamp at_time) { DataRate estimated_throughput = input.estimated_throughput.value_or(latest_estimated_throughput_); if (input.estimated_throughput) @@ -276,87 +272,82 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input, // we will end up with a valid estimate. if (!bitrate_is_initialized_ && input.bw_state != BandwidthUsage::kBwOverusing) - return; + return current_bitrate_; ChangeState(input, at_time); switch (rate_control_state_) { - case RateControlState::kRcHold: + case kRcHold: break; - case RateControlState::kRcIncrease: { + case kRcIncrease: if (estimated_throughput > link_capacity_.UpperBound()) link_capacity_.Reset(); - // We limit the new bitrate based on the troughput to avoid unlimited - // bitrate increases. We allow a bit more lag at very low rates to not too - // easily get stuck if the encoder produces uneven outputs. - DataRate increase_limit = - 1.5 * estimated_throughput + DataRate::kbps(10); - if (ignore_throughput_limit_if_network_estimate_ && network_estimate_ && - network_estimate_->link_capacity_upper.IsFinite()) { - // If we have a Network estimate, we do allow the estimate to increase. - increase_limit = network_estimate_->link_capacity_upper * - estimate_bounded_increase_ratio_.Get(); - } else if (send_side_ && in_alr_ && no_bitrate_increase_in_alr_) { - // Do not increase the delay based estimate in alr since the estimator - // will not be able to get transport feedback necessary to detect if - // the new estimate is correct. - // If we have previously increased above the limit (for instance due to - // probing), we don't allow further changes. - increase_limit = current_bitrate_; - } - - if (current_bitrate_ < increase_limit) { - DataRate increased_bitrate = DataRate::MinusInfinity(); - if (increase_to_network_estimate_ && network_estimate_ && - network_estimate_->link_capacity_upper.IsFinite()) { - increased_bitrate = increase_limit; - } else if (link_capacity_.has_estimate()) { + // Do not increase the delay based estimate in alr since the estimator + // will not be able to get transport feedback necessary to detect if + // the new estimate is correct. + if (!(send_side_ && in_alr_ && no_bitrate_increase_in_alr_)) { + if (link_capacity_.has_estimate()) { // The link_capacity estimate is reset if the measured throughput // is too far from the estimate. We can therefore assume that our // target rate is reasonably close to link capacity and use additive // increase. DataRate additive_increase = AdditiveRateIncrease(at_time, time_last_bitrate_change_); - increased_bitrate = current_bitrate_ + additive_increase; + new_bitrate += additive_increase; } else { // If we don't have an estimate of the link capacity, use faster ramp // up to discover the capacity. DataRate multiplicative_increase = MultiplicativeRateIncrease( - at_time, time_last_bitrate_change_, current_bitrate_); - increased_bitrate = current_bitrate_ + multiplicative_increase; + at_time, time_last_bitrate_change_, new_bitrate); + new_bitrate += multiplicative_increase; } - new_bitrate = std::min(increased_bitrate, increase_limit); } + time_last_bitrate_change_ = at_time; break; - } - - case RateControlState::kRcDecrease: { - DataRate decreased_bitrate = DataRate::PlusInfinity(); - // Set bit rate to something slightly lower than the measured throughput - // to get rid of any self-induced delay. - decreased_bitrate = estimated_throughput * beta_; - if (decreased_bitrate > current_bitrate_ && !link_capacity_fix_) { - // TODO(terelius): The link_capacity estimate may be based on old - // throughput measurements. Relying on them may lead to unnecessary - // BWE drops. + case kRcDecrease: + // TODO(srte): Remove when |estimate_bounded_backoff_| has been validated. + if (network_estimate_ && capacity_deviation_ratio_threshold_ && + !estimate_bounded_backoff_) { + estimated_throughput = std::max(estimated_throughput, + network_estimate_->link_capacity_lower); + } + 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. + new_bitrate = estimated_throughput * beta_; + if (new_bitrate > current_bitrate_) { + // Avoid increasing the rate when over-using. + if (link_capacity_.has_estimate()) { + new_bitrate = beta_ * link_capacity_.estimate(); + } + } + if (estimate_bounded_backoff_ && network_estimate_) { + new_bitrate = std::max( + new_bitrate, network_estimate_->link_capacity_lower * beta_); + } + } else { + new_bitrate = estimated_throughput; if (link_capacity_.has_estimate()) { - decreased_bitrate = beta_ * link_capacity_.estimate(); + new_bitrate = std::max(new_bitrate, link_capacity_.estimate()); } + new_bitrate = std::min(new_bitrate, low_throughput_threshold_.Get()); } - // Avoid increasing the rate when over-using. - if (decreased_bitrate < current_bitrate_) { - new_bitrate = decreased_bitrate; - } + new_bitrate = std::min(new_bitrate, current_bitrate_); if (bitrate_is_initialized_ && estimated_throughput < current_bitrate_) { - if (!new_bitrate.has_value()) { - last_decrease_ = DataRate::Zero(); + constexpr double kDegradationFactor = 0.9; + if (smoothing_experiment_ && + new_bitrate < kDegradationFactor * beta_ * current_bitrate_) { + // If bitrate decreases more than a normal back off after overuse, it + // indicates a real network degradation. We do not let such a decrease + // to determine the bandwidth estimation period. + last_decrease_ = absl::nullopt; } else { - last_decrease_ = current_bitrate_ - *new_bitrate; + last_decrease_ = current_bitrate_ - new_bitrate; } } if (estimated_throughput < link_capacity_.LowerBound()) { @@ -368,34 +359,38 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input, bitrate_is_initialized_ = true; link_capacity_.OnOveruseDetected(estimated_throughput); // Stay on hold until the pipes are cleared. - rate_control_state_ = RateControlState::kRcHold; + rate_control_state_ = kRcHold; time_last_bitrate_change_ = at_time; time_last_bitrate_decrease_ = at_time; break; - } + default: MS_THROW_ERROR("unknown rate control state"); } - - current_bitrate_ = ClampBitrate(new_bitrate.value_or(current_bitrate_)); + return ClampBitrate(new_bitrate, estimated_throughput); } -DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const { - if (!disable_estimate_bounded_increase_ && network_estimate_ && - network_estimate_->link_capacity_upper.IsFinite()) { - DataRate upper_bound = network_estimate_->link_capacity_upper * - estimate_bounded_increase_ratio_.Get(); - if (ignore_network_estimate_decrease_) { - upper_bound = std::max(upper_bound, current_bitrate_); +DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate, + DataRate estimated_throughput) const { + // Allow the estimate to increase as long as alr is not detected to ensure + // that there is no BWE values that can make the estimate stuck at a too + // low bitrate. If an encoder can not produce the bitrate necessary to + // fully use the capacity, alr will sooner or later trigger. + if (!(send_side_ && no_bitrate_increase_in_alr_)) { + // Don't change the bit rate if the send side is too far off. + // We allow a bit more lag at very low rates to not too easily get stuck if + // the encoder produces uneven outputs. + const DataRate max_bitrate = + 1.5 * estimated_throughput + DataRate::kbps(10); + if (new_bitrate > current_bitrate_ && new_bitrate > max_bitrate) { + new_bitrate = std::max(current_bitrate_, max_bitrate); } - new_bitrate = std::min(upper_bound, new_bitrate); } - if (estimate_bounded_backoff_ && network_estimate_ && - network_estimate_->link_capacity_lower.IsFinite() && - new_bitrate < current_bitrate_) { - new_bitrate = std::min( - current_bitrate_, - std::max(new_bitrate, network_estimate_->link_capacity_lower * beta_)); + + if (network_estimate_ && + (estimate_bounded_increase_ || capacity_limit_deviation_factor_)) { + DataRate upper_bound = network_estimate_->link_capacity_upper; + new_bitrate = std::min(new_bitrate, upper_bound); } new_bitrate = std::max(new_bitrate, min_configured_bitrate_); return new_bitrate; @@ -427,18 +422,18 @@ void AimdRateControl::ChangeState(const RateControlInput& input, Timestamp at_time) { switch (input.bw_state) { case BandwidthUsage::kBwNormal: - if (rate_control_state_ == RateControlState::kRcHold) { + if (rate_control_state_ == kRcHold) { time_last_bitrate_change_ = at_time; - rate_control_state_ = RateControlState::kRcIncrease; + rate_control_state_ = kRcIncrease; } break; case BandwidthUsage::kBwOverusing: - if (rate_control_state_ != RateControlState::kRcDecrease) { - rate_control_state_ = RateControlState::kRcDecrease; + if (rate_control_state_ != kRcDecrease) { + rate_control_state_ = kRcDecrease; } break; case BandwidthUsage::kBwUnderusing: - rate_control_state_ = RateControlState::kRcHold; + rate_control_state_ = kRcHold; break; default: MS_THROW_ERROR("unknown input.bw_state"); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h index 6e4ead24a4..cefea2f2a5 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -65,8 +65,6 @@ class AimdRateControl { TimeDelta GetExpectedBandwidthPeriod() const; private: - enum class RateControlState { kRcHold, kRcIncrease, kRcDecrease }; - friend class GoogCcStatePrinter; // Update the target bitrate based on, among other things, the current rate // control state, the current target bitrate and the estimated throughput. @@ -75,9 +73,14 @@ class AimdRateControl { // in the "decrease" state the bitrate will be decreased to slightly below the // current throughput. When in the "hold" state the bitrate will be kept // constant to allow built up queues to drain. - void ChangeBitrate(const RateControlInput& input, Timestamp at_time); - - DataRate ClampBitrate(DataRate new_bitrate) const; + DataRate ChangeBitrate(DataRate current_bitrate, + const RateControlInput& input, + Timestamp at_time); + // Clamps new_bitrate to within the configured min bitrate and a linear + // function of the throughput, so that the new bitrate can't grow too + // large compared to the bitrate actually being received by the other end. + DataRate ClampBitrate(DataRate new_bitrate, + DataRate estimated_throughput) const; DataRate MultiplicativeRateIncrease(Timestamp at_time, Timestamp last_ms, DataRate current_bitrate) const; @@ -104,22 +107,20 @@ class AimdRateControl { // Allow the delay based estimate to only increase as long as application // limited region (alr) is not detected. const bool no_bitrate_increase_in_alr_; + const bool smoothing_experiment_; // Use estimated link capacity lower bound if it is higher than the // acknowledged rate when backing off due to overuse. const bool estimate_bounded_backoff_; - // If false, uses estimated link capacity upper bound * - // `estimate_bounded_increase_ratio_` as upper limit for the estimate. - FieldTrialFlag disable_estimate_bounded_increase_{"Disabled"}; - FieldTrialParameter estimate_bounded_increase_ratio_{"ratio", 1.0}; - FieldTrialParameter ignore_throughput_limit_if_network_estimate_{ - "ignore_acked", false}; - FieldTrialParameter increase_to_network_estimate_{"immediate_incr", - false}; - FieldTrialParameter ignore_network_estimate_decrease_{"ignore_decr", - false}; + // Use estimated link capacity upper bound as upper limit for increasing + // bitrate over the acknowledged rate. + const bool estimate_bounded_increase_; absl::optional last_decrease_; FieldTrialOptional initial_backoff_interval_; - FieldTrialFlag link_capacity_fix_; + FieldTrialParameter low_throughput_threshold_; + // Deprecated, enable |estimate_bounded_backoff_| instead. + FieldTrialOptional capacity_deviation_ratio_threshold_; + // Deprecated, enable |estimate_bounded_increase_| instead. + FieldTrialOptional capacity_limit_deviation_factor_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc index fce739060d..daa9c861d2 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.cc @@ -124,7 +124,14 @@ bool InterArrival::PacketInOrder(uint32_t timestamp) { // that in IsNewerTimestamp() in module_common_types.h. uint32_t timestamp_diff = timestamp - current_timestamp_group_.first_timestamp; - return timestamp_diff < 0x80000000; + + const static uint32_t int_middle = 0x80000000; + + if (timestamp_diff == int_middle) { + return timestamp > current_timestamp_group_.first_timestamp; + } + + return timestamp_diff < int_middle; } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h index cc1ed08d8f..8ce1c145d1 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/inter_arrival.h @@ -35,10 +35,6 @@ class InterArrival { double timestamp_to_ms_coeff, bool enable_burst_grouping); - InterArrival() = delete; - InterArrival(const InterArrival&) = delete; - InterArrival& operator=(const InterArrival&) = delete; - // This function returns true if a delta was computed, or false if the current // group is still incomplete or if only one group has been completed. // |timestamp| is the timestamp. @@ -91,6 +87,8 @@ class InterArrival { double timestamp_to_ms_coeff_; bool burst_grouping_; int num_consecutive_reordered_packets_; + + RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(InterArrival); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h b/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h index 40ff2af2b1..8d08edf630 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h @@ -214,16 +214,5 @@ enum class RtpPacketSendResult { kPacketNotFound // SSRC/sequence number does not map to an available packet. }; -// NOTE! `kNumMediaTypes` must be kept in sync with RtpPacketMediaType! -static constexpr size_t kNumMediaTypes = 5; -enum class RtpPacketMediaType : size_t { - kAudio, // Audio media packets. - kVideo, // Video media packets. - kRetransmission, // Retransmisions, sent as response to NACK. - kForwardErrorCorrection, // FEC packets. - kPadding = kNumMediaTypes - 1, // RTX or plain padding sent to maintain BWE. - // Again, don't forget to udate `kNumMediaTypes` if you add another value! -}; - } // namespace webrtc #endif // MODULES_RTP_RTCP_INCLUDE_RTP_RTCP_DEFINES_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc b/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc deleted file mode 100644 index bd6e69bbed..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.cc +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2016 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 "rtc_base/rate_limiter.h" - -#include - -#include "DepLibUV.hpp" -#include "absl/types/optional.h" -// #include "system_wrappers/include/clock.h" - -namespace webrtc { - -RateLimiter::RateLimiter(Clock* clock, int64_t max_window_ms) - : current_rate_(max_window_ms, RateStatistics::kBpsScale), - window_size_ms_(max_window_ms), - max_rate_bps_(std::numeric_limits::max()) {} - -RateLimiter::~RateLimiter() {} - -// Usage note: This class is intended be usable in a scenario where different -// threads may call each of the the different method. For instance, a network -// thread trying to send data calling TryUseRate(), the bandwidth estimator -// calling SetMaxRate() and a timed maintenance thread periodically updating -// the RTT. -bool RateLimiter::TryUseRate(size_t packet_size_bytes) { - //MutexLock lock(&lock_); - int64_t now_ms = DepLibUV::GetTimeMsInt64(); - absl::optional current_rate = current_rate_.Rate(now_ms); - if (current_rate) { - // If there is a current rate, check if adding bytes would cause maximum - // bitrate target to be exceeded. If there is NOT a valid current rate, - // allow allocating rate even if target is exceeded. This prevents - // problems - // at very low rates, where for instance retransmissions would never be - // allowed due to too high bitrate caused by a single packet. - - size_t bitrate_addition_bps = - (packet_size_bytes * 8 * 1000) / window_size_ms_; - if (*current_rate + bitrate_addition_bps > max_rate_bps_) - return false; - } - - current_rate_.Update(packet_size_bytes, now_ms); - return true; -} - -void RateLimiter::SetMaxRate(uint32_t max_rate_bps) { - // MutexLock lock(&lock_); - max_rate_bps_ = max_rate_bps; -} - -// Set the window size over which to measure the current bitrate. -// For retransmissions, this is typically the RTT. -bool RateLimiter::SetWindowSize(int64_t window_size_ms) { - // MutexLock lock(&lock_); - window_size_ms_ = window_size_ms; - return current_rate_.SetWindowSize(window_size_ms, - DepLibUV::GetTimeMsInt64()); -} - -} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h b/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h deleted file mode 100644 index e27657b01b..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/rtc_base/rate_limiter.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ - -#ifndef RTC_BASE_RATE_LIMITER_H_ -#define RTC_BASE_RATE_LIMITER_H_ - -#include -#include - -#include "rtc_base/rate_statistics.h" - -namespace webrtc { - -class Clock; - -// Class used to limit a bitrate, making sure the average does not exceed a -// maximum as measured over a sliding window. This class is thread safe; all -// methods will acquire (the same) lock befeore executing. -class RateLimiter { - public: - RateLimiter(Clock* clock, int64_t max_window_ms); - - RateLimiter() = delete; - RateLimiter(const RateLimiter&) = delete; - RateLimiter& operator=(const RateLimiter&) = delete; - - ~RateLimiter(); - - // Try to use rate to send bytes. Returns true on success and if so updates - // current rate. - bool TryUseRate(size_t packet_size_bytes); - - // Set the maximum bitrate, in bps, that this limiter allows to send. - void SetMaxRate(uint32_t max_rate_bps); - - // Set the window size over which to measure the current bitrate. - // For example, irt retransmissions, this is typically the RTT. - // Returns true on success and false if window_size_ms is out of range. - bool SetWindowSize(int64_t window_size_ms); - - private: - RateStatistics current_rate_; - int64_t window_size_ms_; - uint32_t max_rate_bps_; -}; - -} // namespace webrtc - -#endif // RTC_BASE_RATE_LIMITER_H_ diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 69d8256aeb..610646fd9f 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -8,7 +8,6 @@ libwebrtc_sources = [ 'libwebrtc/rtc_base/experiments/rate_control_settings.cc', 'libwebrtc/rtc_base/experiments/struct_parameters_parser.cc', 'libwebrtc/rtc_base/network/sent_packet.cc', - 'libwebrtc/rtc_base/rate_limiter.cc', 'libwebrtc/call/rtp_transport_controller_send.cc', 'libwebrtc/api/transport/bitrate_settings.cc', 'libwebrtc/api/transport/field_trial_based_config.cc', @@ -22,8 +21,6 @@ libwebrtc_sources = [ 'libwebrtc/api/network_state_predictor.cc', 'libwebrtc/modules/pacing/interval_budget.cc', 'libwebrtc/modules/pacing/bitrate_prober.cc', - 'libwebrtc/modules/pacing/pacing_controller.cc', - 'libwebrtc/modules/pacing/prioritized_packet_queue.cc', 'libwebrtc/modules/pacing/paced_sender.cc', 'libwebrtc/modules/remote_bitrate_estimator/overuse_detector.cc', 'libwebrtc/modules/remote_bitrate_estimator/overuse_estimator.cc', @@ -41,6 +38,7 @@ libwebrtc_sources = [ 'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc', 'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc', + 'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc', diff --git a/worker/include/RTC/RtpPacket.hpp b/worker/include/RTC/RtpPacket.hpp index 2e0d1f48de..0dece98d5b 100644 --- a/worker/include/RTC/RtpPacket.hpp +++ b/worker/include/RTC/RtpPacket.hpp @@ -4,8 +4,6 @@ #include "common.hpp" #include "Utils.hpp" #include "RTC/Codecs/PayloadDescriptorHandler.hpp" -// FIXME: temp just to compile -#include "libwebrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" #include #include #include @@ -155,10 +153,6 @@ namespace RTC { return (const uint8_t*)this->header; } - // FIXME: temp just to compile - const webrtc::RtpPacketMediaType GetPacketType() const { - return webrtc::RtpPacketMediaType::kAudio; - } size_t GetSize() const { From a43e06e68c1b9acffbfb584d563304a193c1d2cc Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 14 Nov 2022 20:07:29 +0200 Subject: [PATCH 05/70] Enable Loss v2 --- .../bitrate_controller/loss_based_bwe_v2.cc | 38 +++++++++++++++---- worker/src/DepLibWebRTC.cpp | 2 +- 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 6b5bc79632..2ad27dcf38 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -8,6 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ #define MS_CLASS "webrtc::LossBasedBweV2" +#define MS_LOG_DEV_LEVEL 3 #include "modules/bitrate_controller/loss_based_bwe_v2.h" @@ -32,6 +33,7 @@ #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/experiments/field_trial_list.h" #include "rtc_base/experiments/field_trial_parser.h" + #include "Logger.hpp" namespace webrtc { @@ -79,15 +81,14 @@ double GetLossProbability(double inherent_loss, DataRate loss_limited_bandwidth, DataRate sending_rate) { if (inherent_loss < 0.0 || inherent_loss > 1.0) { - /*MS_WARN_TAG(bwe, "Terent loss must be in [0,1]: %", inherent_loss);*/ + MS_WARN_TAG(bwe, "Terent loss must be in [0,1]: %f", inherent_loss); inherent_loss = std::min(std::max(inherent_loss, 0.0), 1.0); } if (!sending_rate.IsFinite()) { - //MS_WARN_TAG(bwe, "The sending rate must be finite: %s", sending_rate); + MS_WARN_TAG(bwe, "The sending rate must be finite: %lld", sending_rate.kbps()); } if (!loss_limited_bandwidth.IsFinite()) { - /*RTC_LOG(LS_WARNING) << "The loss limited bandwidth must be finite: " - << ToString(loss_limited_bandwidth);*/ + MS_WARN_TAG(bwe, "The loss limited bandwidth must be finite: %lld", loss_limited_bandwidth.kbps()); } double loss_probability = inherent_loss; @@ -104,13 +105,11 @@ double GetLossProbability(double inherent_loss, LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) : config_(CreateConfig(key_value_config)) { if (!config_.has_value()) { -/* RTC_LOG(LS_VERBOSE) << "The configuration does not specify that the " - "estimator should be enabled, disabling it.";*/ + MS_WARN_TAG(bwe, "The configuration does not specify that the estimator should be enabled, disabling it."); return; } if (!IsConfigValid()) { -/* RTC_LOG(LS_WARNING) - << "The configuration is not valid, disabling the estimator.";*/ + MS_WARN_TAG(bwe,"The configuration is not valid, disabling the estimator."); config_.reset(); return; } @@ -124,6 +123,7 @@ LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) } bool LossBasedBweV2::IsEnabled() const { + // MS_DEBUG_DEV("Loss V2 is Enabled: %d ", config_.has_value()); return config_.has_value(); } @@ -431,10 +431,32 @@ absl::optional LossBasedBweV2::CreateConfig( config->bandwidth_cap_at_high_loss_rate = bandwidth_cap_at_high_loss_rate.Get(); config->slope_of_bwe_high_loss_func = slope_of_bwe_high_loss_func.Get(); + + + std::string candidate_factors_str; + + MS_DEBUG_TAG(bwe, "Loss V2 settings: "); + + for (double candidate_factor : config->candidate_factors) { + MS_DEBUG_TAG(bwe, "Candidate factor %f", candidate_factor); + } + + MS_DEBUG_TAG(bwe, "Loss V2 settings: " + "pacing bandwidth_rampup_upper_bound_factor: %f" + ", rampup_acceleration_max_factor: %f" + ", rampup_acceleration_maxout_time: %lld" + ", higher_bandwidth_bias_factor: %f" + ", NotIncreaseIfInherentLossLessThanAverageLoss: %d", + config->bandwidth_rampup_upper_bound_factor, + config->rampup_acceleration_max_factor, + config->rampup_acceleration_maxout_time.ms(), + config->higher_bandwidth_bias_factor, + config->not_increase_if_inherent_loss_less_than_average_loss); return config; } bool LossBasedBweV2::IsConfigValid() const { + MS_DEBUG_DEV("Validating lossV2 config"); if (!config_.has_value()) { return false; } diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index e303c90ec4..54970b0680 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -9,7 +9,7 @@ /* Static. */ static std::once_flag globalInitOnce; -static constexpr char FieldTrials[] = "WebRTC-Bwe-AlrLimitedBackoff/Enabled/"; +static constexpr char FieldTrials[] = "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; /* Static methods. */ From f498894b5727fb04a7245c937ed8a47c6675c6ca Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 17 Nov 2022 17:27:25 +0200 Subject: [PATCH 06/70] Sync with latest Loss v2 changes. --- worker/deps/libwebrtc/README.md | 5 + .../bitrate_controller/loss_based_bwe_v2.cc | 200 ++++++++++++------ .../bitrate_controller/loss_based_bwe_v2.h | 39 +++- .../send_side_bandwidth_estimation.cc | 25 ++- .../send_side_bandwidth_estimation.h | 7 +- .../goog_cc/goog_cc_network_control.cc | 53 +++-- .../goog_cc/goog_cc_network_control.h | 2 - .../goog_cc/probe_controller.cc | 199 ++++++++++------- .../goog_cc/probe_controller.h | 32 ++- worker/src/DepLibWebRTC.cpp | 3 +- 10 files changed, 368 insertions(+), 197 deletions(-) diff --git a/worker/deps/libwebrtc/README.md b/worker/deps/libwebrtc/README.md index 2d5ae8cf13..48814038e8 100644 --- a/worker/deps/libwebrtc/README.md +++ b/worker/deps/libwebrtc/README.md @@ -10,3 +10,8 @@ The file `libwebrtc/mediasoup_helpers.h` includes some utilities to plug mediaso The file `worker/deps/libwebrtc/deps/abseil-cpp/abseil-cpp/absl/synchronization/internal/graphcycles.cc` has `#include ` added to it to fix CI builds with Clang. The file `meson.build` is written for using with Meson build system. + +Updated and synced with: + +* libwebrtc branch: main +* libwebrtc commit: 17887eb04a84e426b604d4c084898c3147c7d810 \ No newline at end of file diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 2ad27dcf38..d99abe5fe7 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -44,6 +44,10 @@ bool IsValid(DataRate datarate) { return datarate.IsFinite(); } +bool IsValid(absl::optional datarate) { + return datarate.has_value() && IsValid(datarate.value()); +} + bool IsValid(Timestamp timestamp) { return timestamp.IsFinite(); } @@ -132,8 +136,9 @@ bool LossBasedBweV2::IsReady() const { num_observations_ > 0; } -DataRate LossBasedBweV2::GetBandwidthEstimate( - DataRate delay_based_limit) const { +LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { + Result result; + result.state = current_state_; if (!IsReady()) { /* if (!IsEnabled()) { RTC_LOG(LS_WARNING) @@ -147,18 +152,22 @@ DataRate LossBasedBweV2::GetBandwidthEstimate( RTC_LOG(LS_WARNING) << "The estimator must receive enough loss " "statistics before it can be used."; } - }*/ - return IsValid(delay_based_limit) ? delay_based_limit - : DataRate::PlusInfinity(); + } */ + result.bandwidth_estimate = IsValid(delay_based_estimate_) + ? delay_based_estimate_ + : DataRate::PlusInfinity(); + return result; } - if (delay_based_limit.IsFinite()) { - return std::min({current_estimate_.loss_limited_bandwidth, - GetInstantUpperBound(), delay_based_limit}); + if (IsValid(delay_based_estimate_)) { + result.bandwidth_estimate = + std::min({current_estimate_.loss_limited_bandwidth, + GetInstantUpperBound(), delay_based_estimate_}); } else { - return std::min(current_estimate_.loss_limited_bandwidth, - GetInstantUpperBound()); + result.bandwidth_estimate = std::min( + current_estimate_.loss_limited_bandwidth, GetInstantUpperBound()); } + return result; } void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) { @@ -179,24 +188,45 @@ void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) { } } -void LossBasedBweV2::SetMinBitrate(DataRate min_bitrate) { +void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate, + DataRate max_bitrate) { if (IsValid(min_bitrate)) { min_bitrate_ = min_bitrate; } else { -/* RTC_LOG(LS_WARNING) << "The min bitrate must be finite: " + /*RTC_LOG(LS_WARNING) << "The min bitrate must be finite: " << ToString(min_bitrate);*/ } + + if (IsValid(max_bitrate)) { + max_bitrate_ = max_bitrate; + } else { +/* RTC_LOG(LS_WARNING) << "The max bitrate must be finite: " + << ToString(max_bitrate);*/ + } +} + +void LossBasedBweV2::SetProbeBitrate(absl::optional probe_bitrate) { + if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) { + if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) { + probe_bitrate_ = probe_bitrate.value(); + } + } } void LossBasedBweV2::UpdateBandwidthEstimate( std::vector packet_results, DataRate delay_based_estimate, - BandwidthUsage delay_detector_state) { + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity) { + delay_based_estimate_ = delay_based_estimate; + upper_link_capacity_ = upper_link_capacity; if (!IsEnabled()) { /* RTC_LOG(LS_WARNING) << "The estimator must be enabled before it can be used.";*/ return; } + SetProbeBitrate(probe_bitrate); if (packet_results.empty()) { /* RTC_LOG(LS_VERBOSE) << "The estimate cannot be updated without any loss statistics.";*/ @@ -215,7 +245,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate( ChannelParameters best_candidate = current_estimate_; double objective_max = std::numeric_limits::lowest(); - for (ChannelParameters candidate : GetCandidates(delay_based_estimate)) { + for (ChannelParameters candidate : GetCandidates()) { NewtonsMethodUpdate(candidate); const double candidate_objective = GetObjective(candidate); @@ -239,34 +269,75 @@ void LossBasedBweV2::UpdateBandwidthEstimate( current_estimate_.loss_limited_bandwidth; } - // Bound the estimate increase if: - // 1. The estimate is limited due to loss, and - // 2. The estimate has been increased for less than `delayed_increase_window` - // ago, and - // 3. The best candidate is greater than bandwidth_limit_in_current_window. - if (limited_due_to_loss_candidate_ && - recovering_after_loss_timestamp_.IsFinite() && - recovering_after_loss_timestamp_ + config_->delayed_increase_window > - last_send_time_most_recent_observation_ && - best_candidate.loss_limited_bandwidth > - bandwidth_limit_in_current_window_) { - best_candidate.loss_limited_bandwidth = bandwidth_limit_in_current_window_; - } - limited_due_to_loss_candidate_ = - delay_based_estimate.IsFinite() && - best_candidate.loss_limited_bandwidth < delay_based_estimate; - - if (limited_due_to_loss_candidate_ && + if (IsBandwidthLimitedDueToLoss()) { + // Bound the estimate increase if: + // 1. The estimate has been increased for less than + // `delayed_increase_window` ago, and + // 2. The best candidate is greater than bandwidth_limit_in_current_window. + if (recovering_after_loss_timestamp_.IsFinite() && + recovering_after_loss_timestamp_ + config_->delayed_increase_window > + last_send_time_most_recent_observation_ && + best_candidate.loss_limited_bandwidth > + bandwidth_limit_in_current_window_) { + best_candidate.loss_limited_bandwidth = + bandwidth_limit_in_current_window_; + } + + bool increasing_when_loss_limited = + IsEstimateIncreasingWhenLossLimited(best_candidate); + // Bound the best candidate by the acked bitrate unless there is a recent + // probe result. + if (increasing_when_loss_limited && !IsValid(probe_bitrate_) && + IsValid(acknowledged_bitrate_)) { + best_candidate.loss_limited_bandwidth = + IsValid(best_candidate.loss_limited_bandwidth) + ? std::min(best_candidate.loss_limited_bandwidth, + config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_)) + : config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_); + } + + // Use probe bitrate as the estimate as probe bitrate is trusted to be + // correct. After being used, the probe bitrate is reset. + if (config_->probe_integration_enabled && IsValid(probe_bitrate_)) { + best_candidate.loss_limited_bandwidth = + std::min(probe_bitrate_, best_candidate.loss_limited_bandwidth); + probe_bitrate_ = DataRate::MinusInfinity(); + } + } + + if (IsEstimateIncreasingWhenLossLimited(best_candidate)) { + current_state_ = LossBasedState::kIncreasing; + } else if (IsValid(delay_based_estimate_) && + best_candidate.loss_limited_bandwidth < delay_based_estimate_) { + current_state_ = LossBasedState::kDecreasing; + } else if (IsValid(delay_based_estimate_) && + best_candidate.loss_limited_bandwidth == delay_based_estimate_) { + current_state_ = LossBasedState::kDelayBasedEstimate; + } + current_estimate_ = best_candidate; + + if (IsBandwidthLimitedDueToLoss() && (recovering_after_loss_timestamp_.IsInfinite() || recovering_after_loss_timestamp_ + config_->delayed_increase_window < last_send_time_most_recent_observation_)) { - bandwidth_limit_in_current_window_ = std::max( - kCongestionControllerMinBitrate, - best_candidate.loss_limited_bandwidth * config_->max_increase_factor); + bandwidth_limit_in_current_window_ = + std::max(kCongestionControllerMinBitrate, + current_estimate_.loss_limited_bandwidth * + config_->max_increase_factor); recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_; } +} - current_estimate_ = best_candidate; +bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited( + const ChannelParameters& best_candidate) { + return (current_estimate_.loss_limited_bandwidth < + best_candidate.loss_limited_bandwidth || + (current_estimate_.loss_limited_bandwidth == + best_candidate.loss_limited_bandwidth && + current_state_ == LossBasedState::kIncreasing)) && + IsBandwidthLimitedDueToLoss(); } // Returns a `LossBasedBweV2::Config` iff the `key_value_config` specifies a @@ -337,6 +408,10 @@ absl::optional LossBasedBweV2::CreateConfig( "BandwidthCapAtHighLossRate", DataRate::kbps(500.0)); FieldTrialParameter slope_of_bwe_high_loss_func( "SlopeOfBweHighLossFunc", 1000); + FieldTrialParameter probe_integration_enabled("ProbeIntegrationEnabled", + false); + FieldTrialParameter bound_by_upper_link_capacity_when_loss_limited( + "BoundByUpperLinkCapacityWhenLossLimited", true); if (key_value_config) { ParseFieldTrial({&enabled, &bandwidth_rampup_upper_bound_factor, @@ -369,9 +444,11 @@ absl::optional LossBasedBweV2::CreateConfig( &delayed_increase_window, &use_acked_bitrate_only_when_overusing, ¬_increase_if_inherent_loss_less_than_average_loss, + &probe_integration_enabled, &high_loss_rate_threshold, &bandwidth_cap_at_high_loss_rate, - &slope_of_bwe_high_loss_func}, + &slope_of_bwe_high_loss_func, + &bound_by_upper_link_capacity_when_loss_limited}, key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2")); } @@ -431,6 +508,9 @@ absl::optional LossBasedBweV2::CreateConfig( config->bandwidth_cap_at_high_loss_rate = bandwidth_cap_at_high_loss_rate.Get(); config->slope_of_bwe_high_loss_func = slope_of_bwe_high_loss_func.Get(); + config->probe_integration_enabled = probe_integration_enabled.Get(); + config->bound_by_upper_link_capacity_when_loss_limited = + bound_by_upper_link_capacity_when_loss_limited.Get(); std::string candidate_factors_str; @@ -662,33 +742,25 @@ double LossBasedBweV2::GetAverageReportedLossRatio() const { return num_lost_packets / num_packets; } -DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound( - DataRate delay_based_estimate) const { - DataRate candidate_bandwidth_upper_bound = DataRate::PlusInfinity(); - if (limited_due_to_loss_candidate_) { +DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound() const { + DataRate candidate_bandwidth_upper_bound = max_bitrate_; + if (IsBandwidthLimitedDueToLoss() && + IsValid(bandwidth_limit_in_current_window_)) { candidate_bandwidth_upper_bound = bandwidth_limit_in_current_window_; } if (config_->trendline_integration_enabled) { candidate_bandwidth_upper_bound = std::min(GetInstantUpperBound(), candidate_bandwidth_upper_bound); - if (IsValid(delay_based_estimate)) { + if (IsValid(delay_based_estimate_)) { candidate_bandwidth_upper_bound = - std::min(delay_based_estimate, candidate_bandwidth_upper_bound); + std::min(delay_based_estimate_, candidate_bandwidth_upper_bound); } } if (!acknowledged_bitrate_.has_value()) return candidate_bandwidth_upper_bound; - candidate_bandwidth_upper_bound = - IsValid(candidate_bandwidth_upper_bound) - ? std::min(candidate_bandwidth_upper_bound, - config_->bandwidth_rampup_upper_bound_factor * - (*acknowledged_bitrate_)) - : config_->bandwidth_rampup_upper_bound_factor * - (*acknowledged_bitrate_); - if (config_->rampup_acceleration_max_factor > 0.0) { const TimeDelta time_since_bandwidth_reduced = std::min( config_->rampup_acceleration_maxout_time, @@ -704,8 +776,8 @@ DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound( return candidate_bandwidth_upper_bound; } -std::vector LossBasedBweV2::GetCandidates( - DataRate delay_based_estimate) const { +std::vector LossBasedBweV2::GetCandidates() + const { std::vector bandwidths; bool can_increase_bitrate = TrendlineEsimateAllowBitrateIncrease(); for (double candidate_factor : config_->candidate_factors) { @@ -723,16 +795,16 @@ std::vector LossBasedBweV2::GetCandidates( config_->bandwidth_backoff_lower_bound_factor); } - if (IsValid(delay_based_estimate) && + if (IsValid(delay_based_estimate_) && config_->append_delay_based_estimate_candidate) { if (can_increase_bitrate && - delay_based_estimate > current_estimate_.loss_limited_bandwidth) { - bandwidths.push_back(delay_based_estimate); + delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) { + bandwidths.push_back(delay_based_estimate_); } } const DataRate candidate_bandwidth_upper_bound = - GetCandidateBandwidthUpperBound(delay_based_estimate); + GetCandidateBandwidthUpperBound(); std::vector candidates; candidates.resize(bandwidths.size()); @@ -880,11 +952,11 @@ DataRate LossBasedBweV2::GetSendingRate( } DataRate LossBasedBweV2::GetInstantUpperBound() const { - return cached_instant_upper_bound_.value_or(DataRate::PlusInfinity()); + return cached_instant_upper_bound_.value_or(max_bitrate_); } void LossBasedBweV2::CalculateInstantUpperBound() { - DataRate instant_limit = DataRate::PlusInfinity(); + DataRate instant_limit = max_bitrate_; const double average_reported_loss_ratio = GetAverageReportedLossRatio(); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { instant_limit = config_->instant_upper_bound_bandwidth_balance / @@ -900,6 +972,12 @@ void LossBasedBweV2::CalculateInstantUpperBound() { } } + if (IsBandwidthLimitedDueToLoss()) { + if (IsValid(upper_link_capacity_) && + config_->bound_by_upper_link_capacity_when_loss_limited) { + instant_limit = std::min(instant_limit, upper_link_capacity_); + } + } cached_instant_upper_bound_ = instant_limit; } @@ -1015,4 +1093,8 @@ bool LossBasedBweV2::PushBackObservation( return true; } +bool LossBasedBweV2::IsBandwidthLimitedDueToLoss() const { + return current_state_ != LossBasedState::kDelayBasedEstimate; +} + } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 9dc2215395..80284f83ec 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -26,8 +26,21 @@ namespace webrtc { +// State of the loss based estimate, which can be either increasing/decreasing +// when network is loss limited, or equal to the delay based estimate. +enum class LossBasedState { + kIncreasing = 0, + kDecreasing = 1, + kDelayBasedEstimate = 2 +}; + class LossBasedBweV2 { public: + struct Result { + ~Result() = default; + DataRate bandwidth_estimate = DataRate::Zero(); + LossBasedState state = LossBasedState::kDelayBasedEstimate; + }; // Creates a disabled `LossBasedBweV2` if the // `key_value_config` is not valid. explicit LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config); @@ -43,15 +56,17 @@ class LossBasedBweV2 { bool IsReady() const; // Returns `DataRate::PlusInfinity` if no BWE can be calculated. - DataRate GetBandwidthEstimate(DataRate delay_based_limit) const; + Result GetLossBasedResult() const; void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); void SetBandwidthEstimate(DataRate bandwidth_estimate); - void SetMinBitrate(DataRate min_bitrate); + void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); void UpdateBandwidthEstimate( std::vector packet_results, DataRate delay_based_estimate, - BandwidthUsage delay_detector_state); + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity); private: struct ChannelParameters { @@ -94,6 +109,8 @@ class LossBasedBweV2 { double high_loss_rate_threshold = 1.0; DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity(); double slope_of_bwe_high_loss_func = 1000.0; + bool probe_integration_enabled = false; + bool bound_by_upper_link_capacity_when_loss_limited = false; }; struct Derivatives { @@ -123,9 +140,8 @@ class LossBasedBweV2 { // Returns `0.0` if not enough loss statistics have been received. double GetAverageReportedLossRatio() const; - std::vector GetCandidates( - DataRate delay_based_estimate) const; - DataRate GetCandidateBandwidthUpperBound(DataRate delay_based_estimate) const; + std::vector GetCandidates() const; + DataRate GetCandidateBandwidthUpperBound() const; Derivatives GetDerivatives(const ChannelParameters& channel_parameters) const; double GetFeasibleInherentLoss( const ChannelParameters& channel_parameters) const; @@ -151,9 +167,13 @@ class LossBasedBweV2 { bool PushBackObservation(std::vector packet_results, BandwidthUsage delay_detector_state); void UpdateTrendlineEstimator( - const std::vector packet_feedbacks, + const std::vector& packet_feedbacks, Timestamp at_time); void UpdateDelayDetector(BandwidthUsage delay_detector_state); + bool IsEstimateIncreasingWhenLossLimited( + const ChannelParameters& best_candidate); + bool IsBandwidthLimitedDueToLoss() const; + void SetProbeBitrate(absl::optional probe_bitrate); absl::optional acknowledged_bitrate_; absl::optional config_; @@ -171,6 +191,11 @@ class LossBasedBweV2 { DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); bool limited_due_to_loss_candidate_ = false; DataRate min_bitrate_ = DataRate::kbps(1); + DataRate max_bitrate_ = DataRate::PlusInfinity(); + LossBasedState current_state_ = LossBasedState::kDelayBasedEstimate; + DataRate probe_bitrate_ = DataRate::PlusInfinity(); + DataRate delay_based_estimate_ = DataRate::PlusInfinity(); + DataRate upper_link_capacity_ = DataRate::PlusInfinity(); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 3bfa2ca740..0d9498da2d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -222,6 +222,7 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation( bitrate_threshold_(kDefaultBitrateThreshold), loss_based_bandwidth_estimator_v1_(key_value_config), loss_based_bandwidth_estimator_v2_(key_value_config), + loss_based_state_(LossBasedState::kDelayBasedEstimate), disable_receiver_limit_caps_only_("Disabled") { if (BweLossExperimentIsEnabled()) { @@ -238,7 +239,8 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation( ParseFieldTrial({&disable_receiver_limit_caps_only_}, key_value_config->Lookup("WebRTC-Bwe-ReceiverLimitCapsOnly")); if (LossBasedBandwidthEstimatorV2Enabled()) { - loss_based_bandwidth_estimator_v2_.SetMinBitrate(min_bitrate_configured_); + loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate( + min_bitrate_configured_, max_bitrate_configured_); } } @@ -302,6 +304,8 @@ void SendSideBandwidthEstimation::SetMinMaxBitrate(DataRate min_bitrate, } else { max_bitrate_configured_ = kDefaultMaxBitrate; } + loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate(min_bitrate_configured_, + max_bitrate_configured_); } int SendSideBandwidthEstimation::GetMinBitrate() const { @@ -315,8 +319,8 @@ DataRate SendSideBandwidthEstimation::target_rate() const { return std::max(min_bitrate_configured_, target); } -DataRate SendSideBandwidthEstimation::delay_based_limit() const { - return delay_based_limit_; +LossBasedState SendSideBandwidthEstimation::loss_based_state() const { + return loss_based_state_; } DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const { @@ -359,14 +363,17 @@ void SendSideBandwidthEstimation::SetAcknowledgedRate( void SendSideBandwidthEstimation::UpdateLossBasedEstimator( const TransportPacketsFeedback& report, - BandwidthUsage delay_detector_state) { + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity) { if (LossBasedBandwidthEstimatorV1Enabled()) { loss_based_bandwidth_estimator_v1_.UpdateLossStatistics( report.packet_feedbacks, report.feedback_time); } if (LossBasedBandwidthEstimatorV2Enabled()) { loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( - report.packet_feedbacks, delay_based_limit_, delay_detector_state); + report.packet_feedbacks, delay_based_limit_, delay_detector_state, + probe_bitrate, upper_link_capacity); UpdateEstimate(report.feedback_time); } } @@ -514,10 +521,10 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) { } if (LossBasedBandwidthEstimatorV2ReadyForUse()) { - DataRate new_bitrate = - loss_based_bandwidth_estimator_v2_.GetBandwidthEstimate( - delay_based_limit_); - UpdateTargetBitrate(new_bitrate, at_time); + LossBasedBweV2::Result result = + loss_based_bandwidth_estimator_v2_.GetLossBasedResult(); + loss_based_state_ = result.state; + UpdateTargetBitrate(result.bandwidth_estimate, at_time); return; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 00cfd71724..90faa460ea 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -79,7 +79,7 @@ class SendSideBandwidthEstimation { void OnRouteChange(); DataRate target_rate() const; - DataRate delay_based_limit() const; + LossBasedState loss_based_state() const; uint8_t fraction_loss() const { return last_fraction_loss_; } TimeDelta round_trip_time() const { return last_round_trip_time_; } @@ -113,7 +113,9 @@ class SendSideBandwidthEstimation { void SetAcknowledgedRate(absl::optional acknowledged_rate, Timestamp at_time); void UpdateLossBasedEstimator(const TransportPacketsFeedback& report, - BandwidthUsage delay_detector_state); + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity); private: friend class GoogCcStatePrinter; @@ -194,6 +196,7 @@ class SendSideBandwidthEstimation { DataRate bitrate_threshold_; LossBasedBandwidthEstimation loss_based_bandwidth_estimator_v1_; LossBasedBweV2 loss_based_bandwidth_estimator_v2_; + LossBasedState loss_based_state_; FieldTrialFlag disable_receiver_limit_caps_only_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 5436c81c3f..1848d1f28c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -63,6 +63,19 @@ bool IsEnabled(const WebRtcKeyValueConfig* config, absl::string_view key) { bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Disabled") != 0; } + +BandwidthLimitedCause GetBandwidthLimitedCause( + LossBasedState loss_based_state) { + switch (loss_based_state) { + case LossBasedState::kDecreasing: + return BandwidthLimitedCause::kLossLimitedBweDecreasing; + case LossBasedState::kIncreasing: + return BandwidthLimitedCause::kLossLimitedBweIncreasing; + default: + return BandwidthLimitedCause::kDelayBasedLimited; + } +} + } // namespace GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, @@ -87,8 +100,6 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, pace_at_max_of_bwe_and_lower_link_capacity_( IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtMaxOfBweAndLowerLinkCapacity")), - pace_at_loss_based_bwe_when_loss_( - IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtLossBaseBweWhenLoss")), probe_controller_( new ProbeController(key_value_config_)), congestion_window_pushback_controller_( @@ -118,8 +129,7 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, config.stream_based_config.min_total_allocated_bitrate.value_or( DataRate::Zero())), max_padding_rate_(config.stream_based_config.max_padding_rate.value_or( - DataRate::Zero())), - max_total_allocated_bitrate_(DataRate::Zero()) { + DataRate::Zero())) { //RTC_DCHECK(config.constraints.at_time.IsFinite()); ParseFieldTrial( {&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_}, @@ -192,8 +202,6 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( *total_bitrate, msg.at_time); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); - - max_total_allocated_bitrate_ = *total_bitrate; } initial_config_.reset(); } @@ -287,17 +295,12 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig( if (msg.requests_alr_probing) { probe_controller_->EnablePeriodicAlrProbing(*msg.requests_alr_probing); } - if (msg.max_total_allocated_bitrate && - *msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) { - if (rate_control_settings_.TriggerProbeOnMaxAllocatedBitrateChange()) { - update.probe_cluster_configs = - probe_controller_->OnMaxTotalAllocatedBitrate( - *msg.max_total_allocated_bitrate, msg.at_time); - } else { - probe_controller_->SetMaxBitrate(*msg.max_total_allocated_bitrate); - } - max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate; + if (msg.max_total_allocated_bitrate) { + update.probe_cluster_configs = + probe_controller_->OnMaxTotalAllocatedBitrate( + *msg.max_total_allocated_bitrate, msg.at_time); } + bool pacing_changed = false; if (msg.pacing_factor && *msg.pacing_factor != pacing_factor_) { pacing_factor_ = *msg.pacing_factor; @@ -566,8 +569,9 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time, result.target_bitrate); } - bandwidth_estimation_->UpdateLossBasedEstimator(report, - result.delay_detector_state); + bandwidth_estimation_->UpdateLossBasedEstimator( + report, result.delay_detector_state, probe_bitrate, + estimate_ ? estimate_->link_capacity_upper : DataRate::PlusInfinity()); if (result.updated) { // Update the estimate in the ProbeController, in case we want to probe. MaybeTriggerOnNetworkChanged(&update, report.feedback_time); @@ -631,10 +635,6 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( uint8_t fraction_loss = bandwidth_estimation_->fraction_loss(); TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time(); DataRate loss_based_target_rate = bandwidth_estimation_->target_rate(); - bool bwe_limited_due_to_packet_loss = - loss_based_target_rate.IsFinite() && - bandwidth_estimation_->delay_based_limit().IsFinite() && - loss_based_target_rate < bandwidth_estimation_->delay_based_limit(); DataRate pushback_target_rate = loss_based_target_rate; // BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(), @@ -697,7 +697,9 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( update->target_rate = target_rate_msg; auto probes = probe_controller_->SetEstimatedBitrate( - loss_based_target_rate, bwe_limited_due_to_packet_loss, at_time); + loss_based_target_rate, + GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state()), + at_time); update->probe_cluster_configs.insert(update->probe_cluster_configs.end(), probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); @@ -713,10 +715,7 @@ PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const { // Pacing rate is based on target rate before congestion window pushback, // because we don't want to build queues in the pacer when pushback occurs. DataRate pacing_rate = DataRate::Zero(); - if ((pace_at_max_of_bwe_and_lower_link_capacity_ || - (pace_at_loss_based_bwe_when_loss_ && - last_loss_based_target_rate_ >= delay_based_bwe_->last_estimate())) && - estimate_) { + if (pace_at_max_of_bwe_and_lower_link_capacity_ && estimate_) { pacing_rate = std::max({min_total_allocated_bitrate_, estimate_->link_capacity_lower, last_loss_based_target_rate_}) * diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h index 4d32d09883..0dff2b13be 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -93,7 +93,6 @@ class GoogCcNetworkController : public NetworkControllerInterface { const RateControlSettings rate_control_settings_; const bool loss_based_stable_rate_; const bool pace_at_max_of_bwe_and_lower_link_capacity_; - const bool pace_at_loss_based_bwe_when_loss_; const std::unique_ptr probe_controller_; const std::unique_ptr @@ -136,7 +135,6 @@ class GoogCcNetworkController : public NetworkControllerInterface { double pacing_factor_; DataRate min_total_allocated_bitrate_; DataRate max_padding_rate_; - DataRate max_total_allocated_bitrate_; bool previously_in_alr_ = false; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index eed3d9343a..61a005453b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -83,13 +83,17 @@ ProbeControllerConfig::ProbeControllerConfig( alr_probe_scale("alr_scale", 2), network_state_estimate_probing_interval("network_state_interval", TimeDelta::PlusInfinity()), - network_state_estimate_fast_rampup_rate("network_state_fast_rampup_rate", - 0), - network_state_estimate_drop_down_rate("network_state_drop_down_rate", 0), + probe_if_estimate_lower_than_network_state_estimate_ratio( + "est_lower_than_network_ratio", + 0), + estimate_lower_than_network_state_estimate_probing_interval( + "est_lower_than_network_interval", + TimeDelta::seconds(3)), network_state_probe_scale("network_state_scale", 1.0), network_state_probe_duration("network_state_probe_duration", TimeDelta::Millis<15>()), + probe_on_max_allocated_bitrate_change("probe_max_allocation", true), first_allocation_probe_scale("alloc_p1", 1), second_allocation_probe_scale("alloc_p2", 2), allocation_allow_further_probing("alloc_probe_further", false), @@ -98,21 +102,31 @@ ProbeControllerConfig::ProbeControllerConfig( min_probe_duration("min_probe_duration", TimeDelta::Millis<15>()), limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe", false), + loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", 0.0) { - ParseFieldTrial( - {&first_exponential_probe_scale, &second_exponential_probe_scale, - &further_exponential_probe_scale, &further_probe_threshold, - &alr_probing_interval, &alr_probe_scale, &first_allocation_probe_scale, - &second_allocation_probe_scale, &allocation_allow_further_probing, - &min_probe_duration, &network_state_estimate_probing_interval, - &network_state_estimate_fast_rampup_rate, - &network_state_estimate_drop_down_rate, &network_state_probe_scale, - &network_state_probe_duration, &min_probe_packets_sent, - &limit_probe_target_rate_to_loss_bwe, - &skip_if_estimate_larger_than_fraction_of_max}, - key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); + ParseFieldTrial({&first_exponential_probe_scale, + &second_exponential_probe_scale, + &further_exponential_probe_scale, + &further_probe_threshold, + &alr_probing_interval, + &alr_probe_scale, + &probe_on_max_allocated_bitrate_change, + &first_allocation_probe_scale, + &second_allocation_probe_scale, + &allocation_allow_further_probing, + &min_probe_duration, + &network_state_estimate_probing_interval, + &probe_if_estimate_lower_than_network_state_estimate_ratio, + &estimate_lower_than_network_state_estimate_probing_interval, + &network_state_probe_scale, + &network_state_probe_duration, + &min_probe_packets_sent, + &limit_probe_target_rate_to_loss_bwe, + &loss_limited_probe_scale, + &skip_if_estimate_larger_than_fraction_of_max}, + key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration ParseFieldTrial( @@ -120,8 +134,9 @@ ProbeControllerConfig::ProbeControllerConfig( key_value_config->Lookup("WebRTC-Bwe-InitialProbing")); ParseFieldTrial({&further_exponential_probe_scale, &further_probe_threshold}, key_value_config->Lookup("WebRTC-Bwe-ExponentialProbing")); - ParseFieldTrial({&alr_probing_interval, &alr_probe_scale}, - key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); + ParseFieldTrial( + {&alr_probing_interval, &alr_probe_scale, &loss_limited_probe_scale}, + key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); ParseFieldTrial( {&first_allocation_probe_scale, &second_allocation_probe_scale, &allocation_allow_further_probing, &allocation_probe_max}, @@ -205,7 +220,8 @@ std::vector ProbeController::OnMaxTotalAllocatedBitrate( const bool in_alr = alr_start_time_.has_value(); const bool allow_allocation_probe = in_alr; - if (state_ == State::kProbingComplete && + if (config_.probe_on_max_allocated_bitrate_change && + state_ == State::kProbingComplete && max_total_allocated_bitrate != max_total_allocated_bitrate_ && estimated_bitrate_ < max_bitrate_ && estimated_bitrate_ < max_total_allocated_bitrate && @@ -272,13 +288,9 @@ std::vector ProbeController::InitiateExponentialProbing( std::vector ProbeController::SetEstimatedBitrate( DataRate bitrate, - bool bwe_limited_due_to_packet_loss, + BandwidthLimitedCause bandwidth_limited_cause, Timestamp at_time) { - if (bwe_limited_due_to_packet_loss != bwe_limited_due_to_packet_loss_ && - config_.limit_probe_target_rate_to_loss_bwe) { - state_ = State::kProbingComplete; - } - bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss; + bandwidth_limited_cause_ = bandwidth_limited_cause; if (bitrate < kBitrateDropThreshold * estimated_bitrate_) { time_of_last_large_drop_ = at_time; bitrate_before_last_large_drop_ = estimated_bitrate_; @@ -297,17 +309,28 @@ std::vector ProbeController::SetEstimatedBitrate( if (state_ == State::kWaitingForProbingResult) { // Continue probing if probing results indicate channel has greater // capacity. - // MS_DEBUG_DEV( - // "[measured bitrate:%" PRIi64 ", minimum to probe further:%" PRIi64 "]", - // bitrate_bps, min_bitrate_to_probe_further_bps_); - - if (bitrate > min_bitrate_to_probe_further_) { - pending_probes = InitiateProbing( + DataRate network_state_estimate_probe_further_limit = + config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ + ? network_estimate_->link_capacity_upper * + config_.further_probe_threshold + : DataRate::PlusInfinity(); + + // MS_DEBUG_DEV( + // "[measured bitrate:%" PRIi64 ", minimum to probe further:%" PRIi64 "]", + // bitrate_bps, min_bitrate_to_probe_further_bps_); +/* RTC_LOG(LS_INFO) << "Measured bitrate: " << bitrate + << " Minimum to probe further: " + << min_bitrate_to_probe_further_ << " upper limit: " + << network_state_estimate_probe_further_limit;*/ + + if (bitrate > min_bitrate_to_probe_further_ && + bitrate <= network_state_estimate_probe_further_limit) { + return InitiateProbing( at_time, {config_.further_exponential_probe_scale * bitrate}, true); } } - - return pending_probes; + return {}; } void ProbeController::EnablePeriodicAlrProbing(bool enable) { @@ -370,30 +393,12 @@ void ProbeController::SetMaxBitrate(DataRate max_bitrate) { void ProbeController::SetNetworkStateEstimate( webrtc::NetworkStateEstimate estimate) { - if (config_.network_state_estimate_fast_rampup_rate > 0 && - estimated_bitrate_ < estimate.link_capacity_upper && - (!network_estimate_ || - estimate.link_capacity_upper >= - config_.network_state_estimate_fast_rampup_rate * - network_estimate_->link_capacity_upper)) { - send_probe_on_next_process_interval_ = true; - } - if (config_.network_state_estimate_drop_down_rate > 0 && network_estimate_ && - !estimate.link_capacity_upper.IsZero() && - (estimated_bitrate_ > estimate.link_capacity_upper || - bwe_limited_due_to_packet_loss_) && - estimate.link_capacity_upper <= - config_.network_state_estimate_drop_down_rate * - network_estimate_->link_capacity_upper) { - send_probe_on_next_process_interval_ = true; - } - network_estimate_ = estimate; } void ProbeController::Reset(Timestamp at_time) { network_available_ = true; - bwe_limited_due_to_packet_loss_ = false; + bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited; state_ = State::kInit; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); time_last_probing_initiated_ = Timestamp::Zero(); @@ -408,7 +413,6 @@ void ProbeController::Reset(Timestamp at_time) { time_of_last_large_drop_ = now; bitrate_before_last_large_drop_ = DataRate::Zero(); max_total_allocated_bitrate_ = DataRate::Zero(); - send_probe_on_next_process_interval_ = false; } bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { @@ -422,13 +426,34 @@ bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { } bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const { - if (config_.network_state_estimate_probing_interval->IsFinite() && - network_estimate_ && network_estimate_->link_capacity_upper.IsFinite() && - estimated_bitrate_ < network_estimate_->link_capacity_upper) { + if (!network_estimate_ || + network_estimate_->link_capacity_upper.IsInfinite()) { + return false; + } + + bool probe_due_to_low_estimate = + bandwidth_limited_cause_ == BandwidthLimitedCause::kDelayBasedLimited && + estimated_bitrate_ < + config_.probe_if_estimate_lower_than_network_state_estimate_ratio * + network_estimate_->link_capacity_upper; + if (probe_due_to_low_estimate && + config_.estimate_lower_than_network_state_estimate_probing_interval + ->IsFinite()) { + Timestamp next_probe_time = + time_last_probing_initiated_ + + config_.estimate_lower_than_network_state_estimate_probing_interval; + return at_time >= next_probe_time; + } + + bool periodic_probe = + estimated_bitrate_ < network_estimate_->link_capacity_upper; + if (periodic_probe && + config_.network_state_estimate_probing_interval->IsFinite()) { Timestamp next_probe_time = time_last_probing_initiated_ + config_.network_state_estimate_probing_interval; return at_time >= next_probe_time; } + return false; } @@ -446,8 +471,7 @@ std::vector ProbeController::Process(Timestamp at_time) { if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) { return {}; } - if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) || - TimeForNetworkStateProbe(at_time)) { + if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) { return InitiateProbing( at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true); } @@ -462,32 +486,19 @@ std::vector ProbeController::InitiateProbing( DataRate network_estimate = network_estimate_ ? network_estimate_->link_capacity_upper : DataRate::PlusInfinity(); + DataRate max_probe_rate = + max_total_allocated_bitrate_.IsZero() + ? max_bitrate_ + : std::min(max_total_allocated_bitrate_, max_bitrate_); if (std::min(network_estimate, estimated_bitrate_) > - config_.skip_if_estimate_larger_than_fraction_of_max * max_bitrate_) { + config_.skip_if_estimate_larger_than_fraction_of_max * max_probe_rate) { + state_ = State::kProbingComplete; + min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); return {}; } } - MS_DEBUG_DEV( - "[max_bitrate_bps_:%lld, max_probe_bitrate_bps:%" PRIi64 "]", - max_bitrate_bps_, - max_probe_bitrate_bps); - DataRate max_probe_bitrate = max_bitrate_; - if (bwe_limited_due_to_packet_loss_ && - config_.limit_probe_target_rate_to_loss_bwe) { - max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_); - } - if (config_.network_state_estimate_probing_interval->IsFinite() && - network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { - if (network_estimate_->link_capacity_upper.IsZero()) { - MS_DEBUG_TAG(bwe, "Not sending probe, Network state estimate is zero"); - return {}; - } - max_probe_bitrate = - std::min(max_probe_bitrate, network_estimate_->link_capacity_upper * - config_.network_state_probe_scale); - } if (max_total_allocated_bitrate_ > DataRate::Zero()) { // If a max allocated bitrate has been configured, allow probing up to 2x // that rate. This allows some overhead to account for bursty streams, @@ -499,12 +510,39 @@ std::vector ProbeController::InitiateProbing( std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2); } - send_probe_on_next_process_interval_ = false; + DataRate estimate_capped_bitrate = DataRate::PlusInfinity(); + if (config_.limit_probe_target_rate_to_loss_bwe) { + switch (bandwidth_limited_cause_) { + case BandwidthLimitedCause::kLossLimitedBweDecreasing: + // If bandwidth estimate is decreasing because of packet loss, do not + // send probes. + return {}; + case BandwidthLimitedCause::kLossLimitedBweIncreasing: + estimate_capped_bitrate = + std::min(max_probe_bitrate, + estimated_bitrate_ * config_.loss_limited_probe_scale); + break; + case BandwidthLimitedCause::kDelayBasedLimited: + break; + } + } + if (config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { + if (network_estimate_->link_capacity_upper.IsZero()) { + // RTC_LOG(LS_INFO) << "Not sending probe, Network state estimate is zero"; + return {}; + } + estimate_capped_bitrate = + std::min({estimate_capped_bitrate, max_probe_bitrate, + network_estimate_->link_capacity_upper * + config_.network_state_probe_scale}); + } std::vector pending_probes; for (DataRate bitrate : bitrates_to_probe) { // RTC_DCHECK(!bitrate.IsZero()); + bitrate = std::min(bitrate, estimate_capped_bitrate); if (bitrate > max_probe_bitrate) { bitrate = max_probe_bitrate; probe_further = false; @@ -529,8 +567,11 @@ std::vector ProbeController::InitiateProbing( time_last_probing_initiated_ = now; if (probe_further) { state_ = State::kWaitingForProbingResult; + // Dont expect probe results to be larger than a fraction of the actual + // probe rate. min_bitrate_to_probe_further_ = - (*(bitrates_to_probe.end() - 1)) * config_.further_probe_threshold; + std::min(estimate_capped_bitrate, (*(bitrates_to_probe.end() - 1))) * + config_.further_probe_threshold; } else { state_ = State::kProbingComplete; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h index 1fda7813bf..2954395c5d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h @@ -46,18 +46,19 @@ struct ProbeControllerConfig { // Configures how often we send probes if NetworkStateEstimate is available. FieldTrialParameter network_state_estimate_probing_interval; - // If the network state estimate increase more than this rate, a probe is sent - // the next process interval. - FieldTrialParameter network_state_estimate_fast_rampup_rate; - // If the network state estimate decreases more than this rate, a probe is - // sent the next process interval. - FieldTrialParameter network_state_estimate_drop_down_rate; + // Periodically probe as long as the the ratio beteeen current estimate and + // NetworkStateEstimate is lower then this. + FieldTrialParameter + probe_if_estimate_lower_than_network_state_estimate_ratio; + FieldTrialParameter + estimate_lower_than_network_state_estimate_probing_interval; FieldTrialParameter network_state_probe_scale; // Overrides min_probe_duration if network_state_estimate_probing_interval // is set and a network state estimate is known. FieldTrialParameter network_state_probe_duration; // Configures the probes emitted by changed to the allocated bitrate. + FieldTrialParameter probe_on_max_allocated_bitrate_change; FieldTrialOptional first_allocation_probe_scale; FieldTrialOptional second_allocation_probe_scale; FieldTrialFlag allocation_allow_further_probing; @@ -67,14 +68,23 @@ struct ProbeControllerConfig { FieldTrialParameter min_probe_packets_sent; // The minimum probing duration. FieldTrialParameter min_probe_duration; - // Max limit the target rate of a probe to current estimate if BWE is loss - // limited. + // Periodically probe when bandwidth estimate is loss limited. FieldTrialParameter limit_probe_target_rate_to_loss_bwe; + FieldTrialParameter loss_limited_probe_scale; // Dont send a probe if min(estimate, network state estimate) is larger than // this fraction of the set max bitrate. FieldTrialParameter skip_if_estimate_larger_than_fraction_of_max; }; +// Reason that bandwidth estimate is limited. Bandwidth estimate can be limited +// by either delay based bwe, or loss based bwe when it increases/decreases the +// estimate. +enum class BandwidthLimitedCause { + kLossLimitedBweIncreasing = 0, + kLossLimitedBweDecreasing = 1, + kDelayBasedLimited = 2 +}; + // This class controls initiation of probing to estimate initial channel // capacity. There is also support for probing during a session when max // bitrate is adjusted by an application. @@ -103,7 +113,7 @@ class ProbeController { ABSL_MUST_USE_RESULT std::vector SetEstimatedBitrate( DataRate bitrate, - bool bwe_limited_due_to_packet_loss, + BandwidthLimitedCause bandwidth_limited_cause, Timestamp at_time); void EnablePeriodicAlrProbing(bool enable); @@ -145,12 +155,12 @@ class ProbeController { bool TimeForNetworkStateProbe(Timestamp at_time) const; bool network_available_; - bool bwe_limited_due_to_packet_loss_; + BandwidthLimitedCause bandwidth_limited_cause_ = + BandwidthLimitedCause::kDelayBasedLimited; State state_; DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity(); DataRate estimated_bitrate_ = DataRate::Zero(); - bool send_probe_on_next_process_interval_; absl::optional network_estimate_; DataRate start_bitrate_ = DataRate::Zero(); DataRate max_bitrate_ = DataRate::PlusInfinity(); diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 54970b0680..903750a21d 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -9,7 +9,8 @@ /* Static. */ static std::once_flag globalInitOnce; -static constexpr char FieldTrials[] = "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; +static constexpr char FieldTrials[] = + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; /* Static methods. */ From 676b92eb033b464cee0a4b59d3a1350094efb744 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 22 Nov 2022 15:07:53 +0200 Subject: [PATCH 07/70] Sync with latest Loss v2 changes. Fix Periodic ALR when we suddenly have no traffic due to low reported estimated bitrate. Change min bitrate constant. --- .../bitrate_controller/loss_based_bwe_v2.cc | 19 ++++----- .../send_side_bandwidth_estimation.cc | 4 ++ .../goog_cc/alr_detector.cc | 23 +++++++++-- .../goog_cc/alr_detector.h | 3 +- .../goog_cc/goog_cc_network_control.cc | 14 ++----- .../goog_cc/probe_bitrate_estimator.cc | 2 +- .../goog_cc/probe_controller.cc | 41 +++++++++++-------- .../include/bwe_defines.h | 4 +- 8 files changed, 64 insertions(+), 46 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index d99abe5fe7..7c1e2c6707 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -208,6 +208,7 @@ void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate, void LossBasedBweV2::SetProbeBitrate(absl::optional probe_bitrate) { if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) { if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) { + MS_DEBUG_DEV("Setting probe bitrate to %d", probe_bitrate.value().bps()); probe_bitrate_ = probe_bitrate.value(); } } @@ -222,14 +223,12 @@ void LossBasedBweV2::UpdateBandwidthEstimate( delay_based_estimate_ = delay_based_estimate; upper_link_capacity_ = upper_link_capacity; if (!IsEnabled()) { -/* RTC_LOG(LS_WARNING) - << "The estimator must be enabled before it can be used.";*/ + MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); return; } SetProbeBitrate(probe_bitrate); if (packet_results.empty()) { -/* RTC_LOG(LS_VERBOSE) - << "The estimate cannot be updated without any loss statistics.";*/ + MS_WARN_TAG(bwe, "The estimate cannot be updated without any loss statistics."); return; } @@ -238,8 +237,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate( } if (!IsValid(current_estimate_.loss_limited_bandwidth)) { -/* RTC_LOG(LS_VERBOSE) - << "The estimator must be initialized before it can be used.";*/ + MS_WARN_TAG(bwe, "The estimator must be initialized before it can be used."); return; } @@ -307,13 +305,12 @@ void LossBasedBweV2::UpdateBandwidthEstimate( } } - if (IsEstimateIncreasingWhenLossLimited(best_candidate)) { + if (IsEstimateIncreasingWhenLossLimited(best_candidate) && + best_candidate.loss_limited_bandwidth < delay_based_estimate) { current_state_ = LossBasedState::kIncreasing; - } else if (IsValid(delay_based_estimate_) && - best_candidate.loss_limited_bandwidth < delay_based_estimate_) { + } else if (best_candidate.loss_limited_bandwidth < delay_based_estimate_) { current_state_ = LossBasedState::kDecreasing; - } else if (IsValid(delay_based_estimate_) && - best_candidate.loss_limited_bandwidth == delay_based_estimate_) { + } else if (best_candidate.loss_limited_bandwidth >= delay_based_estimate_) { current_state_ = LossBasedState::kDelayBasedEstimate; } current_estimate_ = best_candidate; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 21cbcaa692..b342ca2318 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -371,6 +371,10 @@ void SendSideBandwidthEstimation::UpdateLossBasedEstimator( report.packet_feedbacks, report.feedback_time); } if (LossBasedBandwidthEstimatorV2Enabled()) { + MS_DEBUG_DEV("Updating loss_based_bandwidth_estimator_v2_. Delay limit %lld, Upper Link Capacity %lld", delay_based_limit_.kbps(), upper_link_capacity.kbps()); + if (probe_bitrate.has_value()) { + MS_DEBUG_DEV("Updating loss_based_bandwidth_estimator_v2_. Probe bitrate: %lld", probe_bitrate.value().kbps()); + } loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( report.packet_feedbacks, delay_based_limit_, delay_detector_state, probe_bitrate, upper_link_capacity); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 0bc5c2d67b..2f5e624378 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::AlrDetector" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/alr_detector.h" #include "rtc_base/numerics/safe_conversions.h" @@ -66,6 +66,16 @@ AlrDetector::AlrDetector(const WebRtcKeyValueConfig* key_value_config) AlrDetector::~AlrDetector() {} +// This is used to trigger ALR start state if we had sudden stop in traffic (all consumers paused due to low bw report). +void AlrDetector::Process() { + int64_t now = DepLibUV::GetTimeMsInt64(); + if (!alr_started_time_ms_.has_value() && last_send_time_ms_.has_value()) { + if ((now - last_send_time_ms_.value()) > 1000) { + OnBytesSent(0, now); + } + } +} + void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { if (!last_send_time_ms_.has_value()) { last_send_time_ms_ = send_time_ms; @@ -95,9 +105,14 @@ void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { void AlrDetector::SetEstimatedBitrate(int bitrate_bps) { //RTC_DCHECK(bitrate_bps); - int target_rate_kbps = - static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; - alr_budget_.set_target_rate_kbps(target_rate_kbps); + + if (last_estimated_bitrate_ != bitrate_bps) { + last_estimated_bitrate_ = bitrate_bps; + MS_DEBUG_TAG(bwe, "Setting ALR bitrate to %d", bitrate_bps); + int target_rate_kbps = + static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; + alr_budget_.set_target_rate_kbps(target_rate_kbps); + } } absl::optional AlrDetector::GetApplicationLimitedRegionStartTime() diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h index 42fc574150..2b3561a50a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h @@ -58,13 +58,14 @@ class AlrDetector { // Returns time in milliseconds when the current application-limited region // started or empty result if the sender is currently not application-limited. absl::optional GetApplicationLimitedRegionStartTime() const; + void Process(); private: friend class GoogCcStatePrinter; const AlrDetectorConfig conf_; absl::optional last_send_time_ms_; - + int last_estimated_bitrate_; IntervalBudget alr_budget_; absl::optional alr_started_time_ms_; }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 1848d1f28c..f0c0184840 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -49,14 +49,6 @@ constexpr float kDefaultPaceMultiplier = 2.5f; // below the current throughput estimate to drain the network queues. constexpr double kProbeDropThroughputFraction = 0.85; -int64_t GetBpsOrDefault(const absl::optional& rate, - int64_t fallback_bps) { - if (rate && rate->IsFinite()) { - return rate->bps(); - } else { - return fallback_bps; - } -} bool IsEnabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Enabled") == 0; } @@ -210,6 +202,7 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( msg.pacer_queue->bytes()); } bandwidth_estimation_->UpdateEstimate(msg.at_time); + alr_detector_->Process(); absl::optional start_time_ms = alr_detector_->GetApplicationLimitedRegionStartTime(); probe_controller_->SetAlrStartTimeMs(start_time_ms); @@ -529,6 +522,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( probe_controller_->SetNetworkStateEstimate(*estimate_); } } + absl::optional probe_bitrate = probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(); if (ignore_probes_lower_than_network_estimate_ && probe_bitrate && @@ -704,10 +698,10 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); - MS_DEBUG_DEV("bwe [at_time:%" PRIu64", pushback_target_bps:%lld, estimate_bps:%lld]", +/* MS_DEBUG_DEV("bwe [at_time:%" PRIu64", pushback_target_bps:%lld, estimate_bps:%lld]", at_time.ms(), last_pushback_target_rate_.bps(), - last_raw_target_rate_.bps()); + loss_based_target_rate.bps());*/ } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc index 6022dbdd99..0c656305c3 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeBitrateEstimator" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h" #include "rtc_base/numerics/safe_conversions.h" diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 61a005453b..d5254cd2ad 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeController" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "api/units/data_rate.h" @@ -17,6 +17,7 @@ #include "api/units/timestamp.h" #include "rtc_base/numerics/safe_conversions.h" +#include "DepLibUV.hpp" #include "Logger.hpp" #include @@ -172,10 +173,10 @@ std::vector ProbeController::SetBitrates( } else if (start_bitrate_.IsZero()) { start_bitrate_ = min_bitrate; } - MS_DEBUG_DEV( +/* MS_DEBUG_DEV( "[old_max_bitrate_bps:%lld, max_bitrate_bps:%lld]", - max_bitrate_bps_, - max_bitrate_bps); + max_bitrate_.bps(), + max_bitrate.bps());*/ // The reason we use the variable `old_max_bitrate_pbs` is because we // need to set `max_bitrate_` before we call InitiateProbing. DataRate old_max_bitrate = max_bitrate_; @@ -305,7 +306,6 @@ std::vector ProbeController::SetEstimatedBitrate( // bitrate_bps / 1000); mid_call_probing_waiting_for_result_ = false; } - std::vector pending_probes; if (state_ == State::kWaitingForProbingResult) { // Continue probing if probing results indicate channel has greater // capacity. @@ -339,13 +339,18 @@ void ProbeController::EnablePeriodicAlrProbing(bool enable) { void ProbeController::SetAlrStartTimeMs( absl::optional alr_start_time_ms) { - if (alr_start_time_ms) { - alr_start_time_ = Timestamp::ms(*alr_start_time_ms); - } else { + if ((alr_start_time_ms.has_value() && !alr_start_time_.has_value()) || + (alr_start_time_ms.has_value() && alr_start_time_.has_value() && (alr_start_time_.value().ms() != alr_start_time_ms.value()))) + { + MS_DEBUG_TAG(bwe, "ALR Start, start time %ld", alr_start_time_ms.value()); + alr_start_time_ = Timestamp::ms(alr_start_time_ms.value()); + } + /*} else { alr_start_time_ = absl::nullopt; - } + }*/ } void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) { + MS_DEBUG_TAG(bwe, "ALR End"); alr_end_time_.emplace(Timestamp::ms(alr_end_time_ms)); } @@ -385,12 +390,6 @@ std::vector ProbeController::RequestProbe( return std::vector(); } -void ProbeController::SetMaxBitrate(DataRate max_bitrate) { - MS_DEBUG_DEV("[max_bitrate_bps:%" PRIi64 "]", max_bitrate); - - max_bitrate_ = max_bitrate; -} - void ProbeController::SetNetworkStateEstimate( webrtc::NetworkStateEstimate estimate) { network_estimate_ = estimate; @@ -417,6 +416,7 @@ void ProbeController::Reset(Timestamp at_time) { bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { if (enable_periodic_alr_probing_ && alr_start_time_) { + //MS_DEBUG_TAG(bwe, "enable_periodic_alr_probing_: %d, alr_start_time_: %lld", enable_periodic_alr_probing_, alr_start_time_.value().ms()); Timestamp next_probe_time = std::max(*alr_start_time_, time_last_probing_initiated_) + config_.alr_probing_interval; @@ -515,14 +515,21 @@ std::vector ProbeController::InitiateProbing( switch (bandwidth_limited_cause_) { case BandwidthLimitedCause::kLossLimitedBweDecreasing: // If bandwidth estimate is decreasing because of packet loss, do not - // send probes. - return {}; + // send probes. Unless we are in ALR state, where we might not have traffic to estimate. + // This might be terribly wrong when we have a big gap between factual and probation bitrate. + if (!alr_start_time_) { + MS_DEBUG_TAG(bwe, "State is BandwidthLimitedCause::kLossLimitedBweDecreasing"); + return {}; + } + break; case BandwidthLimitedCause::kLossLimitedBweIncreasing: + MS_DEBUG_TAG(bwe, "State is BandwidthLimitedCause::kLossLimitedBweIncreasing"); estimate_capped_bitrate = std::min(max_probe_bitrate, estimated_bitrate_ * config_.loss_limited_probe_scale); break; case BandwidthLimitedCause::kDelayBasedLimited: + MS_DEBUG_TAG(bwe, "State is BandwidthLimitedCause::kDelayBasedLimited"); break; } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h index f3213e4904..aae14e1d59 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h @@ -28,8 +28,8 @@ DataRate GetMinBitrate(); } // namespace congestion_controller static const int64_t kBitrateWindowMs = 1000; - -constexpr DataRate kCongestionControllerMinBitrate = DataRate::BitsPerSec<5000>(); +// NOTE: the default value was 5000 kbps, which is just too small for SFU scenario. +constexpr DataRate kCongestionControllerMinBitrate = DataRate::BitsPerSec<150000>(); extern const char kBweTypeHistogram[]; From 011731baaaf95d573b0b7c0ce5d0803138e8c45c Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 24 Nov 2022 12:40:43 +0200 Subject: [PATCH 08/70] Revert "Sync with latest Loss v2 changes. Fix Periodic ALR when we suddenly have no traffic due to low reported estimated bitrate. Change min bitrate constant." This reverts commit 676b92eb033b464cee0a4b59d3a1350094efb744. --- .../bitrate_controller/loss_based_bwe_v2.cc | 19 +++++---- .../send_side_bandwidth_estimation.cc | 4 -- .../goog_cc/alr_detector.cc | 23 ++--------- .../goog_cc/alr_detector.h | 3 +- .../goog_cc/goog_cc_network_control.cc | 14 +++++-- .../goog_cc/probe_bitrate_estimator.cc | 2 +- .../goog_cc/probe_controller.cc | 41 ++++++++----------- .../include/bwe_defines.h | 4 +- 8 files changed, 46 insertions(+), 64 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 7c1e2c6707..d99abe5fe7 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -208,7 +208,6 @@ void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate, void LossBasedBweV2::SetProbeBitrate(absl::optional probe_bitrate) { if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) { if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) { - MS_DEBUG_DEV("Setting probe bitrate to %d", probe_bitrate.value().bps()); probe_bitrate_ = probe_bitrate.value(); } } @@ -223,12 +222,14 @@ void LossBasedBweV2::UpdateBandwidthEstimate( delay_based_estimate_ = delay_based_estimate; upper_link_capacity_ = upper_link_capacity; if (!IsEnabled()) { - MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); +/* RTC_LOG(LS_WARNING) + << "The estimator must be enabled before it can be used.";*/ return; } SetProbeBitrate(probe_bitrate); if (packet_results.empty()) { - MS_WARN_TAG(bwe, "The estimate cannot be updated without any loss statistics."); +/* RTC_LOG(LS_VERBOSE) + << "The estimate cannot be updated without any loss statistics.";*/ return; } @@ -237,7 +238,8 @@ void LossBasedBweV2::UpdateBandwidthEstimate( } if (!IsValid(current_estimate_.loss_limited_bandwidth)) { - MS_WARN_TAG(bwe, "The estimator must be initialized before it can be used."); +/* RTC_LOG(LS_VERBOSE) + << "The estimator must be initialized before it can be used.";*/ return; } @@ -305,12 +307,13 @@ void LossBasedBweV2::UpdateBandwidthEstimate( } } - if (IsEstimateIncreasingWhenLossLimited(best_candidate) && - best_candidate.loss_limited_bandwidth < delay_based_estimate) { + if (IsEstimateIncreasingWhenLossLimited(best_candidate)) { current_state_ = LossBasedState::kIncreasing; - } else if (best_candidate.loss_limited_bandwidth < delay_based_estimate_) { + } else if (IsValid(delay_based_estimate_) && + best_candidate.loss_limited_bandwidth < delay_based_estimate_) { current_state_ = LossBasedState::kDecreasing; - } else if (best_candidate.loss_limited_bandwidth >= delay_based_estimate_) { + } else if (IsValid(delay_based_estimate_) && + best_candidate.loss_limited_bandwidth == delay_based_estimate_) { current_state_ = LossBasedState::kDelayBasedEstimate; } current_estimate_ = best_candidate; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index b342ca2318..21cbcaa692 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -371,10 +371,6 @@ void SendSideBandwidthEstimation::UpdateLossBasedEstimator( report.packet_feedbacks, report.feedback_time); } if (LossBasedBandwidthEstimatorV2Enabled()) { - MS_DEBUG_DEV("Updating loss_based_bandwidth_estimator_v2_. Delay limit %lld, Upper Link Capacity %lld", delay_based_limit_.kbps(), upper_link_capacity.kbps()); - if (probe_bitrate.has_value()) { - MS_DEBUG_DEV("Updating loss_based_bandwidth_estimator_v2_. Probe bitrate: %lld", probe_bitrate.value().kbps()); - } loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( report.packet_feedbacks, delay_based_limit_, delay_detector_state, probe_bitrate, upper_link_capacity); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 2f5e624378..0bc5c2d67b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::AlrDetector" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/alr_detector.h" #include "rtc_base/numerics/safe_conversions.h" @@ -66,16 +66,6 @@ AlrDetector::AlrDetector(const WebRtcKeyValueConfig* key_value_config) AlrDetector::~AlrDetector() {} -// This is used to trigger ALR start state if we had sudden stop in traffic (all consumers paused due to low bw report). -void AlrDetector::Process() { - int64_t now = DepLibUV::GetTimeMsInt64(); - if (!alr_started_time_ms_.has_value() && last_send_time_ms_.has_value()) { - if ((now - last_send_time_ms_.value()) > 1000) { - OnBytesSent(0, now); - } - } -} - void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { if (!last_send_time_ms_.has_value()) { last_send_time_ms_ = send_time_ms; @@ -105,14 +95,9 @@ void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { void AlrDetector::SetEstimatedBitrate(int bitrate_bps) { //RTC_DCHECK(bitrate_bps); - - if (last_estimated_bitrate_ != bitrate_bps) { - last_estimated_bitrate_ = bitrate_bps; - MS_DEBUG_TAG(bwe, "Setting ALR bitrate to %d", bitrate_bps); - int target_rate_kbps = - static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; - alr_budget_.set_target_rate_kbps(target_rate_kbps); - } + int target_rate_kbps = + static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; + alr_budget_.set_target_rate_kbps(target_rate_kbps); } absl::optional AlrDetector::GetApplicationLimitedRegionStartTime() diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h index 2b3561a50a..42fc574150 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h @@ -58,14 +58,13 @@ class AlrDetector { // Returns time in milliseconds when the current application-limited region // started or empty result if the sender is currently not application-limited. absl::optional GetApplicationLimitedRegionStartTime() const; - void Process(); private: friend class GoogCcStatePrinter; const AlrDetectorConfig conf_; absl::optional last_send_time_ms_; - int last_estimated_bitrate_; + IntervalBudget alr_budget_; absl::optional alr_started_time_ms_; }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index f0c0184840..1848d1f28c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -49,6 +49,14 @@ constexpr float kDefaultPaceMultiplier = 2.5f; // below the current throughput estimate to drain the network queues. constexpr double kProbeDropThroughputFraction = 0.85; +int64_t GetBpsOrDefault(const absl::optional& rate, + int64_t fallback_bps) { + if (rate && rate->IsFinite()) { + return rate->bps(); + } else { + return fallback_bps; + } +} bool IsEnabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Enabled") == 0; } @@ -202,7 +210,6 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( msg.pacer_queue->bytes()); } bandwidth_estimation_->UpdateEstimate(msg.at_time); - alr_detector_->Process(); absl::optional start_time_ms = alr_detector_->GetApplicationLimitedRegionStartTime(); probe_controller_->SetAlrStartTimeMs(start_time_ms); @@ -522,7 +529,6 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( probe_controller_->SetNetworkStateEstimate(*estimate_); } } - absl::optional probe_bitrate = probe_bitrate_estimator_->FetchAndResetLastEstimatedBitrate(); if (ignore_probes_lower_than_network_estimate_ && probe_bitrate && @@ -698,10 +704,10 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); -/* MS_DEBUG_DEV("bwe [at_time:%" PRIu64", pushback_target_bps:%lld, estimate_bps:%lld]", + MS_DEBUG_DEV("bwe [at_time:%" PRIu64", pushback_target_bps:%lld, estimate_bps:%lld]", at_time.ms(), last_pushback_target_rate_.bps(), - loss_based_target_rate.bps());*/ + last_raw_target_rate_.bps()); } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc index 0c656305c3..6022dbdd99 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_bitrate_estimator.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeBitrateEstimator" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_bitrate_estimator.h" #include "rtc_base/numerics/safe_conversions.h" diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index d5254cd2ad..61a005453b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeController" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "api/units/data_rate.h" @@ -17,7 +17,6 @@ #include "api/units/timestamp.h" #include "rtc_base/numerics/safe_conversions.h" -#include "DepLibUV.hpp" #include "Logger.hpp" #include @@ -173,10 +172,10 @@ std::vector ProbeController::SetBitrates( } else if (start_bitrate_.IsZero()) { start_bitrate_ = min_bitrate; } -/* MS_DEBUG_DEV( + MS_DEBUG_DEV( "[old_max_bitrate_bps:%lld, max_bitrate_bps:%lld]", - max_bitrate_.bps(), - max_bitrate.bps());*/ + max_bitrate_bps_, + max_bitrate_bps); // The reason we use the variable `old_max_bitrate_pbs` is because we // need to set `max_bitrate_` before we call InitiateProbing. DataRate old_max_bitrate = max_bitrate_; @@ -306,6 +305,7 @@ std::vector ProbeController::SetEstimatedBitrate( // bitrate_bps / 1000); mid_call_probing_waiting_for_result_ = false; } + std::vector pending_probes; if (state_ == State::kWaitingForProbingResult) { // Continue probing if probing results indicate channel has greater // capacity. @@ -339,18 +339,13 @@ void ProbeController::EnablePeriodicAlrProbing(bool enable) { void ProbeController::SetAlrStartTimeMs( absl::optional alr_start_time_ms) { - if ((alr_start_time_ms.has_value() && !alr_start_time_.has_value()) || - (alr_start_time_ms.has_value() && alr_start_time_.has_value() && (alr_start_time_.value().ms() != alr_start_time_ms.value()))) - { - MS_DEBUG_TAG(bwe, "ALR Start, start time %ld", alr_start_time_ms.value()); - alr_start_time_ = Timestamp::ms(alr_start_time_ms.value()); - } - /*} else { + if (alr_start_time_ms) { + alr_start_time_ = Timestamp::ms(*alr_start_time_ms); + } else { alr_start_time_ = absl::nullopt; - }*/ + } } void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) { - MS_DEBUG_TAG(bwe, "ALR End"); alr_end_time_.emplace(Timestamp::ms(alr_end_time_ms)); } @@ -390,6 +385,12 @@ std::vector ProbeController::RequestProbe( return std::vector(); } +void ProbeController::SetMaxBitrate(DataRate max_bitrate) { + MS_DEBUG_DEV("[max_bitrate_bps:%" PRIi64 "]", max_bitrate); + + max_bitrate_ = max_bitrate; +} + void ProbeController::SetNetworkStateEstimate( webrtc::NetworkStateEstimate estimate) { network_estimate_ = estimate; @@ -416,7 +417,6 @@ void ProbeController::Reset(Timestamp at_time) { bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { if (enable_periodic_alr_probing_ && alr_start_time_) { - //MS_DEBUG_TAG(bwe, "enable_periodic_alr_probing_: %d, alr_start_time_: %lld", enable_periodic_alr_probing_, alr_start_time_.value().ms()); Timestamp next_probe_time = std::max(*alr_start_time_, time_last_probing_initiated_) + config_.alr_probing_interval; @@ -515,21 +515,14 @@ std::vector ProbeController::InitiateProbing( switch (bandwidth_limited_cause_) { case BandwidthLimitedCause::kLossLimitedBweDecreasing: // If bandwidth estimate is decreasing because of packet loss, do not - // send probes. Unless we are in ALR state, where we might not have traffic to estimate. - // This might be terribly wrong when we have a big gap between factual and probation bitrate. - if (!alr_start_time_) { - MS_DEBUG_TAG(bwe, "State is BandwidthLimitedCause::kLossLimitedBweDecreasing"); - return {}; - } - break; + // send probes. + return {}; case BandwidthLimitedCause::kLossLimitedBweIncreasing: - MS_DEBUG_TAG(bwe, "State is BandwidthLimitedCause::kLossLimitedBweIncreasing"); estimate_capped_bitrate = std::min(max_probe_bitrate, estimated_bitrate_ * config_.loss_limited_probe_scale); break; case BandwidthLimitedCause::kDelayBasedLimited: - MS_DEBUG_TAG(bwe, "State is BandwidthLimitedCause::kDelayBasedLimited"); break; } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h index aae14e1d59..f3213e4904 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h @@ -28,8 +28,8 @@ DataRate GetMinBitrate(); } // namespace congestion_controller static const int64_t kBitrateWindowMs = 1000; -// NOTE: the default value was 5000 kbps, which is just too small for SFU scenario. -constexpr DataRate kCongestionControllerMinBitrate = DataRate::BitsPerSec<150000>(); + +constexpr DataRate kCongestionControllerMinBitrate = DataRate::BitsPerSec<5000>(); extern const char kBweTypeHistogram[]; From c8c69442772d969db5060c6485714d6015f1e3ae Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 24 Nov 2022 12:40:55 +0200 Subject: [PATCH 09/70] Revert "Sync with latest Loss v2 changes." This reverts commit f498894b5727fb04a7245c937ed8a47c6675c6ca. --- worker/deps/libwebrtc/README.md | 5 - .../bitrate_controller/loss_based_bwe_v2.cc | 200 ++++++------------ .../bitrate_controller/loss_based_bwe_v2.h | 39 +--- .../send_side_bandwidth_estimation.cc | 25 +-- .../send_side_bandwidth_estimation.h | 7 +- .../goog_cc/goog_cc_network_control.cc | 53 ++--- .../goog_cc/goog_cc_network_control.h | 2 + .../goog_cc/probe_controller.cc | 199 +++++++---------- .../goog_cc/probe_controller.h | 32 +-- worker/src/DepLibWebRTC.cpp | 3 +- 10 files changed, 197 insertions(+), 368 deletions(-) diff --git a/worker/deps/libwebrtc/README.md b/worker/deps/libwebrtc/README.md index 48814038e8..2d5ae8cf13 100644 --- a/worker/deps/libwebrtc/README.md +++ b/worker/deps/libwebrtc/README.md @@ -10,8 +10,3 @@ The file `libwebrtc/mediasoup_helpers.h` includes some utilities to plug mediaso The file `worker/deps/libwebrtc/deps/abseil-cpp/abseil-cpp/absl/synchronization/internal/graphcycles.cc` has `#include ` added to it to fix CI builds with Clang. The file `meson.build` is written for using with Meson build system. - -Updated and synced with: - -* libwebrtc branch: main -* libwebrtc commit: 17887eb04a84e426b604d4c084898c3147c7d810 \ No newline at end of file diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index d99abe5fe7..2ad27dcf38 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -44,10 +44,6 @@ bool IsValid(DataRate datarate) { return datarate.IsFinite(); } -bool IsValid(absl::optional datarate) { - return datarate.has_value() && IsValid(datarate.value()); -} - bool IsValid(Timestamp timestamp) { return timestamp.IsFinite(); } @@ -136,9 +132,8 @@ bool LossBasedBweV2::IsReady() const { num_observations_ > 0; } -LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { - Result result; - result.state = current_state_; +DataRate LossBasedBweV2::GetBandwidthEstimate( + DataRate delay_based_limit) const { if (!IsReady()) { /* if (!IsEnabled()) { RTC_LOG(LS_WARNING) @@ -152,22 +147,18 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { RTC_LOG(LS_WARNING) << "The estimator must receive enough loss " "statistics before it can be used."; } - } */ - result.bandwidth_estimate = IsValid(delay_based_estimate_) - ? delay_based_estimate_ - : DataRate::PlusInfinity(); - return result; + }*/ + return IsValid(delay_based_limit) ? delay_based_limit + : DataRate::PlusInfinity(); } - if (IsValid(delay_based_estimate_)) { - result.bandwidth_estimate = - std::min({current_estimate_.loss_limited_bandwidth, - GetInstantUpperBound(), delay_based_estimate_}); + if (delay_based_limit.IsFinite()) { + return std::min({current_estimate_.loss_limited_bandwidth, + GetInstantUpperBound(), delay_based_limit}); } else { - result.bandwidth_estimate = std::min( - current_estimate_.loss_limited_bandwidth, GetInstantUpperBound()); + return std::min(current_estimate_.loss_limited_bandwidth, + GetInstantUpperBound()); } - return result; } void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) { @@ -188,45 +179,24 @@ void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) { } } -void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate, - DataRate max_bitrate) { +void LossBasedBweV2::SetMinBitrate(DataRate min_bitrate) { if (IsValid(min_bitrate)) { min_bitrate_ = min_bitrate; } else { - /*RTC_LOG(LS_WARNING) << "The min bitrate must be finite: " +/* RTC_LOG(LS_WARNING) << "The min bitrate must be finite: " << ToString(min_bitrate);*/ } - - if (IsValid(max_bitrate)) { - max_bitrate_ = max_bitrate; - } else { -/* RTC_LOG(LS_WARNING) << "The max bitrate must be finite: " - << ToString(max_bitrate);*/ - } -} - -void LossBasedBweV2::SetProbeBitrate(absl::optional probe_bitrate) { - if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) { - if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) { - probe_bitrate_ = probe_bitrate.value(); - } - } } void LossBasedBweV2::UpdateBandwidthEstimate( std::vector packet_results, DataRate delay_based_estimate, - BandwidthUsage delay_detector_state, - absl::optional probe_bitrate, - DataRate upper_link_capacity) { - delay_based_estimate_ = delay_based_estimate; - upper_link_capacity_ = upper_link_capacity; + BandwidthUsage delay_detector_state) { if (!IsEnabled()) { /* RTC_LOG(LS_WARNING) << "The estimator must be enabled before it can be used.";*/ return; } - SetProbeBitrate(probe_bitrate); if (packet_results.empty()) { /* RTC_LOG(LS_VERBOSE) << "The estimate cannot be updated without any loss statistics.";*/ @@ -245,7 +215,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate( ChannelParameters best_candidate = current_estimate_; double objective_max = std::numeric_limits::lowest(); - for (ChannelParameters candidate : GetCandidates()) { + for (ChannelParameters candidate : GetCandidates(delay_based_estimate)) { NewtonsMethodUpdate(candidate); const double candidate_objective = GetObjective(candidate); @@ -269,75 +239,34 @@ void LossBasedBweV2::UpdateBandwidthEstimate( current_estimate_.loss_limited_bandwidth; } - if (IsBandwidthLimitedDueToLoss()) { - // Bound the estimate increase if: - // 1. The estimate has been increased for less than - // `delayed_increase_window` ago, and - // 2. The best candidate is greater than bandwidth_limit_in_current_window. - if (recovering_after_loss_timestamp_.IsFinite() && - recovering_after_loss_timestamp_ + config_->delayed_increase_window > - last_send_time_most_recent_observation_ && - best_candidate.loss_limited_bandwidth > - bandwidth_limit_in_current_window_) { - best_candidate.loss_limited_bandwidth = - bandwidth_limit_in_current_window_; - } - - bool increasing_when_loss_limited = - IsEstimateIncreasingWhenLossLimited(best_candidate); - // Bound the best candidate by the acked bitrate unless there is a recent - // probe result. - if (increasing_when_loss_limited && !IsValid(probe_bitrate_) && - IsValid(acknowledged_bitrate_)) { - best_candidate.loss_limited_bandwidth = - IsValid(best_candidate.loss_limited_bandwidth) - ? std::min(best_candidate.loss_limited_bandwidth, - config_->bandwidth_rampup_upper_bound_factor * - (*acknowledged_bitrate_)) - : config_->bandwidth_rampup_upper_bound_factor * - (*acknowledged_bitrate_); - } - - // Use probe bitrate as the estimate as probe bitrate is trusted to be - // correct. After being used, the probe bitrate is reset. - if (config_->probe_integration_enabled && IsValid(probe_bitrate_)) { - best_candidate.loss_limited_bandwidth = - std::min(probe_bitrate_, best_candidate.loss_limited_bandwidth); - probe_bitrate_ = DataRate::MinusInfinity(); - } - } - - if (IsEstimateIncreasingWhenLossLimited(best_candidate)) { - current_state_ = LossBasedState::kIncreasing; - } else if (IsValid(delay_based_estimate_) && - best_candidate.loss_limited_bandwidth < delay_based_estimate_) { - current_state_ = LossBasedState::kDecreasing; - } else if (IsValid(delay_based_estimate_) && - best_candidate.loss_limited_bandwidth == delay_based_estimate_) { - current_state_ = LossBasedState::kDelayBasedEstimate; - } - current_estimate_ = best_candidate; - - if (IsBandwidthLimitedDueToLoss() && + // Bound the estimate increase if: + // 1. The estimate is limited due to loss, and + // 2. The estimate has been increased for less than `delayed_increase_window` + // ago, and + // 3. The best candidate is greater than bandwidth_limit_in_current_window. + if (limited_due_to_loss_candidate_ && + recovering_after_loss_timestamp_.IsFinite() && + recovering_after_loss_timestamp_ + config_->delayed_increase_window > + last_send_time_most_recent_observation_ && + best_candidate.loss_limited_bandwidth > + bandwidth_limit_in_current_window_) { + best_candidate.loss_limited_bandwidth = bandwidth_limit_in_current_window_; + } + limited_due_to_loss_candidate_ = + delay_based_estimate.IsFinite() && + best_candidate.loss_limited_bandwidth < delay_based_estimate; + + if (limited_due_to_loss_candidate_ && (recovering_after_loss_timestamp_.IsInfinite() || recovering_after_loss_timestamp_ + config_->delayed_increase_window < last_send_time_most_recent_observation_)) { - bandwidth_limit_in_current_window_ = - std::max(kCongestionControllerMinBitrate, - current_estimate_.loss_limited_bandwidth * - config_->max_increase_factor); + bandwidth_limit_in_current_window_ = std::max( + kCongestionControllerMinBitrate, + best_candidate.loss_limited_bandwidth * config_->max_increase_factor); recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_; } -} -bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited( - const ChannelParameters& best_candidate) { - return (current_estimate_.loss_limited_bandwidth < - best_candidate.loss_limited_bandwidth || - (current_estimate_.loss_limited_bandwidth == - best_candidate.loss_limited_bandwidth && - current_state_ == LossBasedState::kIncreasing)) && - IsBandwidthLimitedDueToLoss(); + current_estimate_ = best_candidate; } // Returns a `LossBasedBweV2::Config` iff the `key_value_config` specifies a @@ -408,10 +337,6 @@ absl::optional LossBasedBweV2::CreateConfig( "BandwidthCapAtHighLossRate", DataRate::kbps(500.0)); FieldTrialParameter slope_of_bwe_high_loss_func( "SlopeOfBweHighLossFunc", 1000); - FieldTrialParameter probe_integration_enabled("ProbeIntegrationEnabled", - false); - FieldTrialParameter bound_by_upper_link_capacity_when_loss_limited( - "BoundByUpperLinkCapacityWhenLossLimited", true); if (key_value_config) { ParseFieldTrial({&enabled, &bandwidth_rampup_upper_bound_factor, @@ -444,11 +369,9 @@ absl::optional LossBasedBweV2::CreateConfig( &delayed_increase_window, &use_acked_bitrate_only_when_overusing, ¬_increase_if_inherent_loss_less_than_average_loss, - &probe_integration_enabled, &high_loss_rate_threshold, &bandwidth_cap_at_high_loss_rate, - &slope_of_bwe_high_loss_func, - &bound_by_upper_link_capacity_when_loss_limited}, + &slope_of_bwe_high_loss_func}, key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2")); } @@ -508,9 +431,6 @@ absl::optional LossBasedBweV2::CreateConfig( config->bandwidth_cap_at_high_loss_rate = bandwidth_cap_at_high_loss_rate.Get(); config->slope_of_bwe_high_loss_func = slope_of_bwe_high_loss_func.Get(); - config->probe_integration_enabled = probe_integration_enabled.Get(); - config->bound_by_upper_link_capacity_when_loss_limited = - bound_by_upper_link_capacity_when_loss_limited.Get(); std::string candidate_factors_str; @@ -742,25 +662,33 @@ double LossBasedBweV2::GetAverageReportedLossRatio() const { return num_lost_packets / num_packets; } -DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound() const { - DataRate candidate_bandwidth_upper_bound = max_bitrate_; - if (IsBandwidthLimitedDueToLoss() && - IsValid(bandwidth_limit_in_current_window_)) { +DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound( + DataRate delay_based_estimate) const { + DataRate candidate_bandwidth_upper_bound = DataRate::PlusInfinity(); + if (limited_due_to_loss_candidate_) { candidate_bandwidth_upper_bound = bandwidth_limit_in_current_window_; } if (config_->trendline_integration_enabled) { candidate_bandwidth_upper_bound = std::min(GetInstantUpperBound(), candidate_bandwidth_upper_bound); - if (IsValid(delay_based_estimate_)) { + if (IsValid(delay_based_estimate)) { candidate_bandwidth_upper_bound = - std::min(delay_based_estimate_, candidate_bandwidth_upper_bound); + std::min(delay_based_estimate, candidate_bandwidth_upper_bound); } } if (!acknowledged_bitrate_.has_value()) return candidate_bandwidth_upper_bound; + candidate_bandwidth_upper_bound = + IsValid(candidate_bandwidth_upper_bound) + ? std::min(candidate_bandwidth_upper_bound, + config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_)) + : config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_); + if (config_->rampup_acceleration_max_factor > 0.0) { const TimeDelta time_since_bandwidth_reduced = std::min( config_->rampup_acceleration_maxout_time, @@ -776,8 +704,8 @@ DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound() const { return candidate_bandwidth_upper_bound; } -std::vector LossBasedBweV2::GetCandidates() - const { +std::vector LossBasedBweV2::GetCandidates( + DataRate delay_based_estimate) const { std::vector bandwidths; bool can_increase_bitrate = TrendlineEsimateAllowBitrateIncrease(); for (double candidate_factor : config_->candidate_factors) { @@ -795,16 +723,16 @@ std::vector LossBasedBweV2::GetCandidates() config_->bandwidth_backoff_lower_bound_factor); } - if (IsValid(delay_based_estimate_) && + if (IsValid(delay_based_estimate) && config_->append_delay_based_estimate_candidate) { if (can_increase_bitrate && - delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) { - bandwidths.push_back(delay_based_estimate_); + delay_based_estimate > current_estimate_.loss_limited_bandwidth) { + bandwidths.push_back(delay_based_estimate); } } const DataRate candidate_bandwidth_upper_bound = - GetCandidateBandwidthUpperBound(); + GetCandidateBandwidthUpperBound(delay_based_estimate); std::vector candidates; candidates.resize(bandwidths.size()); @@ -952,11 +880,11 @@ DataRate LossBasedBweV2::GetSendingRate( } DataRate LossBasedBweV2::GetInstantUpperBound() const { - return cached_instant_upper_bound_.value_or(max_bitrate_); + return cached_instant_upper_bound_.value_or(DataRate::PlusInfinity()); } void LossBasedBweV2::CalculateInstantUpperBound() { - DataRate instant_limit = max_bitrate_; + DataRate instant_limit = DataRate::PlusInfinity(); const double average_reported_loss_ratio = GetAverageReportedLossRatio(); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { instant_limit = config_->instant_upper_bound_bandwidth_balance / @@ -972,12 +900,6 @@ void LossBasedBweV2::CalculateInstantUpperBound() { } } - if (IsBandwidthLimitedDueToLoss()) { - if (IsValid(upper_link_capacity_) && - config_->bound_by_upper_link_capacity_when_loss_limited) { - instant_limit = std::min(instant_limit, upper_link_capacity_); - } - } cached_instant_upper_bound_ = instant_limit; } @@ -1093,8 +1015,4 @@ bool LossBasedBweV2::PushBackObservation( return true; } -bool LossBasedBweV2::IsBandwidthLimitedDueToLoss() const { - return current_state_ != LossBasedState::kDelayBasedEstimate; -} - } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 80284f83ec..9dc2215395 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -26,21 +26,8 @@ namespace webrtc { -// State of the loss based estimate, which can be either increasing/decreasing -// when network is loss limited, or equal to the delay based estimate. -enum class LossBasedState { - kIncreasing = 0, - kDecreasing = 1, - kDelayBasedEstimate = 2 -}; - class LossBasedBweV2 { public: - struct Result { - ~Result() = default; - DataRate bandwidth_estimate = DataRate::Zero(); - LossBasedState state = LossBasedState::kDelayBasedEstimate; - }; // Creates a disabled `LossBasedBweV2` if the // `key_value_config` is not valid. explicit LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config); @@ -56,17 +43,15 @@ class LossBasedBweV2 { bool IsReady() const; // Returns `DataRate::PlusInfinity` if no BWE can be calculated. - Result GetLossBasedResult() const; + DataRate GetBandwidthEstimate(DataRate delay_based_limit) const; void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); void SetBandwidthEstimate(DataRate bandwidth_estimate); - void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); + void SetMinBitrate(DataRate min_bitrate); void UpdateBandwidthEstimate( std::vector packet_results, DataRate delay_based_estimate, - BandwidthUsage delay_detector_state, - absl::optional probe_bitrate, - DataRate upper_link_capacity); + BandwidthUsage delay_detector_state); private: struct ChannelParameters { @@ -109,8 +94,6 @@ class LossBasedBweV2 { double high_loss_rate_threshold = 1.0; DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity(); double slope_of_bwe_high_loss_func = 1000.0; - bool probe_integration_enabled = false; - bool bound_by_upper_link_capacity_when_loss_limited = false; }; struct Derivatives { @@ -140,8 +123,9 @@ class LossBasedBweV2 { // Returns `0.0` if not enough loss statistics have been received. double GetAverageReportedLossRatio() const; - std::vector GetCandidates() const; - DataRate GetCandidateBandwidthUpperBound() const; + std::vector GetCandidates( + DataRate delay_based_estimate) const; + DataRate GetCandidateBandwidthUpperBound(DataRate delay_based_estimate) const; Derivatives GetDerivatives(const ChannelParameters& channel_parameters) const; double GetFeasibleInherentLoss( const ChannelParameters& channel_parameters) const; @@ -167,13 +151,9 @@ class LossBasedBweV2 { bool PushBackObservation(std::vector packet_results, BandwidthUsage delay_detector_state); void UpdateTrendlineEstimator( - const std::vector& packet_feedbacks, + const std::vector packet_feedbacks, Timestamp at_time); void UpdateDelayDetector(BandwidthUsage delay_detector_state); - bool IsEstimateIncreasingWhenLossLimited( - const ChannelParameters& best_candidate); - bool IsBandwidthLimitedDueToLoss() const; - void SetProbeBitrate(absl::optional probe_bitrate); absl::optional acknowledged_bitrate_; absl::optional config_; @@ -191,11 +171,6 @@ class LossBasedBweV2 { DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); bool limited_due_to_loss_candidate_ = false; DataRate min_bitrate_ = DataRate::kbps(1); - DataRate max_bitrate_ = DataRate::PlusInfinity(); - LossBasedState current_state_ = LossBasedState::kDelayBasedEstimate; - DataRate probe_bitrate_ = DataRate::PlusInfinity(); - DataRate delay_based_estimate_ = DataRate::PlusInfinity(); - DataRate upper_link_capacity_ = DataRate::PlusInfinity(); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 21cbcaa692..fb7992b35c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -222,7 +222,6 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation( bitrate_threshold_(kDefaultBitrateThreshold), loss_based_bandwidth_estimator_v1_(key_value_config), loss_based_bandwidth_estimator_v2_(key_value_config), - loss_based_state_(LossBasedState::kDelayBasedEstimate), disable_receiver_limit_caps_only_("Disabled") { if (BweLossExperimentIsEnabled()) { @@ -239,8 +238,7 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation( ParseFieldTrial({&disable_receiver_limit_caps_only_}, key_value_config->Lookup("WebRTC-Bwe-ReceiverLimitCapsOnly")); if (LossBasedBandwidthEstimatorV2Enabled()) { - loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate( - min_bitrate_configured_, max_bitrate_configured_); + loss_based_bandwidth_estimator_v2_.SetMinBitrate(min_bitrate_configured_); } } @@ -304,8 +302,6 @@ void SendSideBandwidthEstimation::SetMinMaxBitrate(DataRate min_bitrate, } else { max_bitrate_configured_ = kDefaultMaxBitrate; } - loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate(min_bitrate_configured_, - max_bitrate_configured_); } int SendSideBandwidthEstimation::GetMinBitrate() const { @@ -319,8 +315,8 @@ DataRate SendSideBandwidthEstimation::target_rate() const { return std::max(min_bitrate_configured_, target); } -LossBasedState SendSideBandwidthEstimation::loss_based_state() const { - return loss_based_state_; +DataRate SendSideBandwidthEstimation::delay_based_limit() const { + return delay_based_limit_; } DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const { @@ -363,17 +359,14 @@ void SendSideBandwidthEstimation::SetAcknowledgedRate( void SendSideBandwidthEstimation::UpdateLossBasedEstimator( const TransportPacketsFeedback& report, - BandwidthUsage delay_detector_state, - absl::optional probe_bitrate, - DataRate upper_link_capacity) { + BandwidthUsage delay_detector_state) { if (LossBasedBandwidthEstimatorV1Enabled()) { loss_based_bandwidth_estimator_v1_.UpdateLossStatistics( report.packet_feedbacks, report.feedback_time); } if (LossBasedBandwidthEstimatorV2Enabled()) { loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( - report.packet_feedbacks, delay_based_limit_, delay_detector_state, - probe_bitrate, upper_link_capacity); + report.packet_feedbacks, delay_based_limit_, delay_detector_state); UpdateEstimate(report.feedback_time); } } @@ -519,10 +512,10 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) { } if (LossBasedBandwidthEstimatorV2ReadyForUse()) { - LossBasedBweV2::Result result = - loss_based_bandwidth_estimator_v2_.GetLossBasedResult(); - loss_based_state_ = result.state; - UpdateTargetBitrate(result.bandwidth_estimate, at_time); + DataRate new_bitrate = + loss_based_bandwidth_estimator_v2_.GetBandwidthEstimate( + delay_based_limit_); + UpdateTargetBitrate(new_bitrate, at_time); return; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 90faa460ea..00cfd71724 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -79,7 +79,7 @@ class SendSideBandwidthEstimation { void OnRouteChange(); DataRate target_rate() const; - LossBasedState loss_based_state() const; + DataRate delay_based_limit() const; uint8_t fraction_loss() const { return last_fraction_loss_; } TimeDelta round_trip_time() const { return last_round_trip_time_; } @@ -113,9 +113,7 @@ class SendSideBandwidthEstimation { void SetAcknowledgedRate(absl::optional acknowledged_rate, Timestamp at_time); void UpdateLossBasedEstimator(const TransportPacketsFeedback& report, - BandwidthUsage delay_detector_state, - absl::optional probe_bitrate, - DataRate upper_link_capacity); + BandwidthUsage delay_detector_state); private: friend class GoogCcStatePrinter; @@ -196,7 +194,6 @@ class SendSideBandwidthEstimation { DataRate bitrate_threshold_; LossBasedBandwidthEstimation loss_based_bandwidth_estimator_v1_; LossBasedBweV2 loss_based_bandwidth_estimator_v2_; - LossBasedState loss_based_state_; FieldTrialFlag disable_receiver_limit_caps_only_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 1848d1f28c..5436c81c3f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -63,19 +63,6 @@ bool IsEnabled(const WebRtcKeyValueConfig* config, absl::string_view key) { bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Disabled") != 0; } - -BandwidthLimitedCause GetBandwidthLimitedCause( - LossBasedState loss_based_state) { - switch (loss_based_state) { - case LossBasedState::kDecreasing: - return BandwidthLimitedCause::kLossLimitedBweDecreasing; - case LossBasedState::kIncreasing: - return BandwidthLimitedCause::kLossLimitedBweIncreasing; - default: - return BandwidthLimitedCause::kDelayBasedLimited; - } -} - } // namespace GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, @@ -100,6 +87,8 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, pace_at_max_of_bwe_and_lower_link_capacity_( IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtMaxOfBweAndLowerLinkCapacity")), + pace_at_loss_based_bwe_when_loss_( + IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtLossBaseBweWhenLoss")), probe_controller_( new ProbeController(key_value_config_)), congestion_window_pushback_controller_( @@ -129,7 +118,8 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, config.stream_based_config.min_total_allocated_bitrate.value_or( DataRate::Zero())), max_padding_rate_(config.stream_based_config.max_padding_rate.value_or( - DataRate::Zero())) { + DataRate::Zero())), + max_total_allocated_bitrate_(DataRate::Zero()) { //RTC_DCHECK(config.constraints.at_time.IsFinite()); ParseFieldTrial( {&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_}, @@ -202,6 +192,8 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( *total_bitrate, msg.at_time); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); + + max_total_allocated_bitrate_ = *total_bitrate; } initial_config_.reset(); } @@ -295,12 +287,17 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig( if (msg.requests_alr_probing) { probe_controller_->EnablePeriodicAlrProbing(*msg.requests_alr_probing); } - if (msg.max_total_allocated_bitrate) { - update.probe_cluster_configs = - probe_controller_->OnMaxTotalAllocatedBitrate( - *msg.max_total_allocated_bitrate, msg.at_time); + if (msg.max_total_allocated_bitrate && + *msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) { + if (rate_control_settings_.TriggerProbeOnMaxAllocatedBitrateChange()) { + update.probe_cluster_configs = + probe_controller_->OnMaxTotalAllocatedBitrate( + *msg.max_total_allocated_bitrate, msg.at_time); + } else { + probe_controller_->SetMaxBitrate(*msg.max_total_allocated_bitrate); + } + max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate; } - bool pacing_changed = false; if (msg.pacing_factor && *msg.pacing_factor != pacing_factor_) { pacing_factor_ = *msg.pacing_factor; @@ -569,9 +566,8 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time, result.target_bitrate); } - bandwidth_estimation_->UpdateLossBasedEstimator( - report, result.delay_detector_state, probe_bitrate, - estimate_ ? estimate_->link_capacity_upper : DataRate::PlusInfinity()); + bandwidth_estimation_->UpdateLossBasedEstimator(report, + result.delay_detector_state); if (result.updated) { // Update the estimate in the ProbeController, in case we want to probe. MaybeTriggerOnNetworkChanged(&update, report.feedback_time); @@ -635,6 +631,10 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( uint8_t fraction_loss = bandwidth_estimation_->fraction_loss(); TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time(); DataRate loss_based_target_rate = bandwidth_estimation_->target_rate(); + bool bwe_limited_due_to_packet_loss = + loss_based_target_rate.IsFinite() && + bandwidth_estimation_->delay_based_limit().IsFinite() && + loss_based_target_rate < bandwidth_estimation_->delay_based_limit(); DataRate pushback_target_rate = loss_based_target_rate; // BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(), @@ -697,9 +697,7 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( update->target_rate = target_rate_msg; auto probes = probe_controller_->SetEstimatedBitrate( - loss_based_target_rate, - GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state()), - at_time); + loss_based_target_rate, bwe_limited_due_to_packet_loss, at_time); update->probe_cluster_configs.insert(update->probe_cluster_configs.end(), probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); @@ -715,7 +713,10 @@ PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const { // Pacing rate is based on target rate before congestion window pushback, // because we don't want to build queues in the pacer when pushback occurs. DataRate pacing_rate = DataRate::Zero(); - if (pace_at_max_of_bwe_and_lower_link_capacity_ && estimate_) { + if ((pace_at_max_of_bwe_and_lower_link_capacity_ || + (pace_at_loss_based_bwe_when_loss_ && + last_loss_based_target_rate_ >= delay_based_bwe_->last_estimate())) && + estimate_) { pacing_rate = std::max({min_total_allocated_bitrate_, estimate_->link_capacity_lower, last_loss_based_target_rate_}) * diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h index 0dff2b13be..4d32d09883 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -93,6 +93,7 @@ class GoogCcNetworkController : public NetworkControllerInterface { const RateControlSettings rate_control_settings_; const bool loss_based_stable_rate_; const bool pace_at_max_of_bwe_and_lower_link_capacity_; + const bool pace_at_loss_based_bwe_when_loss_; const std::unique_ptr probe_controller_; const std::unique_ptr @@ -135,6 +136,7 @@ class GoogCcNetworkController : public NetworkControllerInterface { double pacing_factor_; DataRate min_total_allocated_bitrate_; DataRate max_padding_rate_; + DataRate max_total_allocated_bitrate_; bool previously_in_alr_ = false; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 61a005453b..eed3d9343a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -83,17 +83,13 @@ ProbeControllerConfig::ProbeControllerConfig( alr_probe_scale("alr_scale", 2), network_state_estimate_probing_interval("network_state_interval", TimeDelta::PlusInfinity()), - probe_if_estimate_lower_than_network_state_estimate_ratio( - "est_lower_than_network_ratio", - 0), - estimate_lower_than_network_state_estimate_probing_interval( - "est_lower_than_network_interval", - TimeDelta::seconds(3)), + network_state_estimate_fast_rampup_rate("network_state_fast_rampup_rate", + 0), + network_state_estimate_drop_down_rate("network_state_drop_down_rate", 0), network_state_probe_scale("network_state_scale", 1.0), network_state_probe_duration("network_state_probe_duration", TimeDelta::Millis<15>()), - probe_on_max_allocated_bitrate_change("probe_max_allocation", true), first_allocation_probe_scale("alloc_p1", 1), second_allocation_probe_scale("alloc_p2", 2), allocation_allow_further_probing("alloc_probe_further", false), @@ -102,31 +98,21 @@ ProbeControllerConfig::ProbeControllerConfig( min_probe_duration("min_probe_duration", TimeDelta::Millis<15>()), limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe", false), - loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", 0.0) { - ParseFieldTrial({&first_exponential_probe_scale, - &second_exponential_probe_scale, - &further_exponential_probe_scale, - &further_probe_threshold, - &alr_probing_interval, - &alr_probe_scale, - &probe_on_max_allocated_bitrate_change, - &first_allocation_probe_scale, - &second_allocation_probe_scale, - &allocation_allow_further_probing, - &min_probe_duration, - &network_state_estimate_probing_interval, - &probe_if_estimate_lower_than_network_state_estimate_ratio, - &estimate_lower_than_network_state_estimate_probing_interval, - &network_state_probe_scale, - &network_state_probe_duration, - &min_probe_packets_sent, - &limit_probe_target_rate_to_loss_bwe, - &loss_limited_probe_scale, - &skip_if_estimate_larger_than_fraction_of_max}, - key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); + ParseFieldTrial( + {&first_exponential_probe_scale, &second_exponential_probe_scale, + &further_exponential_probe_scale, &further_probe_threshold, + &alr_probing_interval, &alr_probe_scale, &first_allocation_probe_scale, + &second_allocation_probe_scale, &allocation_allow_further_probing, + &min_probe_duration, &network_state_estimate_probing_interval, + &network_state_estimate_fast_rampup_rate, + &network_state_estimate_drop_down_rate, &network_state_probe_scale, + &network_state_probe_duration, &min_probe_packets_sent, + &limit_probe_target_rate_to_loss_bwe, + &skip_if_estimate_larger_than_fraction_of_max}, + key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration ParseFieldTrial( @@ -134,9 +120,8 @@ ProbeControllerConfig::ProbeControllerConfig( key_value_config->Lookup("WebRTC-Bwe-InitialProbing")); ParseFieldTrial({&further_exponential_probe_scale, &further_probe_threshold}, key_value_config->Lookup("WebRTC-Bwe-ExponentialProbing")); - ParseFieldTrial( - {&alr_probing_interval, &alr_probe_scale, &loss_limited_probe_scale}, - key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); + ParseFieldTrial({&alr_probing_interval, &alr_probe_scale}, + key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); ParseFieldTrial( {&first_allocation_probe_scale, &second_allocation_probe_scale, &allocation_allow_further_probing, &allocation_probe_max}, @@ -220,8 +205,7 @@ std::vector ProbeController::OnMaxTotalAllocatedBitrate( const bool in_alr = alr_start_time_.has_value(); const bool allow_allocation_probe = in_alr; - if (config_.probe_on_max_allocated_bitrate_change && - state_ == State::kProbingComplete && + if (state_ == State::kProbingComplete && max_total_allocated_bitrate != max_total_allocated_bitrate_ && estimated_bitrate_ < max_bitrate_ && estimated_bitrate_ < max_total_allocated_bitrate && @@ -288,9 +272,13 @@ std::vector ProbeController::InitiateExponentialProbing( std::vector ProbeController::SetEstimatedBitrate( DataRate bitrate, - BandwidthLimitedCause bandwidth_limited_cause, + bool bwe_limited_due_to_packet_loss, Timestamp at_time) { - bandwidth_limited_cause_ = bandwidth_limited_cause; + if (bwe_limited_due_to_packet_loss != bwe_limited_due_to_packet_loss_ && + config_.limit_probe_target_rate_to_loss_bwe) { + state_ = State::kProbingComplete; + } + bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss; if (bitrate < kBitrateDropThreshold * estimated_bitrate_) { time_of_last_large_drop_ = at_time; bitrate_before_last_large_drop_ = estimated_bitrate_; @@ -309,28 +297,17 @@ std::vector ProbeController::SetEstimatedBitrate( if (state_ == State::kWaitingForProbingResult) { // Continue probing if probing results indicate channel has greater // capacity. - DataRate network_state_estimate_probe_further_limit = - config_.network_state_estimate_probing_interval->IsFinite() && - network_estimate_ - ? network_estimate_->link_capacity_upper * - config_.further_probe_threshold - : DataRate::PlusInfinity(); - - // MS_DEBUG_DEV( - // "[measured bitrate:%" PRIi64 ", minimum to probe further:%" PRIi64 "]", - // bitrate_bps, min_bitrate_to_probe_further_bps_); -/* RTC_LOG(LS_INFO) << "Measured bitrate: " << bitrate - << " Minimum to probe further: " - << min_bitrate_to_probe_further_ << " upper limit: " - << network_state_estimate_probe_further_limit;*/ - - if (bitrate > min_bitrate_to_probe_further_ && - bitrate <= network_state_estimate_probe_further_limit) { - return InitiateProbing( + // MS_DEBUG_DEV( + // "[measured bitrate:%" PRIi64 ", minimum to probe further:%" PRIi64 "]", + // bitrate_bps, min_bitrate_to_probe_further_bps_); + + if (bitrate > min_bitrate_to_probe_further_) { + pending_probes = InitiateProbing( at_time, {config_.further_exponential_probe_scale * bitrate}, true); } } - return {}; + + return pending_probes; } void ProbeController::EnablePeriodicAlrProbing(bool enable) { @@ -393,12 +370,30 @@ void ProbeController::SetMaxBitrate(DataRate max_bitrate) { void ProbeController::SetNetworkStateEstimate( webrtc::NetworkStateEstimate estimate) { + if (config_.network_state_estimate_fast_rampup_rate > 0 && + estimated_bitrate_ < estimate.link_capacity_upper && + (!network_estimate_ || + estimate.link_capacity_upper >= + config_.network_state_estimate_fast_rampup_rate * + network_estimate_->link_capacity_upper)) { + send_probe_on_next_process_interval_ = true; + } + if (config_.network_state_estimate_drop_down_rate > 0 && network_estimate_ && + !estimate.link_capacity_upper.IsZero() && + (estimated_bitrate_ > estimate.link_capacity_upper || + bwe_limited_due_to_packet_loss_) && + estimate.link_capacity_upper <= + config_.network_state_estimate_drop_down_rate * + network_estimate_->link_capacity_upper) { + send_probe_on_next_process_interval_ = true; + } + network_estimate_ = estimate; } void ProbeController::Reset(Timestamp at_time) { network_available_ = true; - bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited; + bwe_limited_due_to_packet_loss_ = false; state_ = State::kInit; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); time_last_probing_initiated_ = Timestamp::Zero(); @@ -413,6 +408,7 @@ void ProbeController::Reset(Timestamp at_time) { time_of_last_large_drop_ = now; bitrate_before_last_large_drop_ = DataRate::Zero(); max_total_allocated_bitrate_ = DataRate::Zero(); + send_probe_on_next_process_interval_ = false; } bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { @@ -426,34 +422,13 @@ bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { } bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const { - if (!network_estimate_ || - network_estimate_->link_capacity_upper.IsInfinite()) { - return false; - } - - bool probe_due_to_low_estimate = - bandwidth_limited_cause_ == BandwidthLimitedCause::kDelayBasedLimited && - estimated_bitrate_ < - config_.probe_if_estimate_lower_than_network_state_estimate_ratio * - network_estimate_->link_capacity_upper; - if (probe_due_to_low_estimate && - config_.estimate_lower_than_network_state_estimate_probing_interval - ->IsFinite()) { - Timestamp next_probe_time = - time_last_probing_initiated_ + - config_.estimate_lower_than_network_state_estimate_probing_interval; - return at_time >= next_probe_time; - } - - bool periodic_probe = - estimated_bitrate_ < network_estimate_->link_capacity_upper; - if (periodic_probe && - config_.network_state_estimate_probing_interval->IsFinite()) { + if (config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ && network_estimate_->link_capacity_upper.IsFinite() && + estimated_bitrate_ < network_estimate_->link_capacity_upper) { Timestamp next_probe_time = time_last_probing_initiated_ + config_.network_state_estimate_probing_interval; return at_time >= next_probe_time; } - return false; } @@ -471,7 +446,8 @@ std::vector ProbeController::Process(Timestamp at_time) { if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) { return {}; } - if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) { + if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) || + TimeForNetworkStateProbe(at_time)) { return InitiateProbing( at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true); } @@ -486,19 +462,32 @@ std::vector ProbeController::InitiateProbing( DataRate network_estimate = network_estimate_ ? network_estimate_->link_capacity_upper : DataRate::PlusInfinity(); - DataRate max_probe_rate = - max_total_allocated_bitrate_.IsZero() - ? max_bitrate_ - : std::min(max_total_allocated_bitrate_, max_bitrate_); if (std::min(network_estimate, estimated_bitrate_) > - config_.skip_if_estimate_larger_than_fraction_of_max * max_probe_rate) { - state_ = State::kProbingComplete; - min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); + config_.skip_if_estimate_larger_than_fraction_of_max * max_bitrate_) { return {}; } } + MS_DEBUG_DEV( + "[max_bitrate_bps_:%lld, max_probe_bitrate_bps:%" PRIi64 "]", + max_bitrate_bps_, + max_probe_bitrate_bps); + DataRate max_probe_bitrate = max_bitrate_; + if (bwe_limited_due_to_packet_loss_ && + config_.limit_probe_target_rate_to_loss_bwe) { + max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_); + } + if (config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { + if (network_estimate_->link_capacity_upper.IsZero()) { + MS_DEBUG_TAG(bwe, "Not sending probe, Network state estimate is zero"); + return {}; + } + max_probe_bitrate = + std::min(max_probe_bitrate, network_estimate_->link_capacity_upper * + config_.network_state_probe_scale); + } if (max_total_allocated_bitrate_ > DataRate::Zero()) { // If a max allocated bitrate has been configured, allow probing up to 2x // that rate. This allows some overhead to account for bursty streams, @@ -510,39 +499,12 @@ std::vector ProbeController::InitiateProbing( std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2); } - DataRate estimate_capped_bitrate = DataRate::PlusInfinity(); - if (config_.limit_probe_target_rate_to_loss_bwe) { - switch (bandwidth_limited_cause_) { - case BandwidthLimitedCause::kLossLimitedBweDecreasing: - // If bandwidth estimate is decreasing because of packet loss, do not - // send probes. - return {}; - case BandwidthLimitedCause::kLossLimitedBweIncreasing: - estimate_capped_bitrate = - std::min(max_probe_bitrate, - estimated_bitrate_ * config_.loss_limited_probe_scale); - break; - case BandwidthLimitedCause::kDelayBasedLimited: - break; - } - } - if (config_.network_state_estimate_probing_interval->IsFinite() && - network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { - if (network_estimate_->link_capacity_upper.IsZero()) { - // RTC_LOG(LS_INFO) << "Not sending probe, Network state estimate is zero"; - return {}; - } - estimate_capped_bitrate = - std::min({estimate_capped_bitrate, max_probe_bitrate, - network_estimate_->link_capacity_upper * - config_.network_state_probe_scale}); - } + send_probe_on_next_process_interval_ = false; std::vector pending_probes; for (DataRate bitrate : bitrates_to_probe) { // RTC_DCHECK(!bitrate.IsZero()); - bitrate = std::min(bitrate, estimate_capped_bitrate); if (bitrate > max_probe_bitrate) { bitrate = max_probe_bitrate; probe_further = false; @@ -567,11 +529,8 @@ std::vector ProbeController::InitiateProbing( time_last_probing_initiated_ = now; if (probe_further) { state_ = State::kWaitingForProbingResult; - // Dont expect probe results to be larger than a fraction of the actual - // probe rate. min_bitrate_to_probe_further_ = - std::min(estimate_capped_bitrate, (*(bitrates_to_probe.end() - 1))) * - config_.further_probe_threshold; + (*(bitrates_to_probe.end() - 1)) * config_.further_probe_threshold; } else { state_ = State::kProbingComplete; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h index 2954395c5d..1fda7813bf 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h @@ -46,19 +46,18 @@ struct ProbeControllerConfig { // Configures how often we send probes if NetworkStateEstimate is available. FieldTrialParameter network_state_estimate_probing_interval; - // Periodically probe as long as the the ratio beteeen current estimate and - // NetworkStateEstimate is lower then this. - FieldTrialParameter - probe_if_estimate_lower_than_network_state_estimate_ratio; - FieldTrialParameter - estimate_lower_than_network_state_estimate_probing_interval; + // If the network state estimate increase more than this rate, a probe is sent + // the next process interval. + FieldTrialParameter network_state_estimate_fast_rampup_rate; + // If the network state estimate decreases more than this rate, a probe is + // sent the next process interval. + FieldTrialParameter network_state_estimate_drop_down_rate; FieldTrialParameter network_state_probe_scale; // Overrides min_probe_duration if network_state_estimate_probing_interval // is set and a network state estimate is known. FieldTrialParameter network_state_probe_duration; // Configures the probes emitted by changed to the allocated bitrate. - FieldTrialParameter probe_on_max_allocated_bitrate_change; FieldTrialOptional first_allocation_probe_scale; FieldTrialOptional second_allocation_probe_scale; FieldTrialFlag allocation_allow_further_probing; @@ -68,23 +67,14 @@ struct ProbeControllerConfig { FieldTrialParameter min_probe_packets_sent; // The minimum probing duration. FieldTrialParameter min_probe_duration; - // Periodically probe when bandwidth estimate is loss limited. + // Max limit the target rate of a probe to current estimate if BWE is loss + // limited. FieldTrialParameter limit_probe_target_rate_to_loss_bwe; - FieldTrialParameter loss_limited_probe_scale; // Dont send a probe if min(estimate, network state estimate) is larger than // this fraction of the set max bitrate. FieldTrialParameter skip_if_estimate_larger_than_fraction_of_max; }; -// Reason that bandwidth estimate is limited. Bandwidth estimate can be limited -// by either delay based bwe, or loss based bwe when it increases/decreases the -// estimate. -enum class BandwidthLimitedCause { - kLossLimitedBweIncreasing = 0, - kLossLimitedBweDecreasing = 1, - kDelayBasedLimited = 2 -}; - // This class controls initiation of probing to estimate initial channel // capacity. There is also support for probing during a session when max // bitrate is adjusted by an application. @@ -113,7 +103,7 @@ class ProbeController { ABSL_MUST_USE_RESULT std::vector SetEstimatedBitrate( DataRate bitrate, - BandwidthLimitedCause bandwidth_limited_cause, + bool bwe_limited_due_to_packet_loss, Timestamp at_time); void EnablePeriodicAlrProbing(bool enable); @@ -155,12 +145,12 @@ class ProbeController { bool TimeForNetworkStateProbe(Timestamp at_time) const; bool network_available_; - BandwidthLimitedCause bandwidth_limited_cause_ = - BandwidthLimitedCause::kDelayBasedLimited; + bool bwe_limited_due_to_packet_loss_; State state_; DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity(); DataRate estimated_bitrate_ = DataRate::Zero(); + bool send_probe_on_next_process_interval_; absl::optional network_estimate_; DataRate start_bitrate_ = DataRate::Zero(); DataRate max_bitrate_ = DataRate::PlusInfinity(); diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 903750a21d..54970b0680 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -9,8 +9,7 @@ /* Static. */ static std::once_flag globalInitOnce; -static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; +static constexpr char FieldTrials[] = "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; /* Static methods. */ From 45b5d5c48790fbceeb4de35fa0a0ab17ccb526d5 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 24 Nov 2022 12:46:43 +0200 Subject: [PATCH 10/70] Fix instant loss calculation when sending at high bitrates. --- .../bitrate_controller/loss_based_bwe_v2.cc | 46 ++++++++++++------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 2ad27dcf38..b8ec0eb3b3 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -884,23 +884,37 @@ DataRate LossBasedBweV2::GetInstantUpperBound() const { } void LossBasedBweV2::CalculateInstantUpperBound() { - DataRate instant_limit = DataRate::PlusInfinity(); - const double average_reported_loss_ratio = GetAverageReportedLossRatio(); - if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { - instant_limit = config_->instant_upper_bound_bandwidth_balance / - (average_reported_loss_ratio - - config_->instant_upper_bound_loss_offset); - if (average_reported_loss_ratio > config_->high_loss_rate_threshold) { - instant_limit = std::min( - instant_limit, DataRate::kbps(std::max( - static_cast(min_bitrate_.kbps()), - config_->bandwidth_cap_at_high_loss_rate.kbps() - - config_->slope_of_bwe_high_loss_func * - average_reported_loss_ratio))); - } - } + DataRate instant_limit = DataRate::PlusInfinity(); + const double average_reported_loss_ratio = GetAverageReportedLossRatio(); + + // In case of high bitrates the value of balance (75kbps) is too small, + // and leads to big BW drops even in case of small loss ratio. + DataRate bandwidth_balance = DataRate::kbps(std::max( + config_->instant_upper_bound_bandwidth_balance.kbps(), + current_estimate_.loss_limited_bandwidth.kbps() / 100)); + + if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { + instant_limit = bandwidth_balance / + (average_reported_loss_ratio - + config_->instant_upper_bound_loss_offset); + +/* MS_DEBUG_DEV("balance %lld, instant_limit %lld, average_reported_loss_ratio %f, diff: %f", + bandwidth_balance.bps(), + instant_limit.bps(), + average_reported_loss_ratio, + average_reported_loss_ratio - config_->instant_upper_bound_loss_offset);*/ + + if (average_reported_loss_ratio > config_->high_loss_rate_threshold) { + instant_limit = std::min( + instant_limit, DataRate::kbps(std::max( + static_cast(min_bitrate_.kbps()), + config_->bandwidth_cap_at_high_loss_rate.kbps() - + config_->slope_of_bwe_high_loss_func * + average_reported_loss_ratio))); + } + } - cached_instant_upper_bound_ = instant_limit; + cached_instant_upper_bound_ = instant_limit; } void LossBasedBweV2::CalculateTemporalWeights() { From a468c21de2d816aa9d4d4e05540e2f1be800a614 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 24 Nov 2022 12:57:24 +0200 Subject: [PATCH 11/70] Fix issue when no periodic ALR probing when sudden drop in BW, and therefore stuck at low bitrate. --- .../goog_cc/alr_detector.cc | 22 ++++++++++++++++--- .../goog_cc/alr_detector.h | 3 ++- .../goog_cc/goog_cc_network_control.cc | 9 +------- .../goog_cc/probe_controller.cc | 16 ++++++++++---- 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 0bc5c2d67b..5a3182bb13 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -66,6 +66,17 @@ AlrDetector::AlrDetector(const WebRtcKeyValueConfig* key_value_config) AlrDetector::~AlrDetector() {} +// This is used to trigger ALR start state if we had sudden stop in traffic (all consumers paused due to low bw report). +// if no traffic in 1 second, trigger on OnBytesSent with 0 bitrate to update budgets. +void AlrDetector::Process() { + int64_t now = DepLibUV::GetTimeMsInt64(); + if (!alr_started_time_ms_.has_value() && last_send_time_ms_.has_value()) { + if ((now - last_send_time_ms_.value()) > 1000) { + OnBytesSent(0, now); + } + } +} + void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { if (!last_send_time_ms_.has_value()) { last_send_time_ms_ = send_time_ms; @@ -95,9 +106,14 @@ void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { void AlrDetector::SetEstimatedBitrate(int bitrate_bps) { //RTC_DCHECK(bitrate_bps); - int target_rate_kbps = - static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; - alr_budget_.set_target_rate_kbps(target_rate_kbps); + + if (last_estimated_bitrate_ != bitrate_bps) { + last_estimated_bitrate_ = bitrate_bps; + MS_DEBUG_TAG(bwe, "Setting ALR bitrate to %d", bitrate_bps); + int target_rate_kbps = + static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; + alr_budget_.set_target_rate_kbps(target_rate_kbps); + } } absl::optional AlrDetector::GetApplicationLimitedRegionStartTime() diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h index 42fc574150..2b3561a50a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.h @@ -58,13 +58,14 @@ class AlrDetector { // Returns time in milliseconds when the current application-limited region // started or empty result if the sender is currently not application-limited. absl::optional GetApplicationLimitedRegionStartTime() const; + void Process(); private: friend class GoogCcStatePrinter; const AlrDetectorConfig conf_; absl::optional last_send_time_ms_; - + int last_estimated_bitrate_; IntervalBudget alr_budget_; absl::optional alr_started_time_ms_; }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 5436c81c3f..f251d0b8fe 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -49,14 +49,6 @@ constexpr float kDefaultPaceMultiplier = 2.5f; // below the current throughput estimate to drain the network queues. constexpr double kProbeDropThroughputFraction = 0.85; -int64_t GetBpsOrDefault(const absl::optional& rate, - int64_t fallback_bps) { - if (rate && rate->IsFinite()) { - return rate->bps(); - } else { - return fallback_bps; - } -} bool IsEnabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Enabled") == 0; } @@ -202,6 +194,7 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( msg.pacer_queue->bytes()); } bandwidth_estimation_->UpdateEstimate(msg.at_time); + alr_detector_->Process(); absl::optional start_time_ms = alr_detector_->GetApplicationLimitedRegionStartTime(); probe_controller_->SetAlrStartTimeMs(start_time_ms); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index eed3d9343a..617da5ee17 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -316,13 +316,21 @@ void ProbeController::EnablePeriodicAlrProbing(bool enable) { void ProbeController::SetAlrStartTimeMs( absl::optional alr_start_time_ms) { - if (alr_start_time_ms) { - alr_start_time_ = Timestamp::ms(*alr_start_time_ms); - } else { + if ((alr_start_time_ms.has_value() && !alr_start_time_.has_value()) || + (alr_start_time_ms.has_value() && alr_start_time_.has_value() && (alr_start_time_.value().ms() != alr_start_time_ms.value()))) + { + MS_DEBUG_TAG(bwe, "ALR Start, start time %ld", alr_start_time_ms.value()); + alr_start_time_ = Timestamp::ms(alr_start_time_ms.value()); + } + if (alr_start_time_.has_value() && !alr_start_time_ms.has_value()) { + alr_start_time_ = absl::nullopt; + } + /*} else { alr_start_time_ = absl::nullopt; - } + }*/ } void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) { + MS_DEBUG_TAG(bwe, "ALR End, end time %lld", alr_end_time_ms); alr_end_time_.emplace(Timestamp::ms(alr_end_time_ms)); } From 6e6f6406368480a3eb9dddc4a373a191e13c4e84 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 24 Nov 2022 13:00:16 +0200 Subject: [PATCH 12/70] Increase InstantUpperBoundLossOffset slightly, because we don't have Pacer, and therfore we should allow bigger bursts. --- worker/src/DepLibWebRTC.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 54970b0680..8c63b093cb 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -9,7 +9,8 @@ /* Static. */ static std::once_flag globalInitOnce; -static constexpr char FieldTrials[] = "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; +static constexpr char FieldTrials[] = + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.85/"; /* Static methods. */ From 2dc6ad73481fe6aa2ddbe00ed13215ee7afa0aad Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 24 Nov 2022 13:00:47 +0200 Subject: [PATCH 13/70] Increase InstantUpperBoundLossOffset slightly, because we don't have Pacer, and therfore we should allow bigger bursts. --- worker/src/DepLibWebRTC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 8c63b093cb..aa6ebc29e5 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -10,7 +10,7 @@ static std::once_flag globalInitOnce; static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.85/"; + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.085/"; /* Static methods. */ From e7ee174f85cec68590c6d159fe2897547473332a Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 29 Nov 2022 01:01:01 +0200 Subject: [PATCH 14/70] Increase InstantUpperBoundLossOffset. Fix issue when cc colpases and unable to recover. Fix instant loss calculation at high bitrates. Increase ObservationDurationLowerBound. --- .../bitrate_controller/loss_based_bwe_v2.cc | 274 ++++++++++-------- .../bitrate_controller/loss_based_bwe_v2.h | 7 +- worker/src/DepLibWebRTC.cpp | 2 +- 3 files changed, 160 insertions(+), 123 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index b8ec0eb3b3..29dfbb5c82 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -85,10 +85,10 @@ double GetLossProbability(double inherent_loss, inherent_loss = std::min(std::max(inherent_loss, 0.0), 1.0); } if (!sending_rate.IsFinite()) { - MS_WARN_TAG(bwe, "The sending rate must be finite: %lld", sending_rate.kbps()); + MS_WARN_TAG(bwe, "The sending rate must be finite: %ld", sending_rate.bps()); } if (!loss_limited_bandwidth.IsFinite()) { - MS_WARN_TAG(bwe, "The loss limited bandwidth must be finite: %lld", loss_limited_bandwidth.kbps()); + MS_WARN_TAG(bwe, "The loss limited bandwidth must be finite: %ld", loss_limited_bandwidth.bps()); } double loss_probability = inherent_loss; @@ -114,12 +114,28 @@ LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) return; } - current_estimate_.inherent_loss = config_->initial_inherent_loss_estimate; - observations_.resize(config_->observation_window_size); - temporal_weights_.resize(config_->observation_window_size); - instant_upper_bound_temporal_weights_.resize( - config_->observation_window_size); - CalculateTemporalWeights(); + current_estimate_.inherent_loss = config_->initial_inherent_loss_estimate; + observations_.resize(config_->observation_window_size); + temporal_weights_.resize(config_->observation_window_size); + instant_upper_bound_temporal_weights_.resize( + config_->observation_window_size); + CalculateTemporalWeights(); +} + +void LossBasedBweV2::Reset() { + current_estimate_.inherent_loss = config_->initial_inherent_loss_estimate; + //current_estimate_.loss_limited_bandwidth = config_->bandwidth_rampup_upper_bound_factor; + + observations_.clear(); + temporal_weights_.clear(); + instant_upper_bound_temporal_weights_.clear(); + + observations_.resize(config_->observation_window_size); + temporal_weights_.resize(config_->observation_window_size); + instant_upper_bound_temporal_weights_.resize( + config_->observation_window_size); + + CalculateTemporalWeights(); } bool LossBasedBweV2::IsEnabled() const { @@ -135,26 +151,29 @@ bool LossBasedBweV2::IsReady() const { DataRate LossBasedBweV2::GetBandwidthEstimate( DataRate delay_based_limit) const { if (!IsReady()) { -/* if (!IsEnabled()) { - RTC_LOG(LS_WARNING) - << "The estimator must be enabled before it can be used."; + if (!IsEnabled()) { + MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); } else { if (!IsValid(current_estimate_.loss_limited_bandwidth)) { - RTC_LOG(LS_WARNING) - << "The estimator must be initialized before it can be used."; + MS_WARN_TAG(bwe, "The estimator must be initialized before it can be used."); } if (num_observations_ <= 0) { - RTC_LOG(LS_WARNING) << "The estimator must receive enough loss " - "statistics before it can be used."; + MS_WARN_TAG(bwe, "The estimator must receive enough loss statistics before it can be used."); } - }*/ + } return IsValid(delay_based_limit) ? delay_based_limit : DataRate::PlusInfinity(); } + auto instant_limit = GetInstantUpperBound(); + MS_DEBUG_DEV("Using %s, Inherent Loss limit %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 "", + current_estimate_.loss_limited_bandwidth.bps() <= delay_based_limit.bps() ? "Loss" : "Delay", + current_estimate_.loss_limited_bandwidth.bps(), + delay_based_limit.IsFinite() ? delay_based_limit.bps() : 0, + instant_limit.IsFinite() ? instant_limit.bps() : 0); if (delay_based_limit.IsFinite()) { return std::min({current_estimate_.loss_limited_bandwidth, - GetInstantUpperBound(), delay_based_limit}); + instant_limit, delay_based_limit}); } else { return std::min(current_estimate_.loss_limited_bandwidth, GetInstantUpperBound()); @@ -165,8 +184,7 @@ void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) { if (IsValid(acknowledged_bitrate)) { acknowledged_bitrate_ = acknowledged_bitrate; } else { -/* RTC_LOG(LS_WARNING) << "The acknowledged bitrate must be finite: " - << ToString(acknowledged_bitrate);*/ + MS_WARN_TAG(bwe, "The acknowledged bitrate must be finite: %" PRIi64 "", acknowledged_bitrate.bps()); } } @@ -174,8 +192,7 @@ void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) { if (IsValid(bandwidth_estimate)) { current_estimate_.loss_limited_bandwidth = bandwidth_estimate; } else { -/* RTC_LOG(LS_WARNING) << "The bandwidth estimate must be finite: " - << ToString(bandwidth_estimate);*/ + MS_WARN_TAG(bwe, "The bandwidth estimate must be finite: %" PRIi64 "", bandwidth_estimate.bps()); } } @@ -183,8 +200,7 @@ void LossBasedBweV2::SetMinBitrate(DataRate min_bitrate) { if (IsValid(min_bitrate)) { min_bitrate_ = min_bitrate; } else { -/* RTC_LOG(LS_WARNING) << "The min bitrate must be finite: " - << ToString(min_bitrate);*/ + MS_WARN_TAG(bwe, "The min bitrate must be finite: %" PRIi64 "", min_bitrate.bps()); } } @@ -193,13 +209,11 @@ void LossBasedBweV2::UpdateBandwidthEstimate( DataRate delay_based_estimate, BandwidthUsage delay_detector_state) { if (!IsEnabled()) { -/* RTC_LOG(LS_WARNING) - << "The estimator must be enabled before it can be used.";*/ + MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); return; } if (packet_results.empty()) { -/* RTC_LOG(LS_VERBOSE) - << "The estimate cannot be updated without any loss statistics.";*/ + MS_WARN_TAG(bwe, "The estimate cannot be updated without any loss statistics."); return; } @@ -208,8 +222,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate( } if (!IsValid(current_estimate_.loss_limited_bandwidth)) { -/* RTC_LOG(LS_VERBOSE) - << "The estimator must be initialized before it can be used.";*/ + MS_WARN_TAG(bwe, "The estimator must be initialized before it can be used."); return; } @@ -436,22 +449,44 @@ absl::optional LossBasedBweV2::CreateConfig( std::string candidate_factors_str; MS_DEBUG_TAG(bwe, "Loss V2 settings: "); - + MS_DEBUG_TAG(bwe, "bandwidth_rampup_upper_bound_factor: %f ", config->bandwidth_rampup_upper_bound_factor); + MS_DEBUG_TAG(bwe, "rampup_acceleration_max_factor: %f ", config->rampup_acceleration_max_factor); + MS_DEBUG_TAG(bwe, "rampup_acceleration_maxout_time: %" PRIi64 "", config->rampup_acceleration_maxout_time.ms()); for (double candidate_factor : config->candidate_factors) { - MS_DEBUG_TAG(bwe, "Candidate factor %f", candidate_factor); + MS_DEBUG_TAG(bwe, "candidate_factor: %f", candidate_factor); } + MS_DEBUG_TAG(bwe, "higher_bandwidth_bias_factor: %f ", config->higher_bandwidth_bias_factor); + MS_DEBUG_TAG(bwe, "slope_of_bwe_high_loss_func: %f ", config->slope_of_bwe_high_loss_func); + MS_DEBUG_TAG(bwe, "slope_of_bwe_high_loss_func: %f ", config->slope_of_bwe_high_loss_func); + MS_DEBUG_TAG(bwe, "higher_log_bandwidth_bias_factor: %f ", config->higher_log_bandwidth_bias_factor); + MS_DEBUG_TAG(bwe, "inherent_loss_lower_bound: %f ", config->inherent_loss_lower_bound); + MS_DEBUG_TAG(bwe, "loss_threshold_of_high_bandwidth_preference: %f ", config->loss_threshold_of_high_bandwidth_preference); + MS_DEBUG_TAG(bwe, "bandwidth_preference_smoothing_factor: %f ", config->bandwidth_preference_smoothing_factor); + MS_DEBUG_TAG(bwe, "inherent_loss_upper_bound_bandwidth_balance: %" PRIi64 "", config->inherent_loss_upper_bound_bandwidth_balance.bps()); + MS_DEBUG_TAG(bwe, "inherent_loss_upper_bound_offset: %f ", config->inherent_loss_upper_bound_offset); + MS_DEBUG_TAG(bwe, "initial_inherent_loss_estimate: %f ", config->initial_inherent_loss_estimate); + MS_DEBUG_TAG(bwe, "newton_iterations: %d ", config->newton_iterations); + MS_DEBUG_TAG(bwe, "newton_step_size: %f ", config->newton_step_size); + MS_DEBUG_TAG(bwe, "append_acknowledged_rate_candidate: %d ", config->append_acknowledged_rate_candidate); + MS_DEBUG_TAG(bwe, "append_delay_based_estimate_candidate: %d ", config->append_delay_based_estimate_candidate); + MS_DEBUG_TAG(bwe, "observation_duration_lower_bound: %" PRIi64 "", config->observation_duration_lower_bound.ms()); + MS_DEBUG_TAG(bwe, "observation_window_size: %d ", config->observation_window_size); + MS_DEBUG_TAG(bwe, "sending_rate_smoothing_factor: %f ", config->sending_rate_smoothing_factor); + MS_DEBUG_TAG(bwe, "instant_upper_bound_temporal_weight_factor: %f ", config->instant_upper_bound_temporal_weight_factor); + MS_DEBUG_TAG(bwe, "instant_upper_bound_bandwidth_balance: %" PRIi64 "", config->instant_upper_bound_bandwidth_balance.bps()); + MS_DEBUG_TAG(bwe, "instant_upper_bound_loss_offset: %f ", config->instant_upper_bound_loss_offset); + MS_DEBUG_TAG(bwe, "temporal_weight_factor: %f ", config->temporal_weight_factor); + MS_DEBUG_TAG(bwe, "bandwidth_backoff_lower_bound_factor: %f ", config->bandwidth_backoff_lower_bound_factor); + MS_DEBUG_TAG(bwe, "trendline_integration_enabled: %d ", config->trendline_integration_enabled); + MS_DEBUG_TAG(bwe, "trendline_observations_window_size: %d ", config->trendline_observations_window_size); + MS_DEBUG_TAG(bwe, "max_increase_factor: %f ", config->max_increase_factor); + MS_DEBUG_TAG(bwe, "delayed_increase_window: %" PRIi64 "", config->delayed_increase_window.ms()); + MS_DEBUG_TAG(bwe, "use_acked_bitrate_only_when_overusing: %d ", config->use_acked_bitrate_only_when_overusing); + MS_DEBUG_TAG(bwe, "not_increase_if_inherent_loss_less_than_average_loss: %d ", config->not_increase_if_inherent_loss_less_than_average_loss); + MS_DEBUG_TAG(bwe, "high_loss_rate_threshold: %f ", config->high_loss_rate_threshold); + MS_DEBUG_TAG(bwe, "bandwidth_cap_at_high_loss_rate: %" PRIi64 "", config->bandwidth_cap_at_high_loss_rate.bps()); + MS_DEBUG_TAG(bwe, "slope_of_bwe_high_loss_func: %f ", config->slope_of_bwe_high_loss_func); - MS_DEBUG_TAG(bwe, "Loss V2 settings: " - "pacing bandwidth_rampup_upper_bound_factor: %f" - ", rampup_acceleration_max_factor: %f" - ", rampup_acceleration_maxout_time: %lld" - ", higher_bandwidth_bias_factor: %f" - ", NotIncreaseIfInherentLossLessThanAverageLoss: %d", - config->bandwidth_rampup_upper_bound_factor, - config->rampup_acceleration_max_factor, - config->rampup_acceleration_maxout_time.ms(), - config->higher_bandwidth_bias_factor, - config->not_increase_if_inherent_loss_less_than_average_loss); return config; } @@ -464,27 +499,23 @@ bool LossBasedBweV2::IsConfigValid() const { bool valid = true; if (config_->bandwidth_rampup_upper_bound_factor <= 1.0) { -/* RTC_LOG(LS_WARNING) - << "The bandwidth rampup upper bound factor must be greater than 1: " - << config_->bandwidth_rampup_upper_bound_factor;*/ + MS_WARN_TAG(bwe, "The bandwidth rampup upper bound factor must be greater than 1: %f", + config_->bandwidth_rampup_upper_bound_factor); valid = false; } if (config_->rampup_acceleration_max_factor < 0.0) { -/* RTC_LOG(LS_WARNING) - << "The rampup acceleration max factor must be non-negative.: " - << config_->rampup_acceleration_max_factor;*/ + MS_WARN_TAG(bwe, "The rampup acceleration max factor must be non-negative.: %f", + config_->rampup_acceleration_max_factor); valid = false; } if (config_->rampup_acceleration_maxout_time <= TimeDelta::Zero()) { -/* RTC_LOG(LS_WARNING) - << "The rampup acceleration maxout time must be above zero: " - << config_->rampup_acceleration_maxout_time.seconds();*/ + MS_WARN_TAG(bwe, "The rampup acceleration maxout time must be above zero: %ld ", + config_->rampup_acceleration_maxout_time.seconds()); valid = false; } for (double candidate_factor : config_->candidate_factors) { if (candidate_factor <= 0.0) { - /* RTC_LOG(LS_WARNING) << "All candidate factors must be greater than zero: " - << candidate_factor;*/ + MS_WARN_TAG(bwe, "All candidate factors must be greater than zero: %f", candidate_factor); valid = false; } } @@ -495,146 +526,129 @@ bool LossBasedBweV2::IsConfigValid() const { !config_->append_delay_based_estimate_candidate && !absl::c_any_of(config_->candidate_factors, [](double cf) { return cf != 1.0; })) { -/* RTC_LOG(LS_WARNING) - << "The configuration does not allow generating candidates. Specify " + MS_WARN_TAG(bwe, "The configuration does not allow generating candidates. Specify " "a candidate factor other than 1.0, allow the acknowledged rate " "to be a candidate, and/or allow the delay based estimate to be a " - "candidate.";*/ + "candidate."); valid = false; } if (config_->higher_bandwidth_bias_factor < 0.0) { -/* RTC_LOG(LS_WARNING) - << "The higher bandwidth bias factor must be non-negative: " - << config_->higher_bandwidth_bias_factor;*/ + MS_WARN_TAG(bwe, "The higher bandwidth bias factor must be non-negative: %f", + config_->higher_bandwidth_bias_factor); valid = false; } if (config_->inherent_loss_lower_bound < 0.0 || config_->inherent_loss_lower_bound >= 1.0) { -/* RTC_LOG(LS_WARNING) << "The inherent loss lower bound must be in [0, 1): " - << config_->inherent_loss_lower_bound;*/ + MS_WARN_TAG(bwe, "The inherent loss lower bound must be in [0, 1] %f ", + config_->inherent_loss_lower_bound); valid = false; } if (config_->loss_threshold_of_high_bandwidth_preference < 0.0 || config_->loss_threshold_of_high_bandwidth_preference >= 1.0) { -/* RTC_LOG(LS_WARNING) - << "The loss threshold of high bandwidth preference must be in [0, 1): " - << config_->loss_threshold_of_high_bandwidth_preference;*/ + MS_WARN_TAG(bwe, "The loss threshold of high bandwidth preference must be in [0, 1]: %f", + config_->loss_threshold_of_high_bandwidth_preference); valid = false; } if (config_->bandwidth_preference_smoothing_factor <= 0.0 || config_->bandwidth_preference_smoothing_factor > 1.0) { -/* RTC_LOG(LS_WARNING) - << "The bandwidth preference smoothing factor must be in (0, 1]: " - << config_->bandwidth_preference_smoothing_factor;*/ + MS_WARN_TAG(bwe, "The bandwidth preference smoothing factor must be in [0, 1]: %f", + config_->bandwidth_preference_smoothing_factor); valid = false; } if (config_->inherent_loss_upper_bound_bandwidth_balance <= DataRate::Zero()) { -/* RTC_LOG(LS_WARNING) - << "The inherent loss upper bound bandwidth balance " - "must be positive: " - << ToString(config_->inherent_loss_upper_bound_bandwidth_balance);*/ + MS_WARN_TAG(bwe, "The inherent loss upper bound bandwidth balance must be positive: %ld", + config_->inherent_loss_upper_bound_bandwidth_balance.bps()); valid = false; } if (config_->inherent_loss_upper_bound_offset < config_->inherent_loss_lower_bound || config_->inherent_loss_upper_bound_offset >= 1.0) { -/* RTC_LOG(LS_WARNING) << "The inherent loss upper bound must be greater " - "than or equal to the inherent " - "loss lower bound, which is " - << config_->inherent_loss_lower_bound - << ", and less than 1: " - << config_->inherent_loss_upper_bound_offset;*/ + MS_WARN_TAG(bwe, "The inherent loss upper bound must be greater than or equal to the inherent " + "loss lower bound, which is %f, and less than 1: %f", + config_->inherent_loss_lower_bound, + config_->inherent_loss_upper_bound_offset); valid = false; } if (config_->initial_inherent_loss_estimate < 0.0 || config_->initial_inherent_loss_estimate >= 1.0) { -/* RTC_LOG(LS_WARNING) - << "The initial inherent loss estimate must be in [0, 1): " - << config_->initial_inherent_loss_estimate;*/ + MS_WARN_TAG(bwe, "The initial inherent loss estimate must be in [0, 1]: %f", + config_->initial_inherent_loss_estimate); valid = false; } if (config_->newton_iterations <= 0) { -/* RTC_LOG(LS_WARNING) << "The number of Newton iterations must be positive: " - << config_->newton_iterations;*/ + MS_WARN_TAG(bwe, "The number of Newton iterations must be positive: %d", + config_->newton_iterations); valid = false; } if (config_->newton_step_size <= 0.0) { -/* RTC_LOG(LS_WARNING) << "The Newton step size must be positive: " - << config_->newton_step_size;*/ + MS_WARN_TAG(bwe, "The Newton step size must be positive: %f", + config_->newton_step_size); valid = false; } if (config_->observation_duration_lower_bound <= TimeDelta::Zero()) { -/* RTC_LOG(LS_WARNING) - << "The observation duration lower bound must be positive: " - << ToString(config_->observation_duration_lower_bound);*/ + MS_WARN_TAG(bwe, "The observation duration lower bound must be positive: %" PRIi64 " ms", + config_->observation_duration_lower_bound.ms()); valid = false; } if (config_->observation_window_size < 2) { -/* RTC_LOG(LS_WARNING) << "The observation window size must be at least 2: " - << config_->observation_window_size;*/ + MS_WARN_TAG(bwe, "The observation window size must be at least 2: %d", + config_->observation_window_size); valid = false; } if (config_->sending_rate_smoothing_factor < 0.0 || config_->sending_rate_smoothing_factor >= 1.0) { -/* RTC_LOG(LS_WARNING) - << "The sending rate smoothing factor must be in [0, 1): " - << config_->sending_rate_smoothing_factor;*/ + MS_WARN_TAG(bwe, "The sending rate smoothing factor must be in (0, 1): %f", + config_->sending_rate_smoothing_factor); valid = false; } if (config_->instant_upper_bound_temporal_weight_factor <= 0.0 || config_->instant_upper_bound_temporal_weight_factor > 1.0) { -/* RTC_LOG(LS_WARNING) - << "The instant upper bound temporal weight factor must be in (0, 1]" - << config_->instant_upper_bound_temporal_weight_factor;*/ + MS_WARN_TAG(bwe, "The instant upper bound temporal weight factor must be in (0, 1] %f", + config_->instant_upper_bound_temporal_weight_factor); valid = false; } if (config_->instant_upper_bound_bandwidth_balance <= DataRate::Zero()) { -/* RTC_LOG(LS_WARNING) - << "The instant upper bound bandwidth balance must be positive: " - << ToString(config_->instant_upper_bound_bandwidth_balance);*/ + MS_WARN_TAG(bwe, "The instant upper bound bandwidth balance must be positive: %" PRIi64 "", + config_->instant_upper_bound_bandwidth_balance.bps()); valid = false; } if (config_->instant_upper_bound_loss_offset < 0.0 || config_->instant_upper_bound_loss_offset >= 1.0) { -/* RTC_LOG(LS_WARNING) - << "The instant upper bound loss offset must be in [0, 1): " - << config_->instant_upper_bound_loss_offset;*/ + MS_WARN_TAG(bwe, "The instant upper bound loss offset must be in [0, 1): %f", + config_->instant_upper_bound_loss_offset); valid = false; } if (config_->temporal_weight_factor <= 0.0 || config_->temporal_weight_factor > 1.0) { -/* RTC_LOG(LS_WARNING) << "The temporal weight factor must be in (0, 1]: " - << config_->temporal_weight_factor;*/ + MS_WARN_TAG(bwe, "The temporal weight factor must be in (0, 1]: %f", + config_->temporal_weight_factor); valid = false; } if (config_->bandwidth_backoff_lower_bound_factor > 1.0) { -/* RTC_LOG(LS_WARNING) - << "The bandwidth backoff lower bound factor must not be greater than " - "1: " - << config_->bandwidth_backoff_lower_bound_factor;*/ + MS_WARN_TAG(bwe, "The bandwidth backoff lower bound factor must not be greater than 1: %f", + config_->bandwidth_backoff_lower_bound_factor); valid = false; } if (config_->trendline_observations_window_size < 1) { -/* RTC_LOG(LS_WARNING) << "The trendline window size must be at least 1: " - << config_->trendline_observations_window_size;*/ + MS_WARN_TAG(bwe, "The trendline window size must be at least 1: %d", + config_->trendline_observations_window_size); valid = false; } if (config_->max_increase_factor <= 0.0) { -/* RTC_LOG(LS_WARNING) << "The maximum increase factor must be positive: " - << config_->max_increase_factor;*/ + MS_WARN_TAG(bwe, "The maximum increase factor must be positive: %f", config_->max_increase_factor); valid = false; } if (config_->delayed_increase_window <= TimeDelta::Zero()) { -/* RTC_LOG(LS_WARNING) << "The delayed increase window must be positive: " - << config_->delayed_increase_window.ms();*/ + MS_WARN_TAG(bwe, "The delayed increase window must be positive: %" PRIi64 " ms", + config_->delayed_increase_window.ms()); valid = false; } if (config_->high_loss_rate_threshold <= 0.0 || config_->high_loss_rate_threshold > 1.0) { -/* RTC_LOG(LS_WARNING) << "The high loss rate threshold must be in (0, 1]: " - << config_->high_loss_rate_threshold;*/ + MS_WARN_TAG(bwe, "The high loss rate threshold must be in (0, 1]: %f", + config_->high_loss_rate_threshold); valid = false; } return valid; @@ -889,20 +903,21 @@ void LossBasedBweV2::CalculateInstantUpperBound() { // In case of high bitrates the value of balance (75kbps) is too small, // and leads to big BW drops even in case of small loss ratio. - DataRate bandwidth_balance = DataRate::kbps(std::max( - config_->instant_upper_bound_bandwidth_balance.kbps(), - current_estimate_.loss_limited_bandwidth.kbps() / 100)); + DataRate bandwidth_balance = DataRate::bps(std::max( + config_->instant_upper_bound_bandwidth_balance.bps(), + current_estimate_.loss_limited_bandwidth.bps() / 100)); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { instant_limit = bandwidth_balance / (average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); -/* MS_DEBUG_DEV("balance %lld, instant_limit %lld, average_reported_loss_ratio %f, diff: %f", + + MS_DEBUG_DEV("Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 ", average_reported_loss_ratio %f, diff: %f", bandwidth_balance.bps(), - instant_limit.bps(), + instant_limit.IsFinite() ? instant_limit.bps() : 0, average_reported_loss_ratio, - average_reported_loss_ratio - config_->instant_upper_bound_loss_offset);*/ + average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); if (average_reported_loss_ratio > config_->high_loss_rate_threshold) { instant_limit = std::min( @@ -1002,11 +1017,28 @@ bool LossBasedBweV2::PushBackObservation( const Timestamp last_send_time = packet_results_summary.last_send_time; const TimeDelta observation_duration = last_send_time - last_send_time_most_recent_observation_; + + // MS_NOTE Here we reset loss estimator if there was not traffic in + // max_observation_duration_before_reset_, otherwise, we will stuck + // at low bitrate. + if (observation_duration > max_observation_duration_before_reset_) { + MS_DEBUG_TAG(bwe, "Too big observation duration, resetting stats"); + MS_DEBUG_TAG(bwe, "Current estimate bw: %" PRIi64 ", inherent_loss: %f", current_estimate_.loss_limited_bandwidth.bps(), current_estimate_.inherent_loss); + Reset(); + } + + // Too small to be meaningful. if (observation_duration <= TimeDelta::Zero() || (observation_duration < config_->observation_duration_lower_bound && (delay_detector_state != BandwidthUsage::kBwOverusing || !config_->trendline_integration_enabled))) { + MS_DEBUG_DEV("Observation Duration %" PRIi64 ", Delay detector state %s, trendline_integration_enabled, %d, Current estimate %" PRIi64 "", + observation_duration.ms(), + delay_detector_state == BandwidthUsage::kBwNormal ? "Normal" : + delay_detector_state == BandwidthUsage::kBwOverusing ? "Overusing" : "Underusing", + config_->trendline_integration_enabled, + current_estimate_.loss_limited_bandwidth.bps()); return false; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 9dc2215395..192d05fe2c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -155,6 +155,8 @@ class LossBasedBweV2 { Timestamp at_time); void UpdateDelayDetector(BandwidthUsage delay_detector_state); + void Reset(); + absl::optional acknowledged_bitrate_; absl::optional config_; ChannelParameters current_estimate_; @@ -170,7 +172,10 @@ class LossBasedBweV2 { Timestamp recovering_after_loss_timestamp_ = Timestamp::MinusInfinity(); DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); bool limited_due_to_loss_candidate_ = false; - DataRate min_bitrate_ = DataRate::kbps(1); + // MS_NOTE changed min bitrate from 1 to 100, this allows faster recover + // from huge drop. + DataRate min_bitrate_ = DataRate::kbps(100); + TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); }; } // namespace webrtc diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index aa6ebc29e5..f7c4717fc5 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -10,7 +10,7 @@ static std::once_flag globalInitOnce; static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.085/"; + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:500ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.11/"; /* Static methods. */ From e4b7bf8537236080c73c53d14e84e6c490ff3168 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 29 Nov 2022 01:07:55 +0200 Subject: [PATCH 15/70] clean --- .../libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 29dfbb5c82..911e8f025b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ #define MS_CLASS "webrtc::LossBasedBweV2" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/bitrate_controller/loss_based_bwe_v2.h" From 1647d07a1d35827211237f3d35a1b661b3691be5 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 30 Nov 2022 14:07:26 +0200 Subject: [PATCH 16/70] Add BW balance multiplication to have a meaningful backoff. --- .../libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc | 2 +- .../libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 911e8f025b..a49a4598de 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -905,7 +905,7 @@ void LossBasedBweV2::CalculateInstantUpperBound() { // and leads to big BW drops even in case of small loss ratio. DataRate bandwidth_balance = DataRate::bps(std::max( config_->instant_upper_bound_bandwidth_balance.bps(), - current_estimate_.loss_limited_bandwidth.bps() / 100)); + current_estimate_.loss_limited_bandwidth.bps() * kBwBalanceMultiplicator / 100)); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { instant_limit = bandwidth_balance / diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 192d05fe2c..95fa8249d9 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -176,6 +176,7 @@ class LossBasedBweV2 { // from huge drop. DataRate min_bitrate_ = DataRate::kbps(100); TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); + long long static constexpr kBwBalanceMultiplicator = 1.3; }; } // namespace webrtc From 07bea0fe56623c2fd2ff526c42ef4254a17aa7ac Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 30 Nov 2022 18:30:31 +0200 Subject: [PATCH 17/70] Fix BW balance calculation. Adjust loss settings. --- .../modules/bitrate_controller/loss_based_bwe_v2.cc | 12 ++++++------ .../modules/bitrate_controller/loss_based_bwe_v2.h | 2 +- worker/src/DepLibWebRTC.cpp | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index a49a4598de..c734277525 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -901,13 +901,13 @@ void LossBasedBweV2::CalculateInstantUpperBound() { DataRate instant_limit = DataRate::PlusInfinity(); const double average_reported_loss_ratio = GetAverageReportedLossRatio(); - // In case of high bitrates the value of balance (75kbps) is too small, - // and leads to big BW drops even in case of small loss ratio. - DataRate bandwidth_balance = DataRate::bps(std::max( - config_->instant_upper_bound_bandwidth_balance.bps(), - current_estimate_.loss_limited_bandwidth.bps() * kBwBalanceMultiplicator / 100)); - if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { + // In case of high bitrates the value of balance (75kbps) is too small, + // and leads to big BW drops even in case of small loss ratio. + DataRate bandwidth_balance = DataRate::bps(std::max( + static_cast(config_->instant_upper_bound_bandwidth_balance.bps()), + (current_estimate_.loss_limited_bandwidth.bps() / 100) * kBwBalanceMultiplicator)); + instant_limit = bandwidth_balance / (average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 95fa8249d9..b7607ba8d9 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -176,7 +176,7 @@ class LossBasedBweV2 { // from huge drop. DataRate min_bitrate_ = DataRate::kbps(100); TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); - long long static constexpr kBwBalanceMultiplicator = 1.3; + double static constexpr kBwBalanceMultiplicator = 1.3; }; } // namespace webrtc diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index f7c4717fc5..029ae51d59 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -10,7 +10,7 @@ static std::once_flag globalInitOnce; static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:500ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.11/"; + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:400ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.8/"; /* Static methods. */ From f613ad23c657befe2e6dba1e1b1616ba4a59935a Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 30 Nov 2022 19:07:31 +0200 Subject: [PATCH 18/70] Revert to default coefficients --- worker/src/DepLibWebRTC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 029ae51d59..0dd4c228fe 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -10,7 +10,7 @@ static std::once_flag globalInitOnce; static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:400ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.8/"; + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.5/"; /* Static methods. */ From 4c0202f0c5cb88ddb8ca2a500d0876dec649ff01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?I=C3=B1aki=20Baz=20Castillo?= Date: Thu, 1 Dec 2022 12:50:02 +0100 Subject: [PATCH 19/70] Apply suggestions from code review --- .../libwebrtc/api/transport/network_types.h | 2 +- .../modules/bitrate_controller/loss_based_bwe_v2.h | 4 ++-- .../acknowledged_bitrate_estimator_interface.cc | 12 ++++++------ .../congestion_controller/goog_cc/alr_detector.cc | 4 ++-- .../goog_cc/inter_arrival_delta.cc | 4 ++-- .../goog_cc/trendline_estimator.cc | 8 ++++---- 6 files changed, 17 insertions(+), 17 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index bd76166aa9..1c8d71e361 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -48,7 +48,7 @@ struct StreamsConfig { absl::optional requests_alr_probing; absl::optional pacing_factor; - // TODO(srte): Use BitrateAllocationLimits here. + // TODO: (srte) Use BitrateAllocationLimits here. absl::optional min_total_allocated_bitrate; absl::optional max_padding_rate; absl::optional max_total_allocated_bitrate; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index b7607ba8d9..ba67ac649a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -172,8 +172,8 @@ class LossBasedBweV2 { Timestamp recovering_after_loss_timestamp_ = Timestamp::MinusInfinity(); DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); bool limited_due_to_loss_candidate_ = false; - // MS_NOTE changed min bitrate from 1 to 100, this allows faster recover - // from huge drop. + // NOTE: changed min bitrate from 1 to 100, this allows faster recover + // from huge drop. DataRate min_bitrate_ = DataRate::kbps(100); TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); double static constexpr kBwBalanceMultiplicator = 1.3; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc index 6bfd1c81cb..be4020f3e8 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.cc @@ -29,17 +29,17 @@ RobustThroughputEstimatorSettings::RobustThroughputEstimatorSettings( Parser()->Parse( key_value_config->Lookup(RobustThroughputEstimatorSettings::kKey)); if (window_packets < 10 || 1000 < window_packets) { - MS_WARN_TAG(bwe, "Window size must be between 10 and 1000 packets"); + MS_WARN_TAG(bwe, "window size must be between 10 and 1000 packets"); window_packets = 20; } if (max_window_packets < 10 || 1000 < max_window_packets) { - MS_WARN_TAG(bwe, "Max window size must be between 10 and 1000 packets"); + MS_WARN_TAG(bwe, "max window size must be between 10 and 1000 packets"); max_window_packets = 500; } max_window_packets = std::max(max_window_packets, window_packets); if (required_packets < 10 || 1000 < required_packets) { - MS_WARN_TAG(bwe, "Required number of initial packets must be between " + MS_WARN_TAG(bwe, "required number of initial packets must be between " "10 and 1000 packets"); required_packets = 10; } @@ -47,18 +47,18 @@ RobustThroughputEstimatorSettings::RobustThroughputEstimatorSettings( if (min_window_duration < TimeDelta::Millis<100>() || TimeDelta::Millis<3000>() < min_window_duration) { - MS_WARN_TAG(bwe, "Window duration must be between 100 and 3000 ms"); + MS_WARN_TAG(bwe, "window duration must be between 100 and 3000 ms"); min_window_duration = TimeDelta::Millis<750>(); } if (max_window_duration < TimeDelta::Seconds<1>() || TimeDelta::Seconds<15>() < max_window_duration) { - MS_WARN_TAG(bwe, "Max window duration must be between 1 and 15 s"); + MS_WARN_TAG(bwe, "max window duration must be between 1 and 15 seconds"); max_window_duration = TimeDelta::Seconds<5>(); } min_window_duration = std::min(min_window_duration, max_window_duration); if (unacked_weight < 0.0 || 1.0 < unacked_weight) { - MS_WARN_TAG(bwe, "Weight for prior unacked size must be between 0 and 1."); + MS_WARN_TAG(bwe, "weight for prior unacked size must be between 0 and 1"); unacked_weight = 1.0; } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc index 5a3182bb13..3b12676c99 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc @@ -100,7 +100,7 @@ void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) { alr_started_time_ms_.reset(); } if (state_changed) { - MS_DEBUG_TAG(bwe, "ALR State change"); + MS_DEBUG_TAG(bwe, "ALR state change"); } } @@ -109,7 +109,7 @@ void AlrDetector::SetEstimatedBitrate(int bitrate_bps) { if (last_estimated_bitrate_ != bitrate_bps) { last_estimated_bitrate_ = bitrate_bps; - MS_DEBUG_TAG(bwe, "Setting ALR bitrate to %d", bitrate_bps); + MS_DEBUG_TAG(bwe, "setting ALR bitrate to %d bps", bitrate_bps); int target_rate_kbps = static_cast(bitrate_bps) * conf_.bandwidth_usage_ratio / 1000; alr_budget_.set_target_rate_kbps(target_rate_kbps); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc index 75386bc704..44090ba60e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/inter_arrival_delta.cc @@ -60,7 +60,7 @@ bool InterArrivalDelta::ComputeDeltas(Timestamp send_time, if (*arrival_time_delta - system_time_delta >= kArrivalTimeOffsetThreshold) { - MS_WARN_TAG(bwe, "The arrival time clock offset has changed (diff = %lld ms), resetting.", + MS_WARN_TAG(bwe, "the arrival time clock offset has changed (diff = %lld ms), resetting", arrival_time_delta->ms() - system_time_delta.ms()); Reset(); return false; @@ -70,7 +70,7 @@ bool InterArrivalDelta::ComputeDeltas(Timestamp send_time, // arrival timestamp. ++num_consecutive_reordered_packets_; if (num_consecutive_reordered_packets_ >= kReorderedResetThreshold) { - MS_WARN_TAG(bwe, "Packets between send burst arrived out of order, resetting. arrival_time_delta %lld send time delta %lld", + MS_WARN_TAG(bwe, "packets between send burst arrived out of order, resetting. arrival_time_delta %lld send time delta %lld", arrival_time_delta->ms(), send_time_delta->ms()); Reset(); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index ac95090d75..8d7655218d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -120,25 +120,25 @@ TrendlineEstimatorSettings::TrendlineEstimatorSettings( } Parser()->Parse(key_value_config->Lookup(TrendlineEstimatorSettings::kKey)); if (window_size < 10 || 200 < window_size) { - MS_WARN_TAG(bwe, "Window size must be between 10 and 200 packets"); + MS_WARN_TAG(bwe, "window size must be between 10 and 200 packets"); window_size = kDefaultTrendlineWindowSize; } if (enable_cap) { if (beginning_packets < 1 || end_packets < 1 || beginning_packets > window_size || end_packets > window_size) { - MS_WARN_TAG(bwe, "Size of beginning and end must be between 1 and %d", window_size); + MS_WARN_TAG(bwe, "size of beginning and end must be between 1 and %d", window_size); enable_cap = false; beginning_packets = end_packets = 0; cap_uncertainty = 0.0; } if (beginning_packets + end_packets > window_size) { - MS_WARN_TAG(bwe, "Size of beginning plus end can't exceed the window size"); + MS_WARN_TAG(bwe, "size of beginning plus end can't exceed the window size"); enable_cap = false; beginning_packets = end_packets = 0; cap_uncertainty = 0.0; } if (cap_uncertainty < 0.0 || 0.025 < cap_uncertainty) { - MS_WARN_TAG(bwe, "Cap uncertainty must be between 0 and 0.025"); + MS_WARN_TAG(bwe, "cap uncertainty must be between 0 and 0.025"); cap_uncertainty = 0.0; } } From c4b007cb145485776b125b75ebaf140edf4d9e77 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 1 Dec 2022 14:34:00 +0200 Subject: [PATCH 20/70] Fix default coefficients --- worker/src/DepLibWebRTC.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 0dd4c228fe..903750a21d 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -10,7 +10,7 @@ static std::once_flag globalInitOnce; static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,InstantUpperBoundLossOffset:0.5/"; + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; /* Static methods. */ From 2c4994f273c02e1d9980859ff4a1d0599e68e56a Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 2 Dec 2022 14:18:44 +0200 Subject: [PATCH 21/70] Use sending rate instead of estimate in BW balance calculation, when sending at high rates. --- .../bitrate_controller/loss_based_bwe_v2.cc | 50 ++++++++++--------- .../bitrate_controller/loss_based_bwe_v2.h | 2 +- worker/src/DepLibWebRTC.cpp | 2 +- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index c734277525..421bd42f46 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -897,27 +897,31 @@ DataRate LossBasedBweV2::GetInstantUpperBound() const { return cached_instant_upper_bound_.value_or(DataRate::PlusInfinity()); } -void LossBasedBweV2::CalculateInstantUpperBound() { +void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { DataRate instant_limit = DataRate::PlusInfinity(); const double average_reported_loss_ratio = GetAverageReportedLossRatio(); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { - // In case of high bitrates the value of balance (75kbps) is too small, - // and leads to big BW drops even in case of small loss ratio. - DataRate bandwidth_balance = DataRate::bps(std::max( - static_cast(config_->instant_upper_bound_bandwidth_balance.bps()), - (current_estimate_.loss_limited_bandwidth.bps() / 100) * kBwBalanceMultiplicator)); + + DataRate bandwidth_balance = config_->instant_upper_bound_bandwidth_balance; + + // MS_NOTE: In case of high sending rate the value of balance (75kbps) is too small, + // and leads to big BW drops even in the case of small loss ratio. + if (sending_rate.bps() > config_->instant_upper_bound_bandwidth_balance.bps() * 100) { + bandwidth_balance = DataRate::bps((sending_rate.bps() / 100) * kBwBalanceMultiplicator); + } instant_limit = bandwidth_balance / (average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); - MS_DEBUG_DEV("Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 ", average_reported_loss_ratio %f, diff: %f", + MS_DEBUG_DEV("Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 ", average_reported_loss_ratio %f, diff: %f, sending rate: %lld", bandwidth_balance.bps(), instant_limit.IsFinite() ? instant_limit.bps() : 0, average_reported_loss_ratio, - average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); + average_reported_loss_ratio - config_->instant_upper_bound_loss_offset, + sending_rate.bps()); if (average_reported_loss_ratio > config_->high_loss_rate_threshold) { instant_limit = std::min( @@ -961,10 +965,11 @@ bool LossBasedBweV2::TrendlineEsimateAllowBitrateIncrease() const { } for (const auto& detector_state : delay_detector_states_) { - if (detector_state == BandwidthUsage::kBwOverusing || +/* if (detector_state == BandwidthUsage::kBwOverusing || detector_state == BandwidthUsage::kBwUnderusing) { return false; - } + }*/ + if (detector_state == BandwidthUsage::kBwOverusing) return false; } return true; } @@ -1018,16 +1023,6 @@ bool LossBasedBweV2::PushBackObservation( const TimeDelta observation_duration = last_send_time - last_send_time_most_recent_observation_; - // MS_NOTE Here we reset loss estimator if there was not traffic in - // max_observation_duration_before_reset_, otherwise, we will stuck - // at low bitrate. - if (observation_duration > max_observation_duration_before_reset_) { - MS_DEBUG_TAG(bwe, "Too big observation duration, resetting stats"); - MS_DEBUG_TAG(bwe, "Current estimate bw: %" PRIi64 ", inherent_loss: %f", current_estimate_.loss_limited_bandwidth.bps(), current_estimate_.inherent_loss); - Reset(); - } - - // Too small to be meaningful. if (observation_duration <= TimeDelta::Zero() || (observation_duration < config_->observation_duration_lower_bound && @@ -1043,21 +1038,30 @@ bool LossBasedBweV2::PushBackObservation( } last_send_time_most_recent_observation_ = last_send_time; + DataRate sending_rate = GetSendingRate(partial_observation_.size / observation_duration); Observation observation; observation.num_packets = partial_observation_.num_packets; observation.num_lost_packets = partial_observation_.num_lost_packets; observation.num_received_packets = observation.num_packets - observation.num_lost_packets; - observation.sending_rate = - GetSendingRate(partial_observation_.size / observation_duration); + observation.sending_rate = sending_rate; observation.id = num_observations_++; observations_[observation.id % config_->observation_window_size] = observation; partial_observation_ = PartialObservation(); - CalculateInstantUpperBound(); + CalculateInstantUpperBound(sending_rate); + + // MS_NOTE Here we reset loss estimator if there was not traffic in + // max_observation_duration_before_reset_, otherwise, we will stuck + // at low bitrate. + if (observation_duration > max_observation_duration_before_reset_) { + MS_DEBUG_TAG(bwe, "Too big observation duration, resetting stats"); + MS_DEBUG_TAG(bwe, "Current estimate bw: %" PRIi64 ", inherent_loss: %f", current_estimate_.loss_limited_bandwidth.bps(), current_estimate_.inherent_loss); + Reset(); + } return true; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index ba67ac649a..80c82453b8 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -135,7 +135,7 @@ class LossBasedBweV2 { double GetObjective(const ChannelParameters& channel_parameters) const; DataRate GetSendingRate(DataRate instantaneous_sending_rate) const; DataRate GetInstantUpperBound() const; - void CalculateInstantUpperBound(); + void CalculateInstantUpperBound(DataRate instantaneous_sending_rate); void CalculateTemporalWeights(); void NewtonsMethodUpdate(ChannelParameters& channel_parameters) const; diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index 903750a21d..ed01b708c2 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -10,7 +10,7 @@ static std::once_flag globalInitOnce; static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2/"; + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/"; /* Static methods. */ From e54567512a76fe6b072c62dc279cc96149fbe6ce Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 2 Dec 2022 14:24:52 +0200 Subject: [PATCH 22/70] Update default libwebrtc fieldTrial string. --- node/src/Worker.ts | 2 +- rust/src/worker.rs | 2 +- worker/include/Settings.hpp | 2 +- worker/src/DepLibWebRTC.cpp | 16 ++++++++++++---- 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 74eec53483..fcbc13bc93 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -70,7 +70,7 @@ export type WorkerSettings = * * NOTE: For advanced users only. An invalid value will make the worker crash. * Default value is - * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/". + * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". */ libwebrtcFieldTrials?: string; diff --git a/rust/src/worker.rs b/rust/src/worker.rs index c99dac5fb9..df834aeff0 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -186,7 +186,7 @@ pub struct WorkerSettings { /// /// NOTE: For advanced users only. An invalid value will make the worker crash. /// Default value is - /// "WebRTC-Bwe-AlrLimitedBackoff/Enabled/". + /// "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". #[doc(hidden)] pub libwebrtc_field_trials: Option, /// Function that will be called under worker thread before worker starts, can be used for diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index bd3343546d..f029a7d365 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -38,7 +38,7 @@ class Settings uint16_t rtcMaxPort{ 59999u }; std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; - std::string libwebrtcFieldTrials{ "WebRTC-Bwe-AlrLimitedBackoff/Enabled/" }; + std::string libwebrtcFieldTrials{ "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/" }; }; public: diff --git a/worker/src/DepLibWebRTC.cpp b/worker/src/DepLibWebRTC.cpp index ed01b708c2..9155847994 100644 --- a/worker/src/DepLibWebRTC.cpp +++ b/worker/src/DepLibWebRTC.cpp @@ -3,14 +3,13 @@ #include "DepLibWebRTC.hpp" #include "Logger.hpp" +#include "Settings.hpp" #include "system_wrappers/source/field_trial.h" // webrtc::field_trial #include /* Static. */ static std::once_flag globalInitOnce; -static constexpr char FieldTrials[] = - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/"; /* Static methods. */ @@ -18,10 +17,19 @@ void DepLibWebRTC::ClassInit() { MS_TRACE(); - std::call_once(globalInitOnce, [] { webrtc::field_trial::InitFieldTrialsFromString(FieldTrials); }); + MS_DEBUG_TAG( + info, "libwebrtc field trials: \"%s\"", Settings::configuration.libwebrtcFieldTrials.c_str()); + + std::call_once( + globalInitOnce, + [] + { + webrtc::field_trial::InitFieldTrialsFromString( + Settings::configuration.libwebrtcFieldTrials.c_str()); + }); } void DepLibWebRTC::ClassDestroy() { MS_TRACE(); -} +} \ No newline at end of file From c5bfc177cd746f36e3b5b4a74532cbaf8e6b07f7 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 2 Dec 2022 14:27:06 +0200 Subject: [PATCH 23/70] format --- worker/include/Settings.hpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index f029a7d365..61ec65eb4c 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -38,7 +38,9 @@ class Settings uint16_t rtcMaxPort{ 59999u }; std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; - std::string libwebrtcFieldTrials{ "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/" }; + std::string libwebrtcFieldTrials{ + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/" + }; }; public: From b9a11610c7703f8ddf94058c8d1dbc07962f9487 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 2 Dec 2022 14:35:11 +0200 Subject: [PATCH 24/70] Fix testing change. --- .../modules/bitrate_controller/loss_based_bwe_v2.cc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 421bd42f46..6284e334f6 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -965,11 +965,10 @@ bool LossBasedBweV2::TrendlineEsimateAllowBitrateIncrease() const { } for (const auto& detector_state : delay_detector_states_) { -/* if (detector_state == BandwidthUsage::kBwOverusing || + if (detector_state == BandwidthUsage::kBwOverusing || detector_state == BandwidthUsage::kBwUnderusing) { return false; - }*/ - if (detector_state == BandwidthUsage::kBwOverusing) return false; + } } return true; } From 0d9986393b514221199a673572000fd36668598d Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 2 Dec 2022 19:36:25 +0200 Subject: [PATCH 25/70] `Backport changes from aimd rate control, plus minor fixes. --- .../bitrate_controller/loss_based_bwe_v2.cc | 1 + .../goog_cc/trendline_estimator.cc | 22 +- .../aimd_rate_control.cc | 188 +++++++++--------- .../aimd_rate_control.h | 33 ++- 4 files changed, 131 insertions(+), 113 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 6284e334f6..ccf82fe13a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -449,6 +449,7 @@ absl::optional LossBasedBweV2::CreateConfig( std::string candidate_factors_str; MS_DEBUG_TAG(bwe, "Loss V2 settings: "); + MS_DEBUG_TAG(bwe, "Enabled: %d ", enabled.Get()); MS_DEBUG_TAG(bwe, "bandwidth_rampup_upper_bound_factor: %f ", config->bandwidth_rampup_upper_bound_factor); MS_DEBUG_TAG(bwe, "rampup_acceleration_max_factor: %f ", config->rampup_acceleration_max_factor); MS_DEBUG_TAG(bwe, "rampup_acceleration_maxout_time: %" PRIi64 "", config->rampup_acceleration_maxout_time.ms()); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 8d7655218d..6fbbda895d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -123,6 +123,9 @@ TrendlineEstimatorSettings::TrendlineEstimatorSettings( MS_WARN_TAG(bwe, "window size must be between 10 and 200 packets"); window_size = kDefaultTrendlineWindowSize; } + MS_DEBUG_DEV( + "using Trendline filter for delay change estimation with window size: %zu", + window_size); if (enable_cap) { if (beginning_packets < 1 || end_packets < 1 || beginning_packets > window_size || end_packets > window_size) { @@ -177,9 +180,6 @@ TrendlineEstimator::TrendlineEstimator( hypothesis_(BandwidthUsage::kBwNormal), hypothesis_predicted_(BandwidthUsage::kBwNormal), network_state_predictor_(network_state_predictor) { - MS_DEBUG_DEV( - "using Trendline filter for delay change estimation with window size: %zu", - window_size_); } TrendlineEstimator::~TrendlineEstimator() {} @@ -267,6 +267,9 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { hypothesis_ = BandwidthUsage::kBwNormal; return; } + + BandwidthUsage prev_hypothesis = hypothesis_; + const double modified_trend = std::min(num_of_deltas_, kMinNumDeltas) * trend * threshold_gain_; prev_modified_trend_ = modified_trend; @@ -287,27 +290,34 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { if (trend >= prev_trend_) { time_over_using_ = 0; overuse_counter_ = 0; - MS_DEBUG_DEV("hypothesis_: BandwidthUsage::kBwOverusing"); + +/* #if MS_LOG_DEV_LEVEL == 3 for (auto& kv : delay_hist_) { MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f", kv.first, kv.second); } #endif +*/ hypothesis_ = BandwidthUsage::kBwOverusing; + if (hypothesis_ != prev_hypothesis) + MS_DEBUG_DEV("hypothesis_: BandwidthUsage::kBwOverusing"); + } } } else if (modified_trend < -threshold_) { time_over_using_ = -1; overuse_counter_ = 0; hypothesis_ = BandwidthUsage::kBwUnderusing; - MS_DEBUG_DEV("---- BandwidthUsage::kBwUnderusing ---"); + if (hypothesis_ != prev_hypothesis) + MS_DEBUG_DEV("---- BandwidthUsage::kBwUnderusing ---"); } else { time_over_using_ = -1; overuse_counter_ = 0; - MS_DEBUG_DEV("---- BandwidthUsage::kBwNormal ---"); hypothesis_ = BandwidthUsage::kBwNormal; + if (hypothesis_ != prev_hypothesis) + MS_DEBUG_DEV("---- BandwidthUsage::kBwNormal ---"); } prev_trend_ = trend; UpdateThreshold(modified_trend, now_ms); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 3bc3253376..94b29b332b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -41,6 +41,10 @@ bool IsEnabled(const WebRtcKeyValueConfig& field_trials, return field_trials.Lookup(key).find("Enabled") == 0; } +bool IsNotDisabled(const WebRtcKeyValueConfig& field_trials, absl::string_view key) { + return field_trials.Lookup(key).find("Disabled") != 1; +} + double ReadBackoffFactor(const WebRtcKeyValueConfig& key_value_config) { std::string experiment_string = key_value_config.Lookup(kBweBackOffFactorExperiment); @@ -74,7 +78,7 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, current_bitrate_(max_configured_bitrate_), latest_estimated_throughput_(current_bitrate_), link_capacity_(), - rate_control_state_(kRcHold), + rate_control_state_(RateControlState::kRcHold), time_last_bitrate_change_(Timestamp::MinusInfinity()), time_last_bitrate_decrease_(Timestamp::MinusInfinity()), time_first_throughput_estimate_(Timestamp::MinusInfinity()), @@ -89,15 +93,16 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, no_bitrate_increase_in_alr_( IsEnabled(*key_value_config, "WebRTC-DontIncreaseDelayBasedBweInAlr")), - smoothing_experiment_(false), estimate_bounded_backoff_( - IsEnabled(*key_value_config, "WebRTC-Bwe-EstimateBoundedBackoff")), - estimate_bounded_increase_( - IsEnabled(*key_value_config, "WebRTC-Bwe-EstimateBoundedIncrease")), + IsNotDisabled(*key_value_config, + "WebRTC-Bwe-EstimateBoundedBackoff")), initial_backoff_interval_("initial_backoff_interval"), - low_throughput_threshold_("low_throughput", DataRate::Zero()), - capacity_deviation_ratio_threshold_("cap_thr", 0.2), - capacity_limit_deviation_factor_("cap_lim", 1) { + link_capacity_fix_("link_capacity_fix") { + ParseFieldTrial( + {&disable_estimate_bounded_increase_, &estimate_bounded_increase_ratio_, + &ignore_throughput_limit_if_network_estimate_, + &ignore_network_estimate_decrease_, &increase_to_network_estimate_}, + key_value_config->Lookup("WebRTC-Bwe-EstimateBoundedIncrease")); // E.g // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms, // low_throughput:50kbps/ @@ -203,7 +208,7 @@ DataRate AimdRateControl::Update(const RateControlInput* input, } } - current_bitrate_ = ChangeBitrate(current_bitrate_, *input, at_time); + ChangeBitrate(*input, at_time); return current_bitrate_; } @@ -214,7 +219,7 @@ void AimdRateControl::SetInApplicationLimitedRegion(bool in_alr) { void AimdRateControl::SetEstimate(DataRate bitrate, Timestamp at_time) { bitrate_is_initialized_ = true; DataRate prev_bitrate = current_bitrate_; - current_bitrate_ = ClampBitrate(bitrate, bitrate); + current_bitrate_ = ClampBitrate(bitrate); time_last_bitrate_change_ = at_time; if (current_bitrate_ < prev_bitrate) { time_last_bitrate_decrease_ = at_time; @@ -245,23 +250,22 @@ double AimdRateControl::GetNearMaxIncreaseRateBpsPerSecond() const { } TimeDelta AimdRateControl::GetExpectedBandwidthPeriod() const { - const TimeDelta kMinPeriod = - smoothing_experiment_ ? TimeDelta::ms(500) : TimeDelta::seconds(2); + const TimeDelta kMinPeriod = TimeDelta::seconds(2); const TimeDelta kDefaultPeriod = TimeDelta::seconds(3); const TimeDelta kMaxPeriod = TimeDelta::seconds(50); double increase_rate_bps_per_second = GetNearMaxIncreaseRateBpsPerSecond(); if (!last_decrease_) - return smoothing_experiment_ ? kMinPeriod : kDefaultPeriod; + return kDefaultPeriod; double time_to_recover_decrease_seconds = last_decrease_->bps() / increase_rate_bps_per_second; TimeDelta period = TimeDelta::seconds(time_to_recover_decrease_seconds); return period.Clamped(kMinPeriod, kMaxPeriod); } -DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, - const RateControlInput& input, - Timestamp at_time) { +void AimdRateControl::ChangeBitrate(const RateControlInput& input, + Timestamp at_time) { + absl::optional new_bitrate; DataRate estimated_throughput = input.estimated_throughput.value_or(latest_estimated_throughput_); if (input.estimated_throughput) @@ -272,82 +276,90 @@ DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, // we will end up with a valid estimate. if (!bitrate_is_initialized_ && input.bw_state != BandwidthUsage::kBwOverusing) - return current_bitrate_; + return; ChangeState(input, at_time); - + MS_DEBUG_DEV("[estimated_throughput %lld, low_throughput_threshold_ %lld, link_capacity_: %lld]", + estimated_throughput.bps(), + low_throughput_threshold_->bps(), + link_capacity_.has_estimate() ? link_capacity_.estimate().bps() : -1); switch (rate_control_state_) { - case kRcHold: + case RateControlState::kRcHold: break; - case kRcIncrease: + case RateControlState::kRcIncrease: { if (estimated_throughput > link_capacity_.UpperBound()) link_capacity_.Reset(); - // Do not increase the delay based estimate in alr since the estimator - // will not be able to get transport feedback necessary to detect if - // the new estimate is correct. - if (!(send_side_ && in_alr_ && no_bitrate_increase_in_alr_)) { - if (link_capacity_.has_estimate()) { + // We limit the new bitrate based on the troughput to avoid unlimited + // bitrate increases. We allow a bit more lag at very low rates to not too + // easily get stuck if the encoder produces uneven outputs. + DataRate increase_limit = + 1.5 * estimated_throughput + DataRate::KilobitsPerSec(10); + if (ignore_throughput_limit_if_network_estimate_ && network_estimate_ && + network_estimate_->link_capacity_upper.IsFinite()) { + // If we have a Network estimate, we do allow the estimate to increase. + increase_limit = network_estimate_->link_capacity_upper * + estimate_bounded_increase_ratio_.Get(); + } else if (send_side_ && in_alr_ && no_bitrate_increase_in_alr_) { + // Do not increase the delay based estimate in alr since the estimator + // will not be able to get transport feedback necessary to detect if + // the new estimate is correct. + // If we have previously increased above the limit (for instance due to + // probing), we don't allow further changes. + increase_limit = current_bitrate_; + } + + if (current_bitrate_ < increase_limit) { + DataRate increased_bitrate = DataRate::MinusInfinity(); + if (increase_to_network_estimate_ && network_estimate_ && + network_estimate_->link_capacity_upper.IsFinite()) { + increased_bitrate = increase_limit; + } else if (link_capacity_.has_estimate()) { // The link_capacity estimate is reset if the measured throughput // is too far from the estimate. We can therefore assume that our // target rate is reasonably close to link capacity and use additive // increase. DataRate additive_increase = AdditiveRateIncrease(at_time, time_last_bitrate_change_); - new_bitrate += additive_increase; + increased_bitrate = current_bitrate_ + additive_increase; } else { // If we don't have an estimate of the link capacity, use faster ramp // up to discover the capacity. DataRate multiplicative_increase = MultiplicativeRateIncrease( - at_time, time_last_bitrate_change_, new_bitrate); - new_bitrate += multiplicative_increase; + at_time, time_last_bitrate_change_, current_bitrate_); + increased_bitrate = current_bitrate_ + multiplicative_increase; } + new_bitrate = std::min(increased_bitrate, increase_limit); } - time_last_bitrate_change_ = at_time; break; + } - case kRcDecrease: - // TODO(srte): Remove when |estimate_bounded_backoff_| has been validated. - if (network_estimate_ && capacity_deviation_ratio_threshold_ && - !estimate_bounded_backoff_) { - estimated_throughput = std::max(estimated_throughput, - network_estimate_->link_capacity_lower); - } - 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. - new_bitrate = estimated_throughput * beta_; - if (new_bitrate > current_bitrate_) { - // Avoid increasing the rate when over-using. - if (link_capacity_.has_estimate()) { - new_bitrate = beta_ * link_capacity_.estimate(); - } - } - if (estimate_bounded_backoff_ && network_estimate_) { - new_bitrate = std::max( - new_bitrate, network_estimate_->link_capacity_lower * beta_); - } - } else { - new_bitrate = estimated_throughput; + case RateControlState::kRcDecrease: { + DataRate decreased_bitrate = DataRate::PlusInfinity(); + + // Set bit rate to something slightly lower than the measured throughput + // to get rid of any self-induced delay. + decreased_bitrate = estimated_throughput * beta_; + if (decreased_bitrate > current_bitrate_ && !link_capacity_fix_) { + // TODO(terelius): The link_capacity estimate may be based on old + // throughput measurements. Relying on them may lead to unnecessary + // BWE drops. if (link_capacity_.has_estimate()) { - new_bitrate = std::max(new_bitrate, link_capacity_.estimate()); + decreased_bitrate = beta_ * link_capacity_.estimate(); } - new_bitrate = std::min(new_bitrate, low_throughput_threshold_.Get()); } - new_bitrate = std::min(new_bitrate, current_bitrate_); + // Avoid increasing the rate when over-using. + if (decreased_bitrate < current_bitrate_) { + new_bitrate = decreased_bitrate; + } if (bitrate_is_initialized_ && estimated_throughput < current_bitrate_) { - constexpr double kDegradationFactor = 0.9; - if (smoothing_experiment_ && - new_bitrate < kDegradationFactor * beta_ * current_bitrate_) { - // If bitrate decreases more than a normal back off after overuse, it - // indicates a real network degradation. We do not let such a decrease - // to determine the bandwidth estimation period. - last_decrease_ = absl::nullopt; + if (!new_bitrate.has_value()) { + last_decrease_ = DataRate::Zero(); } else { - last_decrease_ = current_bitrate_ - new_bitrate; + last_decrease_ = current_bitrate_ - *new_bitrate; } } if (estimated_throughput < link_capacity_.LowerBound()) { @@ -359,38 +371,34 @@ DataRate AimdRateControl::ChangeBitrate(DataRate new_bitrate, bitrate_is_initialized_ = true; link_capacity_.OnOveruseDetected(estimated_throughput); // Stay on hold until the pipes are cleared. - rate_control_state_ = kRcHold; + rate_control_state_ = RateControlState::kRcHold; time_last_bitrate_change_ = at_time; time_last_bitrate_decrease_ = at_time; break; - + } default: MS_THROW_ERROR("unknown rate control state"); } - return ClampBitrate(new_bitrate, estimated_throughput); + + current_bitrate_ = ClampBitrate(new_bitrate.value_or(current_bitrate_)); } -DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate, - DataRate estimated_throughput) const { - // Allow the estimate to increase as long as alr is not detected to ensure - // that there is no BWE values that can make the estimate stuck at a too - // low bitrate. If an encoder can not produce the bitrate necessary to - // fully use the capacity, alr will sooner or later trigger. - if (!(send_side_ && no_bitrate_increase_in_alr_)) { - // Don't change the bit rate if the send side is too far off. - // We allow a bit more lag at very low rates to not too easily get stuck if - // the encoder produces uneven outputs. - const DataRate max_bitrate = - 1.5 * estimated_throughput + DataRate::kbps(10); - if (new_bitrate > current_bitrate_ && new_bitrate > max_bitrate) { - new_bitrate = std::max(current_bitrate_, max_bitrate); +DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const { + if (!disable_estimate_bounded_increase_ && network_estimate_ && + network_estimate_->link_capacity_upper.IsFinite()) { + DataRate upper_bound = network_estimate_->link_capacity_upper * + estimate_bounded_increase_ratio_.Get(); + if (ignore_network_estimate_decrease_) { + upper_bound = std::max(upper_bound, current_bitrate_); } + new_bitrate = std::min(upper_bound, new_bitrate); } - - if (network_estimate_ && - (estimate_bounded_increase_ || capacity_limit_deviation_factor_)) { - DataRate upper_bound = network_estimate_->link_capacity_upper; - new_bitrate = std::min(new_bitrate, upper_bound); + if (estimate_bounded_backoff_ && network_estimate_ && + network_estimate_->link_capacity_lower.IsFinite() && + new_bitrate < current_bitrate_) { + new_bitrate = std::min( + current_bitrate_, + std::max(new_bitrate, network_estimate_->link_capacity_lower * beta_)); } new_bitrate = std::max(new_bitrate, min_configured_bitrate_); return new_bitrate; @@ -422,18 +430,18 @@ void AimdRateControl::ChangeState(const RateControlInput& input, Timestamp at_time) { switch (input.bw_state) { case BandwidthUsage::kBwNormal: - if (rate_control_state_ == kRcHold) { + if (rate_control_state_ == RateControlState::kRcHold) { time_last_bitrate_change_ = at_time; - rate_control_state_ = kRcIncrease; + rate_control_state_ = RateControlState::kRcIncrease; } break; case BandwidthUsage::kBwOverusing: - if (rate_control_state_ != kRcDecrease) { - rate_control_state_ = kRcDecrease; + if (rate_control_state_ != RateControlState::kRcDecrease) { + rate_control_state_ = RateControlState::kRcDecrease; } break; case BandwidthUsage::kBwUnderusing: - rate_control_state_ = kRcHold; + rate_control_state_ = RateControlState::kRcHold; break; default: MS_THROW_ERROR("unknown input.bw_state"); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h index cefea2f2a5..6e4ead24a4 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -65,6 +65,8 @@ class AimdRateControl { TimeDelta GetExpectedBandwidthPeriod() const; private: + enum class RateControlState { kRcHold, kRcIncrease, kRcDecrease }; + friend class GoogCcStatePrinter; // Update the target bitrate based on, among other things, the current rate // control state, the current target bitrate and the estimated throughput. @@ -73,14 +75,9 @@ class AimdRateControl { // in the "decrease" state the bitrate will be decreased to slightly below the // current throughput. When in the "hold" state the bitrate will be kept // constant to allow built up queues to drain. - DataRate ChangeBitrate(DataRate current_bitrate, - const RateControlInput& input, - Timestamp at_time); - // Clamps new_bitrate to within the configured min bitrate and a linear - // function of the throughput, so that the new bitrate can't grow too - // large compared to the bitrate actually being received by the other end. - DataRate ClampBitrate(DataRate new_bitrate, - DataRate estimated_throughput) const; + void ChangeBitrate(const RateControlInput& input, Timestamp at_time); + + DataRate ClampBitrate(DataRate new_bitrate) const; DataRate MultiplicativeRateIncrease(Timestamp at_time, Timestamp last_ms, DataRate current_bitrate) const; @@ -107,20 +104,22 @@ class AimdRateControl { // Allow the delay based estimate to only increase as long as application // limited region (alr) is not detected. const bool no_bitrate_increase_in_alr_; - const bool smoothing_experiment_; // Use estimated link capacity lower bound if it is higher than the // acknowledged rate when backing off due to overuse. const bool estimate_bounded_backoff_; - // Use estimated link capacity upper bound as upper limit for increasing - // bitrate over the acknowledged rate. - const bool estimate_bounded_increase_; + // If false, uses estimated link capacity upper bound * + // `estimate_bounded_increase_ratio_` as upper limit for the estimate. + FieldTrialFlag disable_estimate_bounded_increase_{"Disabled"}; + FieldTrialParameter estimate_bounded_increase_ratio_{"ratio", 1.0}; + FieldTrialParameter ignore_throughput_limit_if_network_estimate_{ + "ignore_acked", false}; + FieldTrialParameter increase_to_network_estimate_{"immediate_incr", + false}; + FieldTrialParameter ignore_network_estimate_decrease_{"ignore_decr", + false}; absl::optional last_decrease_; FieldTrialOptional initial_backoff_interval_; - FieldTrialParameter low_throughput_threshold_; - // Deprecated, enable |estimate_bounded_backoff_| instead. - FieldTrialOptional capacity_deviation_ratio_threshold_; - // Deprecated, enable |estimate_bounded_increase_| instead. - FieldTrialOptional capacity_limit_deviation_factor_; + FieldTrialFlag link_capacity_fix_; }; } // namespace webrtc From 619361a11d54598762794fa8e714684a4bf12bf5 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 2 Dec 2022 19:38:38 +0200 Subject: [PATCH 26/70] `Backport changes from aimd rate control, plus minor fixes. --- .../remote_bitrate_estimator/aimd_rate_control.cc | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 94b29b332b..4fab5cd72e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -104,18 +104,14 @@ AimdRateControl::AimdRateControl(const WebRtcKeyValueConfig* key_value_config, &ignore_network_estimate_decrease_, &increase_to_network_estimate_}, key_value_config->Lookup("WebRTC-Bwe-EstimateBoundedIncrease")); // E.g - // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms, - // low_throughput:50kbps/ - ParseFieldTrial({&initial_backoff_interval_, &low_throughput_threshold_}, + // WebRTC-BweAimdRateControlConfig/initial_backoff_interval:100ms/ + ParseFieldTrial({&initial_backoff_interval_, &link_capacity_fix_}, key_value_config->Lookup("WebRTC-BweAimdRateControlConfig")); if (initial_backoff_interval_) { MS_DEBUG_TAG(bwe, "Using aimd rate control with initial back-off interval: %s", ToString(*initial_backoff_interval_).c_str()); } MS_DEBUG_TAG(bwe, "Using aimd rate control with back off factor: %f ", beta_); - ParseFieldTrial( - {&capacity_deviation_ratio_threshold_, &capacity_limit_deviation_factor_}, - key_value_config->Lookup("WebRTC-Bwe-AimdRateControl-NetworkState")); } AimdRateControl::~AimdRateControl() {} @@ -295,7 +291,7 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input, // bitrate increases. We allow a bit more lag at very low rates to not too // easily get stuck if the encoder produces uneven outputs. DataRate increase_limit = - 1.5 * estimated_throughput + DataRate::KilobitsPerSec(10); + 1.5 * estimated_throughput + DataRate::kbps(10); if (ignore_throughput_limit_if_network_estimate_ && network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { // If we have a Network estimate, we do allow the estimate to increase. From 252d5685bd405335dc4adb19084a258432a39b67 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 5 Dec 2022 17:20:19 +0200 Subject: [PATCH 27/70] Fix log --- .../modules/remote_bitrate_estimator/aimd_rate_control.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 4fab5cd72e..dd401846d3 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -275,9 +275,8 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input, return; ChangeState(input, at_time); - MS_DEBUG_DEV("[estimated_throughput %lld, low_throughput_threshold_ %lld, link_capacity_: %lld]", + MS_DEBUG_DEV("[estimated_throughput %lld, link_capacity_: %lld]", estimated_throughput.bps(), - low_throughput_threshold_->bps(), link_capacity_.has_estimate() ? link_capacity_.estimate().bps() : -1); switch (rate_control_state_) { case RateControlState::kRcHold: From 0c7eef047d116ebe6a5554e9b83cba0f9180de94 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 5 Dec 2022 21:45:37 +0200 Subject: [PATCH 28/70] Backport latest changes from libwebrtc. --- worker/deps/libwebrtc/libwebrtc.gyp | 2 - .../bitrate_controller/loss_based_bwe_v2.cc | 200 +++++++++++------ .../bitrate_controller/loss_based_bwe_v2.h | 41 +++- .../send_side_bandwidth_estimation.cc | 24 ++- .../send_side_bandwidth_estimation.h | 7 +- .../goog_cc/bitrate_estimator.cc | 40 ++-- .../goog_cc/bitrate_estimator.h | 7 +- .../congestion_window_pushback_controller.cc | 9 - .../congestion_window_pushback_controller.h | 1 - .../goog_cc/median_slope_estimator.cc | 88 -------- .../goog_cc/median_slope_estimator.h | 72 ------- .../goog_cc/probe_controller.cc | 204 ++++++++++-------- .../goog_cc/probe_controller.h | 34 +-- worker/deps/libwebrtc/meson.build | 1 - 14 files changed, 360 insertions(+), 370 deletions(-) delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc delete mode 100644 worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h diff --git a/worker/deps/libwebrtc/libwebrtc.gyp b/worker/deps/libwebrtc/libwebrtc.gyp index bc786cf165..eb84186549 100644 --- a/worker/deps/libwebrtc/libwebrtc.gyp +++ b/worker/deps/libwebrtc/libwebrtc.gyp @@ -52,7 +52,6 @@ 'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc', 'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc', - 'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc', @@ -110,7 +109,6 @@ 'libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h', 'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.h', 'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.h', - 'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h', 'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h', 'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h', 'libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h', diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index ccf82fe13a..a0a40562a2 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -44,6 +44,10 @@ bool IsValid(DataRate datarate) { return datarate.IsFinite(); } +bool IsValid(absl::optional datarate) { + return datarate.has_value() && IsValid(datarate.value()); +} + bool IsValid(Timestamp timestamp) { return timestamp.IsFinite(); } @@ -148,8 +152,9 @@ bool LossBasedBweV2::IsReady() const { num_observations_ > 0; } -DataRate LossBasedBweV2::GetBandwidthEstimate( - DataRate delay_based_limit) const { +LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { + Result result; + result.state = current_state_; if (!IsReady()) { if (!IsEnabled()) { MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); @@ -161,8 +166,10 @@ DataRate LossBasedBweV2::GetBandwidthEstimate( MS_WARN_TAG(bwe, "The estimator must receive enough loss statistics before it can be used."); } } - return IsValid(delay_based_limit) ? delay_based_limit - : DataRate::PlusInfinity(); + result.bandwidth_estimate = IsValid(delay_based_estimate_) + ? delay_based_estimate_ + : DataRate::PlusInfinity(); + return result; } auto instant_limit = GetInstantUpperBound(); @@ -171,13 +178,15 @@ DataRate LossBasedBweV2::GetBandwidthEstimate( current_estimate_.loss_limited_bandwidth.bps(), delay_based_limit.IsFinite() ? delay_based_limit.bps() : 0, instant_limit.IsFinite() ? instant_limit.bps() : 0); - if (delay_based_limit.IsFinite()) { - return std::min({current_estimate_.loss_limited_bandwidth, - instant_limit, delay_based_limit}); - } else { - return std::min(current_estimate_.loss_limited_bandwidth, - GetInstantUpperBound()); - } + if (IsValid(delay_based_estimate_)) { + result.bandwidth_estimate = + std::min({current_estimate_.loss_limited_bandwidth, + instant_limit, delay_based_estimate_}); + } else { + result.bandwidth_estimate = std::min( + current_estimate_.loss_limited_bandwidth, instant_limit); + } + return result; } void LossBasedBweV2::SetAcknowledgedBitrate(DataRate acknowledged_bitrate) { @@ -196,18 +205,37 @@ void LossBasedBweV2::SetBandwidthEstimate(DataRate bandwidth_estimate) { } } -void LossBasedBweV2::SetMinBitrate(DataRate min_bitrate) { +void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate, + DataRate max_bitrate) { if (IsValid(min_bitrate)) { min_bitrate_ = min_bitrate; } else { MS_WARN_TAG(bwe, "The min bitrate must be finite: %" PRIi64 "", min_bitrate.bps()); + } + + if (IsValid(max_bitrate)) { + max_bitrate_ = max_bitrate; + } else { + MS_WARN_TAG(bwe, "The max bitrate must be finite: %" PRIi64 "", max_bitrate.bps()); + } +} + +void LossBasedBweV2::SetProbeBitrate(absl::optional probe_bitrate) { + if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) { + if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) { + probe_bitrate_ = probe_bitrate.value(); + } } } void LossBasedBweV2::UpdateBandwidthEstimate( std::vector packet_results, DataRate delay_based_estimate, - BandwidthUsage delay_detector_state) { + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity) { + delay_based_estimate_ = delay_based_estimate; + upper_link_capacity_ = upper_link_capacity; if (!IsEnabled()) { MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); return; @@ -228,7 +256,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate( ChannelParameters best_candidate = current_estimate_; double objective_max = std::numeric_limits::lowest(); - for (ChannelParameters candidate : GetCandidates(delay_based_estimate)) { + for (ChannelParameters candidate : GetCandidates()) { NewtonsMethodUpdate(candidate); const double candidate_objective = GetObjective(candidate); @@ -252,34 +280,74 @@ void LossBasedBweV2::UpdateBandwidthEstimate( current_estimate_.loss_limited_bandwidth; } - // Bound the estimate increase if: - // 1. The estimate is limited due to loss, and - // 2. The estimate has been increased for less than `delayed_increase_window` - // ago, and - // 3. The best candidate is greater than bandwidth_limit_in_current_window. - if (limited_due_to_loss_candidate_ && - recovering_after_loss_timestamp_.IsFinite() && - recovering_after_loss_timestamp_ + config_->delayed_increase_window > - last_send_time_most_recent_observation_ && - best_candidate.loss_limited_bandwidth > - bandwidth_limit_in_current_window_) { - best_candidate.loss_limited_bandwidth = bandwidth_limit_in_current_window_; - } - limited_due_to_loss_candidate_ = - delay_based_estimate.IsFinite() && - best_candidate.loss_limited_bandwidth < delay_based_estimate; - - if (limited_due_to_loss_candidate_ && + if (IsBandwidthLimitedDueToLoss()) { + // Bound the estimate increase if: + // 1. The estimate has been increased for less than + // `delayed_increase_window` ago, and + // 2. The best candidate is greater than bandwidth_limit_in_current_window. + if (recovering_after_loss_timestamp_.IsFinite() && + recovering_after_loss_timestamp_ + config_->delayed_increase_window > + last_send_time_most_recent_observation_ && + best_candidate.loss_limited_bandwidth > + bandwidth_limit_in_current_window_) { + best_candidate.loss_limited_bandwidth = + bandwidth_limit_in_current_window_; + } + + bool increasing_when_loss_limited = + IsEstimateIncreasingWhenLossLimited(best_candidate); + // Bound the best candidate by the acked bitrate unless there is a recent + // probe result. + if (increasing_when_loss_limited && !IsValid(probe_bitrate_) && + IsValid(acknowledged_bitrate_)) { + best_candidate.loss_limited_bandwidth = + IsValid(best_candidate.loss_limited_bandwidth) + ? std::min(best_candidate.loss_limited_bandwidth, + config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_)) + : config_->bandwidth_rampup_upper_bound_factor * + (*acknowledged_bitrate_); + } + + // Use probe bitrate as the estimate as probe bitrate is trusted to be + // correct. After being used, the probe bitrate is reset. + if (config_->probe_integration_enabled && IsValid(probe_bitrate_)) { + best_candidate.loss_limited_bandwidth = + std::min(probe_bitrate_, best_candidate.loss_limited_bandwidth); + probe_bitrate_ = DataRate::MinusInfinity(); + } + } + + if (IsEstimateIncreasingWhenLossLimited(best_candidate) && + best_candidate.loss_limited_bandwidth < delay_based_estimate) { + current_state_ = LossBasedState::kIncreasing; + } else if (best_candidate.loss_limited_bandwidth < delay_based_estimate_) { + current_state_ = LossBasedState::kDecreasing; + } else if (best_candidate.loss_limited_bandwidth >= delay_based_estimate_) { + current_state_ = LossBasedState::kDelayBasedEstimate; + } + current_estimate_ = best_candidate; + + if (IsBandwidthLimitedDueToLoss() && (recovering_after_loss_timestamp_.IsInfinite() || recovering_after_loss_timestamp_ + config_->delayed_increase_window < last_send_time_most_recent_observation_)) { - bandwidth_limit_in_current_window_ = std::max( - kCongestionControllerMinBitrate, - best_candidate.loss_limited_bandwidth * config_->max_increase_factor); + bandwidth_limit_in_current_window_ = + std::max(kCongestionControllerMinBitrate, + current_estimate_.loss_limited_bandwidth * + config_->max_increase_factor); recovering_after_loss_timestamp_ = last_send_time_most_recent_observation_; } +} - current_estimate_ = best_candidate; +bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited( + const ChannelParameters& best_candidate) { + return (current_estimate_.loss_limited_bandwidth < + best_candidate.loss_limited_bandwidth || + (current_estimate_.loss_limited_bandwidth == + best_candidate.loss_limited_bandwidth && + current_state_ == LossBasedState::kIncreasing)) && + IsBandwidthLimitedDueToLoss(); } // Returns a `LossBasedBweV2::Config` iff the `key_value_config` specifies a @@ -350,6 +418,10 @@ absl::optional LossBasedBweV2::CreateConfig( "BandwidthCapAtHighLossRate", DataRate::kbps(500.0)); FieldTrialParameter slope_of_bwe_high_loss_func( "SlopeOfBweHighLossFunc", 1000); + FieldTrialParameter probe_integration_enabled("ProbeIntegrationEnabled", + false); + FieldTrialParameter bound_by_upper_link_capacity_when_loss_limited( + "BoundByUpperLinkCapacityWhenLossLimited", true); if (key_value_config) { ParseFieldTrial({&enabled, &bandwidth_rampup_upper_bound_factor, @@ -382,9 +454,11 @@ absl::optional LossBasedBweV2::CreateConfig( &delayed_increase_window, &use_acked_bitrate_only_when_overusing, ¬_increase_if_inherent_loss_less_than_average_loss, + &probe_integration_enabled, &high_loss_rate_threshold, &bandwidth_cap_at_high_loss_rate, - &slope_of_bwe_high_loss_func}, + &slope_of_bwe_high_loss_func, + &bound_by_upper_link_capacity_when_loss_limited}, key_value_config->Lookup("WebRTC-Bwe-LossBasedBweV2")); } @@ -444,6 +518,9 @@ absl::optional LossBasedBweV2::CreateConfig( config->bandwidth_cap_at_high_loss_rate = bandwidth_cap_at_high_loss_rate.Get(); config->slope_of_bwe_high_loss_func = slope_of_bwe_high_loss_func.Get(); + config->probe_integration_enabled = probe_integration_enabled.Get(); + config->bound_by_upper_link_capacity_when_loss_limited = + bound_by_upper_link_capacity_when_loss_limited.Get(); std::string candidate_factors_str; @@ -677,33 +754,25 @@ double LossBasedBweV2::GetAverageReportedLossRatio() const { return num_lost_packets / num_packets; } -DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound( - DataRate delay_based_estimate) const { - DataRate candidate_bandwidth_upper_bound = DataRate::PlusInfinity(); - if (limited_due_to_loss_candidate_) { +DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound() const { + DataRate candidate_bandwidth_upper_bound = max_bitrate_; + if (IsBandwidthLimitedDueToLoss() && + IsValid(bandwidth_limit_in_current_window_)) { candidate_bandwidth_upper_bound = bandwidth_limit_in_current_window_; } if (config_->trendline_integration_enabled) { candidate_bandwidth_upper_bound = std::min(GetInstantUpperBound(), candidate_bandwidth_upper_bound); - if (IsValid(delay_based_estimate)) { + if (IsValid(delay_based_estimate_)) { candidate_bandwidth_upper_bound = - std::min(delay_based_estimate, candidate_bandwidth_upper_bound); + std::min(delay_based_estimate_, candidate_bandwidth_upper_bound); } } if (!acknowledged_bitrate_.has_value()) return candidate_bandwidth_upper_bound; - candidate_bandwidth_upper_bound = - IsValid(candidate_bandwidth_upper_bound) - ? std::min(candidate_bandwidth_upper_bound, - config_->bandwidth_rampup_upper_bound_factor * - (*acknowledged_bitrate_)) - : config_->bandwidth_rampup_upper_bound_factor * - (*acknowledged_bitrate_); - if (config_->rampup_acceleration_max_factor > 0.0) { const TimeDelta time_since_bandwidth_reduced = std::min( config_->rampup_acceleration_maxout_time, @@ -719,8 +788,8 @@ DataRate LossBasedBweV2::GetCandidateBandwidthUpperBound( return candidate_bandwidth_upper_bound; } -std::vector LossBasedBweV2::GetCandidates( - DataRate delay_based_estimate) const { +std::vector LossBasedBweV2::GetCandidates() + const { std::vector bandwidths; bool can_increase_bitrate = TrendlineEsimateAllowBitrateIncrease(); for (double candidate_factor : config_->candidate_factors) { @@ -738,16 +807,16 @@ std::vector LossBasedBweV2::GetCandidates( config_->bandwidth_backoff_lower_bound_factor); } - if (IsValid(delay_based_estimate) && + if (IsValid(delay_based_estimate_) && config_->append_delay_based_estimate_candidate) { if (can_increase_bitrate && - delay_based_estimate > current_estimate_.loss_limited_bandwidth) { - bandwidths.push_back(delay_based_estimate); + delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) { + bandwidths.push_back(delay_based_estimate_); } } const DataRate candidate_bandwidth_upper_bound = - GetCandidateBandwidthUpperBound(delay_based_estimate); + GetCandidateBandwidthUpperBound(); std::vector candidates; candidates.resize(bandwidths.size()); @@ -895,11 +964,11 @@ DataRate LossBasedBweV2::GetSendingRate( } DataRate LossBasedBweV2::GetInstantUpperBound() const { - return cached_instant_upper_bound_.value_or(DataRate::PlusInfinity()); + return cached_instant_upper_bound_.value_or(max_bitrate_); } void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { - DataRate instant_limit = DataRate::PlusInfinity(); + DataRate instant_limit = max_bitrate_; const double average_reported_loss_ratio = GetAverageReportedLossRatio(); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { @@ -934,7 +1003,13 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { } } - cached_instant_upper_bound_ = instant_limit; + if (IsBandwidthLimitedDueToLoss()) { + if (IsValid(upper_link_capacity_) && + config_->bound_by_upper_link_capacity_when_loss_limited) { + instant_limit = std::min(instant_limit, upper_link_capacity_); + } + } + cached_instant_upper_bound_ = instant_limit; } void LossBasedBweV2::CalculateTemporalWeights() { @@ -1022,7 +1097,6 @@ bool LossBasedBweV2::PushBackObservation( const Timestamp last_send_time = packet_results_summary.last_send_time; const TimeDelta observation_duration = last_send_time - last_send_time_most_recent_observation_; - // Too small to be meaningful. if (observation_duration <= TimeDelta::Zero() || (observation_duration < config_->observation_duration_lower_bound && @@ -1065,4 +1139,8 @@ bool LossBasedBweV2::PushBackObservation( return true; } +bool LossBasedBweV2::IsBandwidthLimitedDueToLoss() const { + return current_state_ != LossBasedState::kDelayBasedEstimate; +} + } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 80c82453b8..641204db16 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -26,8 +26,21 @@ namespace webrtc { +// State of the loss based estimate, which can be either increasing/decreasing +// when network is loss limited, or equal to the delay based estimate. +enum class LossBasedState { + kIncreasing = 0, + kDecreasing = 1, + kDelayBasedEstimate = 2 +}; + class LossBasedBweV2 { public: + struct Result { + ~Result() = default; + DataRate bandwidth_estimate = DataRate::Zero(); + LossBasedState state = LossBasedState::kDelayBasedEstimate; + }; // Creates a disabled `LossBasedBweV2` if the // `key_value_config` is not valid. explicit LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config); @@ -43,15 +56,17 @@ class LossBasedBweV2 { bool IsReady() const; // Returns `DataRate::PlusInfinity` if no BWE can be calculated. - DataRate GetBandwidthEstimate(DataRate delay_based_limit) const; + Result GetLossBasedResult() const; void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); void SetBandwidthEstimate(DataRate bandwidth_estimate); - void SetMinBitrate(DataRate min_bitrate); + void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); void UpdateBandwidthEstimate( std::vector packet_results, DataRate delay_based_estimate, - BandwidthUsage delay_detector_state); + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity); private: struct ChannelParameters { @@ -94,6 +109,8 @@ class LossBasedBweV2 { double high_loss_rate_threshold = 1.0; DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity(); double slope_of_bwe_high_loss_func = 1000.0; + bool probe_integration_enabled = false; + bool bound_by_upper_link_capacity_when_loss_limited = false; }; struct Derivatives { @@ -123,9 +140,8 @@ class LossBasedBweV2 { // Returns `0.0` if not enough loss statistics have been received. double GetAverageReportedLossRatio() const; - std::vector GetCandidates( - DataRate delay_based_estimate) const; - DataRate GetCandidateBandwidthUpperBound(DataRate delay_based_estimate) const; + std::vector GetCandidates() const; + DataRate GetCandidateBandwidthUpperBound() const; Derivatives GetDerivatives(const ChannelParameters& channel_parameters) const; double GetFeasibleInherentLoss( const ChannelParameters& channel_parameters) const; @@ -154,7 +170,10 @@ class LossBasedBweV2 { const std::vector packet_feedbacks, Timestamp at_time); void UpdateDelayDetector(BandwidthUsage delay_detector_state); - + bool IsEstimateIncreasingWhenLossLimited( + const ChannelParameters& best_candidate); + bool IsBandwidthLimitedDueToLoss() const; + void SetProbeBitrate(absl::optional probe_bitrate); void Reset(); absl::optional acknowledged_bitrate_; @@ -171,10 +190,14 @@ class LossBasedBweV2 { std::deque delay_detector_states_; Timestamp recovering_after_loss_timestamp_ = Timestamp::MinusInfinity(); DataRate bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); - bool limited_due_to_loss_candidate_ = false; - // NOTE: changed min bitrate from 1 to 100, this allows faster recover + LossBasedState current_state_ = LossBasedState::kDelayBasedEstimate; + DataRate probe_bitrate_ = DataRate::PlusInfinity(); + DataRate delay_based_estimate_ = DataRate::PlusInfinity(); + DataRate upper_link_capacity_ = DataRate::PlusInfinity(); + // MS_NOTE: changed min bitrate from 1 to 100, this allows faster recover // from huge drop. DataRate min_bitrate_ = DataRate::kbps(100); + DataRate max_bitrate_ = DataRate::PlusInfinity(); TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); double static constexpr kBwBalanceMultiplicator = 1.3; }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index fb7992b35c..c7cc3f61e4 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -238,7 +238,8 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation( ParseFieldTrial({&disable_receiver_limit_caps_only_}, key_value_config->Lookup("WebRTC-Bwe-ReceiverLimitCapsOnly")); if (LossBasedBandwidthEstimatorV2Enabled()) { - loss_based_bandwidth_estimator_v2_.SetMinBitrate(min_bitrate_configured_); + loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate( + min_bitrate_configured_, max_bitrate_configured_); } } @@ -302,6 +303,8 @@ void SendSideBandwidthEstimation::SetMinMaxBitrate(DataRate min_bitrate, } else { max_bitrate_configured_ = kDefaultMaxBitrate; } + loss_based_bandwidth_estimator_v2_.SetMinMaxBitrate(min_bitrate_configured_, + max_bitrate_configured_); } int SendSideBandwidthEstimation::GetMinBitrate() const { @@ -315,8 +318,8 @@ DataRate SendSideBandwidthEstimation::target_rate() const { return std::max(min_bitrate_configured_, target); } -DataRate SendSideBandwidthEstimation::delay_based_limit() const { - return delay_based_limit_; +LossBasedState SendSideBandwidthEstimation::loss_based_state() const { + return loss_based_state_; } DataRate SendSideBandwidthEstimation::GetEstimatedLinkCapacity() const { @@ -359,14 +362,17 @@ void SendSideBandwidthEstimation::SetAcknowledgedRate( void SendSideBandwidthEstimation::UpdateLossBasedEstimator( const TransportPacketsFeedback& report, - BandwidthUsage delay_detector_state) { + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity) { if (LossBasedBandwidthEstimatorV1Enabled()) { loss_based_bandwidth_estimator_v1_.UpdateLossStatistics( report.packet_feedbacks, report.feedback_time); } if (LossBasedBandwidthEstimatorV2Enabled()) { loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( - report.packet_feedbacks, delay_based_limit_, delay_detector_state); + report.packet_feedbacks, delay_based_limit_, delay_detector_state, + probe_bitrate, upper_link_capacity); UpdateEstimate(report.feedback_time); } } @@ -512,10 +518,10 @@ void SendSideBandwidthEstimation::UpdateEstimate(Timestamp at_time) { } if (LossBasedBandwidthEstimatorV2ReadyForUse()) { - DataRate new_bitrate = - loss_based_bandwidth_estimator_v2_.GetBandwidthEstimate( - delay_based_limit_); - UpdateTargetBitrate(new_bitrate, at_time); + LossBasedBweV2::Result result = + loss_based_bandwidth_estimator_v2_.GetLossBasedResult(); + loss_based_state_ = result.state; + UpdateTargetBitrate(result.bandwidth_estimate, at_time); return; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 00cfd71724..90faa460ea 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -79,7 +79,7 @@ class SendSideBandwidthEstimation { void OnRouteChange(); DataRate target_rate() const; - DataRate delay_based_limit() const; + LossBasedState loss_based_state() const; uint8_t fraction_loss() const { return last_fraction_loss_; } TimeDelta round_trip_time() const { return last_round_trip_time_; } @@ -113,7 +113,9 @@ class SendSideBandwidthEstimation { void SetAcknowledgedRate(absl::optional acknowledged_rate, Timestamp at_time); void UpdateLossBasedEstimator(const TransportPacketsFeedback& report, - BandwidthUsage delay_detector_state); + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, + DataRate upper_link_capacity); private: friend class GoogCcStatePrinter; @@ -194,6 +196,7 @@ class SendSideBandwidthEstimation { DataRate bitrate_threshold_; LossBasedBandwidthEstimation loss_based_bandwidth_estimator_v1_; LossBasedBweV2 loss_based_bandwidth_estimator_v2_; + LossBasedState loss_based_state_; FieldTrialFlag disable_receiver_limit_caps_only_; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc index d0e2cb056b..6764eba95c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc @@ -44,7 +44,9 @@ BitrateEstimator::BitrateEstimator(const WebRtcKeyValueConfig* key_value_config) kMinRateWindowMs, kMaxRateWindowMs), uncertainty_scale_("scale", 10.0), - uncertainty_scale_in_alr_("scale_alr", 10.0), + uncertainty_scale_in_alr_("scale_alr", uncertainty_scale_), + small_sample_uncertainty_scale_("scale_small", uncertainty_scale_), + small_sample_threshold_("small_thresh", DataSize::Zero()), uncertainty_symmetry_cap_("symmetry_cap", DataRate::Zero()), estimate_floor_("floor", DataRate::Zero()), current_window_ms_(0), @@ -52,22 +54,24 @@ BitrateEstimator::BitrateEstimator(const WebRtcKeyValueConfig* key_value_config) bitrate_estimate_kbps_(-1.0f), bitrate_estimate_var_(50.0f) { // E.g WebRTC-BweThroughputWindowConfig/initial_window_ms:350,window_ms:250/ - ParseFieldTrial({&initial_window_ms_, &noninitial_window_ms_, - &uncertainty_scale_, &uncertainty_scale_in_alr_, - &uncertainty_symmetry_cap_, &estimate_floor_}, - key_value_config->Lookup(kBweThroughputWindowConfig)); + ParseFieldTrial( + {&initial_window_ms_, &noninitial_window_ms_, &uncertainty_scale_, + &uncertainty_scale_in_alr_, &small_sample_uncertainty_scale_, + &small_sample_threshold_, &uncertainty_symmetry_cap_, &estimate_floor_}, + key_value_config->Lookup(kBweThroughputWindowConfig)); } BitrateEstimator::~BitrateEstimator() = default; void BitrateEstimator::Update(Timestamp at_time, DataSize amount, bool in_alr) { - int rate_window_ms = noninitial_window_ms_; + int rate_window_ms = noninitial_window_ms_.Get(); // We use a larger window at the beginning to get a more stable sample that // we can use to initialize the estimate. if (bitrate_estimate_kbps_ < 0.f) - rate_window_ms = initial_window_ms_; - float bitrate_sample_kbps = - UpdateWindow(at_time.ms(), amount.bytes(), rate_window_ms); + rate_window_ms = initial_window_ms_.Get(); + bool is_small_sample = false; + float bitrate_sample_kbps = UpdateWindow(at_time.ms(), amount.bytes(), + rate_window_ms, &is_small_sample); if (bitrate_sample_kbps < 0.0f) return; if (bitrate_estimate_kbps_ < 0.0f) { @@ -75,15 +79,19 @@ void BitrateEstimator::Update(Timestamp at_time, DataSize amount, bool in_alr) { bitrate_estimate_kbps_ = bitrate_sample_kbps; return; } - // Define the sample uncertainty as a function of how far away it is from the - // current estimate. With low values of uncertainty_symmetry_cap_ we add more - // uncertainty to increases than to decreases. For higher values we approach - // symmetry. + // Optionally use higher uncertainty for very small samples to avoid dropping + // estimate and for samples obtained in ALR. float scale = uncertainty_scale_; - if (in_alr && bitrate_sample_kbps < bitrate_estimate_kbps_) { + if (is_small_sample && bitrate_sample_kbps < bitrate_estimate_kbps_) { + scale = small_sample_uncertainty_scale_; + } else if (in_alr && bitrate_sample_kbps < bitrate_estimate_kbps_) { // Optionally use higher uncertainty for samples obtained during ALR. scale = uncertainty_scale_in_alr_; } + // Define the sample uncertainty as a function of how far away it is from the + // current estimate. With low values of uncertainty_symmetry_cap_ we add more + // uncertainty to increases than to decreases. For higher values we approach + // symmetry. float sample_uncertainty = scale * std::abs(bitrate_estimate_kbps_ - bitrate_sample_kbps) / (bitrate_estimate_kbps_ + @@ -110,7 +118,8 @@ void BitrateEstimator::Update(Timestamp at_time, DataSize amount, bool in_alr) { float BitrateEstimator::UpdateWindow(int64_t now_ms, int bytes, - int rate_window_ms) { + int rate_window_ms, + bool* is_small_sample) { // Reset if time moves backwards. if (now_ms < prev_time_ms_) { prev_time_ms_ = -1; @@ -128,6 +137,7 @@ float BitrateEstimator::UpdateWindow(int64_t now_ms, prev_time_ms_ = now_ms; float bitrate_sample = -1.0f; if (current_window_ms_ >= rate_window_ms) { + *is_small_sample = sum_ < small_sample_threshold_->bytes(); bitrate_sample = 8.0f * sum_ / static_cast(rate_window_ms); current_window_ms_ -= rate_window_ms; sum_ = 0; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.h index 324eac53eb..d1fd754997 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.h @@ -38,12 +38,17 @@ class BitrateEstimator { virtual void ExpectFastRateChange(); private: - float UpdateWindow(int64_t now_ms, int bytes, int rate_window_ms); + float UpdateWindow(int64_t now_ms, + int bytes, + int rate_window_ms, + bool* is_small_sample); int sum_; FieldTrialConstrained initial_window_ms_; FieldTrialConstrained noninitial_window_ms_; FieldTrialParameter uncertainty_scale_; FieldTrialParameter uncertainty_scale_in_alr_; + FieldTrialParameter small_sample_uncertainty_scale_; + FieldTrialParameter small_sample_threshold_; FieldTrialParameter uncertainty_symmetry_cap_; FieldTrialParameter estimate_floor_; int64_t current_window_ms_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc index 53b9bd4c96..fdfc4a16c7 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.cc @@ -44,15 +44,6 @@ void CongestionWindowPushbackController::UpdatePacingQueue( pacing_bytes_ = pacing_bytes; } -void CongestionWindowPushbackController::UpdateMaxOutstandingData( - size_t max_outstanding_bytes) { - DataSize data_window = DataSize::bytes(max_outstanding_bytes); - if (current_data_window_) { - data_window = (data_window + current_data_window_.value()) / 2; - } - current_data_window_ = data_window; -} - void CongestionWindowPushbackController::SetDataWindow(DataSize data_window) { current_data_window_ = data_window; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.h index 38d817c9fd..479334182c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/congestion_window_pushback_controller.h @@ -34,7 +34,6 @@ class CongestionWindowPushbackController { uint32_t min_pushback_target_bitrate_bps); void UpdateOutstandingData(int64_t outstanding_bytes); void UpdatePacingQueue(int64_t pacing_bytes); - void UpdateMaxOutstandingData(size_t max_outstanding_bytes); uint32_t UpdateTargetBitrate(uint32_t bitrate_bps); void SetDataWindow(DataSize data_window); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc deleted file mode 100644 index 07648b9751..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2016 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 "modules/congestion_controller/goog_cc/median_slope_estimator.h" - -#include - -namespace webrtc { - -constexpr unsigned int kDeltaCounterMax = 1000; - -MedianSlopeEstimator::MedianSlopeEstimator(size_t window_size, - double threshold_gain) - : window_size_(window_size), - threshold_gain_(threshold_gain), - num_of_deltas_(0), - accumulated_delay_(0), - delay_hist_(), - median_filter_(0.5), - trendline_(0) {} - -MedianSlopeEstimator::~MedianSlopeEstimator() {} - -MedianSlopeEstimator::DelayInfo::DelayInfo(int64_t time, - double delay, - size_t slope_count) - : time(time), delay(delay) { - slopes.reserve(slope_count); -} - -MedianSlopeEstimator::DelayInfo::~DelayInfo() = default; - -void MedianSlopeEstimator::Update(double recv_delta_ms, - double send_delta_ms, - int64_t arrival_time_ms) { - const double delta_ms = recv_delta_ms - send_delta_ms; - ++num_of_deltas_; - if (num_of_deltas_ > kDeltaCounterMax) - num_of_deltas_ = kDeltaCounterMax; - - accumulated_delay_ += delta_ms; - // BWE_TEST_LOGGING_PLOT(1, "accumulated_delay_ms", arrival_time_ms, - // accumulated_delay_); - - // If the window is full, remove the |window_size_| - 1 slopes that belong to - // the oldest point. - if (delay_hist_.size() == window_size_) { - // for (double slope : delay_hist_.front().slopes) { - // const bool success = median_filter_.Erase(slope); - // RTC_CHECK(success); - // } - delay_hist_.pop_front(); - } - // Add |window_size_| - 1 new slopes. - for (auto& old_delay : delay_hist_) { - if (arrival_time_ms - old_delay.time != 0) { - // The C99 standard explicitly states that casts and assignments must - // perform the associated conversions. This means that |slope| will be - // a 64-bit double even if the division is computed using, e.g., 80-bit - // extended precision. I believe this also holds in C++ even though the - // C++11 standard isn't as explicit. Furthermore, there are good reasons - // to believe that compilers couldn't perform optimizations that break - // this assumption even if they wanted to. - double slope = (accumulated_delay_ - old_delay.delay) / - static_cast(arrival_time_ms - old_delay.time); - median_filter_.Insert(slope); - // We want to avoid issues with different rounding mode / precision - // which we might get if we recomputed the slope when we remove it. - old_delay.slopes.push_back(slope); - } - } - delay_hist_.emplace_back(arrival_time_ms, accumulated_delay_, - window_size_ - 1); - // Recompute the median slope. - if (delay_hist_.size() == window_size_) - trendline_ = median_filter_.GetPercentileValue(); - - // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trendline_); -} - -} // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h deleted file mode 100644 index 674a82829a..0000000000 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2016 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. - */ -#ifndef MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ -#define MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ - -#include "rtc_base/constructor_magic.h" -#include "rtc_base/numerics/percentile_filter.h" - -#include -#include -#include -#include - -namespace webrtc { - -class MedianSlopeEstimator { - public: - // |window_size| is the number of points required to compute a trend line. - // |threshold_gain| is used to scale the trendline slope for comparison to - // the old threshold. Once the old estimator has been removed (or the - // thresholds been merged into the estimators), we can just set the - // threshold instead of setting a gain. - MedianSlopeEstimator(size_t window_size, double threshold_gain); - ~MedianSlopeEstimator(); - - // Update the estimator with a new sample. The deltas should represent deltas - // between timestamp groups as defined by the InterArrival class. - void Update(double recv_delta_ms, - double send_delta_ms, - int64_t arrival_time_ms); - - // Returns the estimated trend k multiplied by some gain. - // 0 < k < 1 -> the delay increases, queues are filling up - // k == 0 -> the delay does not change - // k < 0 -> the delay decreases, queues are being emptied - double trendline_slope() const { return trendline_ * threshold_gain_; } - - // Returns the number of deltas which the current estimator state is based on. - unsigned int num_of_deltas() const { return num_of_deltas_; } - - private: - struct DelayInfo { - DelayInfo(int64_t time, double delay, size_t slope_count); - ~DelayInfo(); - int64_t time; - double delay; - std::vector slopes; - }; - // Parameters. - const size_t window_size_; - const double threshold_gain_; - // Used by the existing threshold. - unsigned int num_of_deltas_; - // Theil-Sen robust line fitting - double accumulated_delay_; - std::deque delay_hist_; - PercentileFilter median_filter_; - double trendline_; - - RTC_DISALLOW_COPY_AND_ASSIGN(MedianSlopeEstimator); -}; - -} // namespace webrtc - -#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_MEDIAN_SLOPE_ESTIMATOR_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 617da5ee17..0f777ff1fb 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -83,36 +83,50 @@ ProbeControllerConfig::ProbeControllerConfig( alr_probe_scale("alr_scale", 2), network_state_estimate_probing_interval("network_state_interval", TimeDelta::PlusInfinity()), - network_state_estimate_fast_rampup_rate("network_state_fast_rampup_rate", - 0), - network_state_estimate_drop_down_rate("network_state_drop_down_rate", 0), + probe_if_estimate_lower_than_network_state_estimate_ratio( + "est_lower_than_network_ratio", + 0), + estimate_lower_than_network_state_estimate_probing_interval( + "est_lower_than_network_interval", + TimeDelta::seconds(3)), network_state_probe_scale("network_state_scale", 1.0), network_state_probe_duration("network_state_probe_duration", TimeDelta::Millis<15>()), + probe_on_max_allocated_bitrate_change("probe_max_allocation", true), first_allocation_probe_scale("alloc_p1", 1), second_allocation_probe_scale("alloc_p2", 2), allocation_allow_further_probing("alloc_probe_further", false), allocation_probe_max("alloc_probe_max", DataRate::PlusInfinity()), min_probe_packets_sent("min_probe_packets_sent", 5), - min_probe_duration("min_probe_duration", TimeDelta::Millis<15>()), + min_probe_duration("min_probe_duration", TimeDelta::ms(15)), limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe", false), + loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", 0.0) { - ParseFieldTrial( - {&first_exponential_probe_scale, &second_exponential_probe_scale, - &further_exponential_probe_scale, &further_probe_threshold, - &alr_probing_interval, &alr_probe_scale, &first_allocation_probe_scale, - &second_allocation_probe_scale, &allocation_allow_further_probing, - &min_probe_duration, &network_state_estimate_probing_interval, - &network_state_estimate_fast_rampup_rate, - &network_state_estimate_drop_down_rate, &network_state_probe_scale, - &network_state_probe_duration, &min_probe_packets_sent, - &limit_probe_target_rate_to_loss_bwe, - &skip_if_estimate_larger_than_fraction_of_max}, - key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); + ParseFieldTrial({&first_exponential_probe_scale, + &second_exponential_probe_scale, + &further_exponential_probe_scale, + &further_probe_threshold, + &alr_probing_interval, + &alr_probe_scale, + &probe_on_max_allocated_bitrate_change, + &first_allocation_probe_scale, + &second_allocation_probe_scale, + &allocation_allow_further_probing, + &min_probe_duration, + &network_state_estimate_probing_interval, + &probe_if_estimate_lower_than_network_state_estimate_ratio, + &estimate_lower_than_network_state_estimate_probing_interval, + &network_state_probe_scale, + &network_state_probe_duration, + &min_probe_packets_sent, + &limit_probe_target_rate_to_loss_bwe, + &loss_limited_probe_scale, + &skip_if_estimate_larger_than_fraction_of_max}, + key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration ParseFieldTrial( @@ -120,8 +134,9 @@ ProbeControllerConfig::ProbeControllerConfig( key_value_config->Lookup("WebRTC-Bwe-InitialProbing")); ParseFieldTrial({&further_exponential_probe_scale, &further_probe_threshold}, key_value_config->Lookup("WebRTC-Bwe-ExponentialProbing")); - ParseFieldTrial({&alr_probing_interval, &alr_probe_scale}, - key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); + ParseFieldTrial( + {&alr_probing_interval, &alr_probe_scale, &loss_limited_probe_scale}, + key_value_config->Lookup("WebRTC-Bwe-AlrProbing")); ParseFieldTrial( {&first_allocation_probe_scale, &second_allocation_probe_scale, &allocation_allow_further_probing, &allocation_probe_max}, @@ -205,7 +220,8 @@ std::vector ProbeController::OnMaxTotalAllocatedBitrate( const bool in_alr = alr_start_time_.has_value(); const bool allow_allocation_probe = in_alr; - if (state_ == State::kProbingComplete && + if (config_.probe_on_max_allocated_bitrate_change && + state_ == State::kProbingComplete && max_total_allocated_bitrate != max_total_allocated_bitrate_ && estimated_bitrate_ < max_bitrate_ && estimated_bitrate_ < max_total_allocated_bitrate && @@ -272,13 +288,9 @@ std::vector ProbeController::InitiateExponentialProbing( std::vector ProbeController::SetEstimatedBitrate( DataRate bitrate, - bool bwe_limited_due_to_packet_loss, + BandwidthLimitedCause bandwidth_limited_cause, Timestamp at_time) { - if (bwe_limited_due_to_packet_loss != bwe_limited_due_to_packet_loss_ && - config_.limit_probe_target_rate_to_loss_bwe) { - state_ = State::kProbingComplete; - } - bwe_limited_due_to_packet_loss_ = bwe_limited_due_to_packet_loss; + bandwidth_limited_cause_ = bandwidth_limited_cause; if (bitrate < kBitrateDropThreshold * estimated_bitrate_) { time_of_last_large_drop_ = at_time; bitrate_before_last_large_drop_ = estimated_bitrate_; @@ -293,21 +305,27 @@ std::vector ProbeController::SetEstimatedBitrate( // bitrate_bps / 1000); mid_call_probing_waiting_for_result_ = false; } - std::vector pending_probes; if (state_ == State::kWaitingForProbingResult) { // Continue probing if probing results indicate channel has greater // capacity. - // MS_DEBUG_DEV( - // "[measured bitrate:%" PRIi64 ", minimum to probe further:%" PRIi64 "]", - // bitrate_bps, min_bitrate_to_probe_further_bps_); - - if (bitrate > min_bitrate_to_probe_further_) { - pending_probes = InitiateProbing( + DataRate network_state_estimate_probe_further_limit = + config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ + ? network_estimate_->link_capacity_upper * + config_.further_probe_threshold + : DataRate::PlusInfinity(); +/* RTC_LOG(LS_INFO) << "Measured bitrate: " << bitrate + << " Minimum to probe further: " + << min_bitrate_to_probe_further_ << " upper limit: " + << network_state_estimate_probe_further_limit;*/ + + if (bitrate > min_bitrate_to_probe_further_ && + bitrate <= network_state_estimate_probe_further_limit) { + return InitiateProbing( at_time, {config_.further_exponential_probe_scale * bitrate}, true); } } - - return pending_probes; + return {}; } void ProbeController::EnablePeriodicAlrProbing(bool enable) { @@ -370,38 +388,14 @@ std::vector ProbeController::RequestProbe( return std::vector(); } -void ProbeController::SetMaxBitrate(DataRate max_bitrate) { - MS_DEBUG_DEV("[max_bitrate_bps:%" PRIi64 "]", max_bitrate); - - max_bitrate_ = max_bitrate; -} - void ProbeController::SetNetworkStateEstimate( webrtc::NetworkStateEstimate estimate) { - if (config_.network_state_estimate_fast_rampup_rate > 0 && - estimated_bitrate_ < estimate.link_capacity_upper && - (!network_estimate_ || - estimate.link_capacity_upper >= - config_.network_state_estimate_fast_rampup_rate * - network_estimate_->link_capacity_upper)) { - send_probe_on_next_process_interval_ = true; - } - if (config_.network_state_estimate_drop_down_rate > 0 && network_estimate_ && - !estimate.link_capacity_upper.IsZero() && - (estimated_bitrate_ > estimate.link_capacity_upper || - bwe_limited_due_to_packet_loss_) && - estimate.link_capacity_upper <= - config_.network_state_estimate_drop_down_rate * - network_estimate_->link_capacity_upper) { - send_probe_on_next_process_interval_ = true; - } - network_estimate_ = estimate; } void ProbeController::Reset(Timestamp at_time) { network_available_ = true; - bwe_limited_due_to_packet_loss_ = false; + bandwidth_limited_cause_ = BandwidthLimitedCause::kDelayBasedLimited; state_ = State::kInit; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); time_last_probing_initiated_ = Timestamp::Zero(); @@ -416,7 +410,6 @@ void ProbeController::Reset(Timestamp at_time) { time_of_last_large_drop_ = now; bitrate_before_last_large_drop_ = DataRate::Zero(); max_total_allocated_bitrate_ = DataRate::Zero(); - send_probe_on_next_process_interval_ = false; } bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { @@ -430,13 +423,34 @@ bool ProbeController::TimeForAlrProbe(Timestamp at_time) const { } bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const { - if (config_.network_state_estimate_probing_interval->IsFinite() && - network_estimate_ && network_estimate_->link_capacity_upper.IsFinite() && - estimated_bitrate_ < network_estimate_->link_capacity_upper) { + if (!network_estimate_ || + network_estimate_->link_capacity_upper.IsInfinite()) { + return false; + } + + bool probe_due_to_low_estimate = + bandwidth_limited_cause_ == BandwidthLimitedCause::kDelayBasedLimited && + estimated_bitrate_ < + config_.probe_if_estimate_lower_than_network_state_estimate_ratio * + network_estimate_->link_capacity_upper; + if (probe_due_to_low_estimate && + config_.estimate_lower_than_network_state_estimate_probing_interval + ->IsFinite()) { + Timestamp next_probe_time = + time_last_probing_initiated_ + + config_.estimate_lower_than_network_state_estimate_probing_interval; + return at_time >= next_probe_time; + } + + bool periodic_probe = + estimated_bitrate_ < network_estimate_->link_capacity_upper; + if (periodic_probe && + config_.network_state_estimate_probing_interval->IsFinite()) { Timestamp next_probe_time = time_last_probing_initiated_ + config_.network_state_estimate_probing_interval; return at_time >= next_probe_time; } + return false; } @@ -454,8 +468,7 @@ std::vector ProbeController::Process(Timestamp at_time) { if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) { return {}; } - if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) || - TimeForNetworkStateProbe(at_time)) { + if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) { return InitiateProbing( at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true); } @@ -470,32 +483,19 @@ std::vector ProbeController::InitiateProbing( DataRate network_estimate = network_estimate_ ? network_estimate_->link_capacity_upper : DataRate::PlusInfinity(); + DataRate max_probe_rate = + max_total_allocated_bitrate_.IsZero() + ? max_bitrate_ + : std::min(max_total_allocated_bitrate_, max_bitrate_); if (std::min(network_estimate, estimated_bitrate_) > - config_.skip_if_estimate_larger_than_fraction_of_max * max_bitrate_) { + config_.skip_if_estimate_larger_than_fraction_of_max * max_probe_rate) { + state_ = State::kProbingComplete; + min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); return {}; } } - MS_DEBUG_DEV( - "[max_bitrate_bps_:%lld, max_probe_bitrate_bps:%" PRIi64 "]", - max_bitrate_bps_, - max_probe_bitrate_bps); - DataRate max_probe_bitrate = max_bitrate_; - if (bwe_limited_due_to_packet_loss_ && - config_.limit_probe_target_rate_to_loss_bwe) { - max_probe_bitrate = std::min(estimated_bitrate_, max_bitrate_); - } - if (config_.network_state_estimate_probing_interval->IsFinite() && - network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { - if (network_estimate_->link_capacity_upper.IsZero()) { - MS_DEBUG_TAG(bwe, "Not sending probe, Network state estimate is zero"); - return {}; - } - max_probe_bitrate = - std::min(max_probe_bitrate, network_estimate_->link_capacity_upper * - config_.network_state_probe_scale); - } if (max_total_allocated_bitrate_ > DataRate::Zero()) { // If a max allocated bitrate has been configured, allow probing up to 2x // that rate. This allows some overhead to account for bursty streams, @@ -507,12 +507,39 @@ std::vector ProbeController::InitiateProbing( std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2); } - send_probe_on_next_process_interval_ = false; + DataRate estimate_capped_bitrate = DataRate::PlusInfinity(); + if (config_.limit_probe_target_rate_to_loss_bwe) { + switch (bandwidth_limited_cause_) { + case BandwidthLimitedCause::kLossLimitedBweDecreasing: + // If bandwidth estimate is decreasing because of packet loss, do not + // send probes. + return {}; + case BandwidthLimitedCause::kLossLimitedBweIncreasing: + estimate_capped_bitrate = + std::min(max_probe_bitrate, + estimated_bitrate_ * config_.loss_limited_probe_scale); + break; + case BandwidthLimitedCause::kDelayBasedLimited: + break; + } + } + if (config_.network_state_estimate_probing_interval->IsFinite() && + network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { + if (network_estimate_->link_capacity_upper.IsZero()) { + MS_DEBUG_TAG(bwe, "Not sending probe, Network state estimate is zero"); + return {}; + } + estimate_capped_bitrate = + std::min({estimate_capped_bitrate, max_probe_bitrate, + network_estimate_->link_capacity_upper * + config_.network_state_probe_scale}); + } std::vector pending_probes; for (DataRate bitrate : bitrates_to_probe) { // RTC_DCHECK(!bitrate.IsZero()); + bitrate = std::min(bitrate, estimate_capped_bitrate); if (bitrate > max_probe_bitrate) { bitrate = max_probe_bitrate; probe_further = false; @@ -537,8 +564,11 @@ std::vector ProbeController::InitiateProbing( time_last_probing_initiated_ = now; if (probe_further) { state_ = State::kWaitingForProbingResult; + // Dont expect probe results to be larger than a fraction of the actual + // probe rate. min_bitrate_to_probe_further_ = - (*(bitrates_to_probe.end() - 1)) * config_.further_probe_threshold; + std::min(estimate_capped_bitrate, (*(bitrates_to_probe.end() - 1))) * + config_.further_probe_threshold; } else { state_ = State::kProbingComplete; min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h index 1fda7813bf..6cdc70c832 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h @@ -46,18 +46,19 @@ struct ProbeControllerConfig { // Configures how often we send probes if NetworkStateEstimate is available. FieldTrialParameter network_state_estimate_probing_interval; - // If the network state estimate increase more than this rate, a probe is sent - // the next process interval. - FieldTrialParameter network_state_estimate_fast_rampup_rate; - // If the network state estimate decreases more than this rate, a probe is - // sent the next process interval. - FieldTrialParameter network_state_estimate_drop_down_rate; + // Periodically probe as long as the the ratio beteeen current estimate and + // NetworkStateEstimate is lower then this. + FieldTrialParameter + probe_if_estimate_lower_than_network_state_estimate_ratio; + FieldTrialParameter + estimate_lower_than_network_state_estimate_probing_interval; FieldTrialParameter network_state_probe_scale; // Overrides min_probe_duration if network_state_estimate_probing_interval // is set and a network state estimate is known. FieldTrialParameter network_state_probe_duration; // Configures the probes emitted by changed to the allocated bitrate. + FieldTrialParameter probe_on_max_allocated_bitrate_change; FieldTrialOptional first_allocation_probe_scale; FieldTrialOptional second_allocation_probe_scale; FieldTrialFlag allocation_allow_further_probing; @@ -67,14 +68,23 @@ struct ProbeControllerConfig { FieldTrialParameter min_probe_packets_sent; // The minimum probing duration. FieldTrialParameter min_probe_duration; - // Max limit the target rate of a probe to current estimate if BWE is loss - // limited. + // Periodically probe when bandwidth estimate is loss limited. FieldTrialParameter limit_probe_target_rate_to_loss_bwe; + FieldTrialParameter loss_limited_probe_scale; // Dont send a probe if min(estimate, network state estimate) is larger than // this fraction of the set max bitrate. FieldTrialParameter skip_if_estimate_larger_than_fraction_of_max; }; +// Reason that bandwidth estimate is limited. Bandwidth estimate can be limited +// by either delay based bwe, or loss based bwe when it increases/decreases the +// estimate. +enum class BandwidthLimitedCause { + kLossLimitedBweIncreasing = 0, + kLossLimitedBweDecreasing = 1, + kDelayBasedLimited = 2 +}; + // This class controls initiation of probing to estimate initial channel // capacity. There is also support for probing during a session when max // bitrate is adjusted by an application. @@ -103,7 +113,7 @@ class ProbeController { ABSL_MUST_USE_RESULT std::vector SetEstimatedBitrate( DataRate bitrate, - bool bwe_limited_due_to_packet_loss, + BandwidthLimitedCause bandwidth_limited_cause, Timestamp at_time); void EnablePeriodicAlrProbing(bool enable); @@ -114,8 +124,6 @@ class ProbeController { ABSL_MUST_USE_RESULT std::vector RequestProbe( Timestamp at_time); - // Sets a new maximum probing bitrate, without generating a new probe cluster. - void SetMaxBitrate(DataRate max_bitrate); void SetNetworkStateEstimate(webrtc::NetworkStateEstimate estimate); // Resets the ProbeController to a state equivalent to as if it was just @@ -145,12 +153,12 @@ class ProbeController { bool TimeForNetworkStateProbe(Timestamp at_time) const; bool network_available_; - bool bwe_limited_due_to_packet_loss_; + BandwidthLimitedCause bandwidth_limited_cause_ = + BandwidthLimitedCause::kDelayBasedLimited; State state_; DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity(); Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity(); DataRate estimated_bitrate_ = DataRate::Zero(); - bool send_probe_on_next_process_interval_; absl::optional network_estimate_; DataRate start_bitrate_ = DataRate::Zero(); DataRate max_bitrate_ = DataRate::PlusInfinity(); diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 610646fd9f..78076c8e6c 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -38,7 +38,6 @@ libwebrtc_sources = [ 'libwebrtc/modules/congestion_controller/goog_cc/link_capacity_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/alr_detector.cc', 'libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc', - 'libwebrtc/modules/congestion_controller/goog_cc/median_slope_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/bitrate_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc', 'libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc', From 66deb26da8909d62a6c77b09be6b6aeccdff8dfe Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 5 Dec 2022 21:53:04 +0200 Subject: [PATCH 29/70] Backport latest changes from libwebrtc. --- .../goog_cc/goog_cc_network_control.cc | 59 ++++++++----------- .../goog_cc/goog_cc_network_control.h | 3 - 2 files changed, 25 insertions(+), 37 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index f251d0b8fe..c45ca8ec0a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -55,6 +55,17 @@ bool IsEnabled(const WebRtcKeyValueConfig* config, absl::string_view key) { bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Disabled") != 0; } +BandwidthLimitedCause GetBandwidthLimitedCause( + LossBasedState loss_based_state) { + switch (loss_based_state) { + case LossBasedState::kDecreasing: + return BandwidthLimitedCause::kLossLimitedBweDecreasing; + case LossBasedState::kIncreasing: + return BandwidthLimitedCause::kLossLimitedBweIncreasing; + default: + return BandwidthLimitedCause::kDelayBasedLimited; + } +} } // namespace GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, @@ -74,13 +85,9 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, "WebRTC-Bwe-LimitProbesLowerThanThroughputEstimate")), rate_control_settings_( RateControlSettings::ParseFromKeyValueConfig(key_value_config_)), - loss_based_stable_rate_( - IsEnabled(key_value_config_, "WebRTC-Bwe-LossBasedStableRate")), pace_at_max_of_bwe_and_lower_link_capacity_( IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtMaxOfBweAndLowerLinkCapacity")), - pace_at_loss_based_bwe_when_loss_( - IsEnabled(key_value_config_, "WebRTC-Bwe-PaceAtLossBaseBweWhenLoss")), probe_controller_( new ProbeController(key_value_config_)), congestion_window_pushback_controller_( @@ -110,8 +117,7 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, config.stream_based_config.min_total_allocated_bitrate.value_or( DataRate::Zero())), max_padding_rate_(config.stream_based_config.max_padding_rate.value_or( - DataRate::Zero())), - max_total_allocated_bitrate_(DataRate::Zero()) { + DataRate::Zero())) { //RTC_DCHECK(config.constraints.at_time.IsFinite()); ParseFieldTrial( {&safe_reset_on_route_change_, &safe_reset_acknowledged_rate_}, @@ -184,8 +190,6 @@ NetworkControlUpdate GoogCcNetworkController::OnProcessInterval( *total_bitrate, msg.at_time); update.probe_cluster_configs.insert(update.probe_cluster_configs.end(), probes.begin(), probes.end()); - - max_total_allocated_bitrate_ = *total_bitrate; } initial_config_.reset(); } @@ -280,17 +284,12 @@ NetworkControlUpdate GoogCcNetworkController::OnStreamsConfig( if (msg.requests_alr_probing) { probe_controller_->EnablePeriodicAlrProbing(*msg.requests_alr_probing); } - if (msg.max_total_allocated_bitrate && - *msg.max_total_allocated_bitrate != max_total_allocated_bitrate_) { - if (rate_control_settings_.TriggerProbeOnMaxAllocatedBitrateChange()) { - update.probe_cluster_configs = - probe_controller_->OnMaxTotalAllocatedBitrate( - *msg.max_total_allocated_bitrate, msg.at_time); - } else { - probe_controller_->SetMaxBitrate(*msg.max_total_allocated_bitrate); - } - max_total_allocated_bitrate_ = *msg.max_total_allocated_bitrate; + if (msg.max_total_allocated_bitrate) { + update.probe_cluster_configs = + probe_controller_->OnMaxTotalAllocatedBitrate( + *msg.max_total_allocated_bitrate, msg.at_time); } + bool pacing_changed = false; if (msg.pacing_factor && *msg.pacing_factor != pacing_factor_) { pacing_factor_ = *msg.pacing_factor; @@ -559,8 +558,9 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time, result.target_bitrate); } - bandwidth_estimation_->UpdateLossBasedEstimator(report, - result.delay_detector_state); + bandwidth_estimation_->UpdateLossBasedEstimator( + report, result.delay_detector_state, probe_bitrate, + estimate_ ? estimate_->link_capacity_upper : DataRate::PlusInfinity()); if (result.updated) { // Update the estimate in the ProbeController, in case we want to probe. MaybeTriggerOnNetworkChanged(&update, report.feedback_time); @@ -624,10 +624,6 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( uint8_t fraction_loss = bandwidth_estimation_->fraction_loss(); TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time(); DataRate loss_based_target_rate = bandwidth_estimation_->target_rate(); - bool bwe_limited_due_to_packet_loss = - loss_based_target_rate.IsFinite() && - bandwidth_estimation_->delay_based_limit().IsFinite() && - loss_based_target_rate < bandwidth_estimation_->delay_based_limit(); DataRate pushback_target_rate = loss_based_target_rate; // BWE_TEST_LOGGING_PLOT(1, "fraction_loss_%", at_time.ms(), @@ -652,11 +648,7 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( } DataRate stable_target_rate = bandwidth_estimation_->GetEstimatedLinkCapacity(); - if (loss_based_stable_rate_) { - stable_target_rate = std::min(stable_target_rate, loss_based_target_rate); - } else { - stable_target_rate = std::min(stable_target_rate, pushback_target_rate); - } + stable_target_rate = std::min(stable_target_rate, pushback_target_rate); if ((loss_based_target_rate != last_loss_based_target_rate_) || (fraction_loss != last_estimated_fraction_loss_) || @@ -690,7 +682,9 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( update->target_rate = target_rate_msg; auto probes = probe_controller_->SetEstimatedBitrate( - loss_based_target_rate, bwe_limited_due_to_packet_loss, at_time); + loss_based_target_rate, + GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state()), + at_time); update->probe_cluster_configs.insert(update->probe_cluster_configs.end(), probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); @@ -706,10 +700,7 @@ PacerConfig GoogCcNetworkController::GetPacingRates(Timestamp at_time) const { // Pacing rate is based on target rate before congestion window pushback, // because we don't want to build queues in the pacer when pushback occurs. DataRate pacing_rate = DataRate::Zero(); - if ((pace_at_max_of_bwe_and_lower_link_capacity_ || - (pace_at_loss_based_bwe_when_loss_ && - last_loss_based_target_rate_ >= delay_based_bwe_->last_estimate())) && - estimate_) { + if (pace_at_max_of_bwe_and_lower_link_capacity_ && estimate_) { pacing_rate = std::max({min_total_allocated_bitrate_, estimate_->link_capacity_lower, last_loss_based_target_rate_}) * diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h index 4d32d09883..5d9e945568 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -91,9 +91,7 @@ class GoogCcNetworkController : public NetworkControllerInterface { const bool ignore_probes_lower_than_network_estimate_; const bool limit_probes_lower_than_throughput_estimate_; const RateControlSettings rate_control_settings_; - const bool loss_based_stable_rate_; const bool pace_at_max_of_bwe_and_lower_link_capacity_; - const bool pace_at_loss_based_bwe_when_loss_; const std::unique_ptr probe_controller_; const std::unique_ptr @@ -136,7 +134,6 @@ class GoogCcNetworkController : public NetworkControllerInterface { double pacing_factor_; DataRate min_total_allocated_bitrate_; DataRate max_padding_rate_; - DataRate max_total_allocated_bitrate_; bool previously_in_alr_ = false; From 23a3204b8159f7f731e70346cc7726bc5c67bc5f Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 5 Dec 2022 22:07:55 +0200 Subject: [PATCH 30/70] Backport latest changes from libwebrtc. --- .../libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index a0a40562a2..009751868f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -240,6 +240,7 @@ void LossBasedBweV2::UpdateBandwidthEstimate( MS_WARN_TAG(bwe, "The estimator must be enabled before it can be used."); return; } + SetProbeBitrate(probe_bitrate); if (packet_results.empty()) { MS_WARN_TAG(bwe, "The estimate cannot be updated without any loss statistics."); return; From beb4d1db9f3b2596c49204c3d708526f350cc2ed Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 7 Dec 2022 18:16:50 +0200 Subject: [PATCH 31/70] Backport more changes. Rework trend-line estimator to produce R-squared in conjunction with slope, force to hold bitrate if we have big deviation of estimated values vs real values. Force overuse if R-squared < 0.1. Switch to TWCC feedback, ignore RR. --- .../bitrate_controller/loss_based_bwe_v2.cc | 12 +-- .../send_side_bandwidth_estimation.cc | 1 + .../goog_cc/trendline_estimator.cc | 90 +++++++++++++------ .../goog_cc/trendline_estimator.h | 18 +++- .../aimd_rate_control.cc | 5 +- worker/include/Settings.hpp | 2 +- .../RTC/TransportCongestionControlClient.cpp | 2 +- 7 files changed, 92 insertions(+), 38 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 009751868f..66299fba13 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -173,11 +173,11 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { } auto instant_limit = GetInstantUpperBound(); - MS_DEBUG_DEV("Using %s, Inherent Loss limit %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 "", - current_estimate_.loss_limited_bandwidth.bps() <= delay_based_limit.bps() ? "Loss" : "Delay", +/* MS_DEBUG_DEV("Using %s, Inherent Loss limit %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 "", + current_estimate_.loss_limited_bandwidth.bps() <= delay_based_estimate_.bps() ? "Loss" : "Delay", current_estimate_.loss_limited_bandwidth.bps(), - delay_based_limit.IsFinite() ? delay_based_limit.bps() : 0, - instant_limit.IsFinite() ? instant_limit.bps() : 0); + delay_based_estimate_.IsFinite() ? delay_based_estimate_.bps() : 0, + instant_limit.IsFinite() ? instant_limit.bps() : 0);*/ if (IsValid(delay_based_estimate_)) { result.bandwidth_estimate = std::min({current_estimate_.loss_limited_bandwidth, @@ -1103,12 +1103,12 @@ bool LossBasedBweV2::PushBackObservation( (observation_duration < config_->observation_duration_lower_bound && (delay_detector_state != BandwidthUsage::kBwOverusing || !config_->trendline_integration_enabled))) { - MS_DEBUG_DEV("Observation Duration %" PRIi64 ", Delay detector state %s, trendline_integration_enabled, %d, Current estimate %" PRIi64 "", +/* MS_DEBUG_DEV("Observation Duration %" PRIi64 ", Delay detector state %s, trendline_integration_enabled, %d, Current estimate %" PRIi64 "", observation_duration.ms(), delay_detector_state == BandwidthUsage::kBwNormal ? "Normal" : delay_detector_state == BandwidthUsage::kBwOverusing ? "Overusing" : "Underusing", config_->trendline_integration_enabled, - current_estimate_.loss_limited_bandwidth.bps()); + current_estimate_.loss_limited_bandwidth.bps());*/ return false; } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index c7cc3f61e4..21cbcaa692 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -222,6 +222,7 @@ SendSideBandwidthEstimation::SendSideBandwidthEstimation( bitrate_threshold_(kDefaultBitrateThreshold), loss_based_bandwidth_estimator_v1_(key_value_config), loss_based_bandwidth_estimator_v2_(key_value_config), + loss_based_state_(LossBasedState::kDelayBasedEstimate), disable_receiver_limit_caps_only_("Disabled") { if (BweLossExperimentIsEnabled()) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 6fbbda895d..e5f7efc7cf 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::TrendlineEstimator" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/trendline_estimator.h" @@ -50,7 +50,7 @@ size_t ReadTrendlineFilterWindowSize(const WebRtcKeyValueConfig* key_value_confi return TrendlineEstimatorSettings::kDefaultTrendlineWindowSize; } -absl::optional LinearFitSlope( +absl::optional LinearFitSlope( const std::deque& packets) { // RTC_DCHECK(packets.size() >= 2); // Compute the "center of mass". @@ -73,7 +73,22 @@ absl::optional LinearFitSlope( } if (denominator == 0) return absl::nullopt; - return numerator / denominator; + double b1 = numerator / denominator; + double b0 = y_avg - (b1 * x_avg); + + // Compute the R squared + double r_numerator = 0; + double r_denominator = 0; + for (const auto& packet : packets) { + double x = packet.arrival_time_ms; + double y = packet.smoothed_delay_ms; + r_numerator += pow(((b0 + (b1 * x)) - y_avg), 2); + r_denominator += pow((y - y_avg), 2); + } + + double r_squared = r_numerator / r_denominator; + + return TrendlineEstimator::RegressionResult(b1, r_squared); } absl::optional ComputeSlopeCap( @@ -104,8 +119,15 @@ absl::optional ComputeSlopeCap( settings.cap_uncertainty; } +double getAverage(std::deque const& hist) { + if (hist.empty()) { + return 0; + } + return std::accumulate(hist.begin(), hist.end(), 0.0) / hist.size(); +} + constexpr double kMaxAdaptOffsetMs = 15.0; -constexpr double kOverUsingTimeThreshold = 10; +constexpr double kOverUsingTimeThreshold = 5; constexpr int kMinNumDeltas = 60; constexpr int kDeltaCounterMax = 1000; @@ -168,13 +190,14 @@ TrendlineEstimator::TrendlineEstimator( accumulated_delay_(0), smoothed_delay_(0), delay_hist_(), + r_squared_hist_(), k_up_(0.0087), k_down_(0.039), overusing_time_threshold_(kOverUsingTimeThreshold), threshold_(12.5), prev_modified_trend_(NAN), last_update_ms_(-1), - prev_trend_(0.0), + prev_trend_(0.0, 0.0), time_over_using_(-1), overuse_counter_(0), hypothesis_(BandwidthUsage::kBwNormal), @@ -220,26 +243,32 @@ void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, delay_hist_.pop_front(); // Simple linear regression. - double trend = prev_trend_; + auto trend = prev_trend_; + RegressionResult result; + double avg_r_squared {0.0}; if (delay_hist_.size() == settings_.window_size) { // Update trend_ if it is possible to fit a line to the data. The delay // trend can be seen as an estimate of (send_rate - capacity)/capacity. // 0 < trend < 1 -> the delay increases, queues are filling up // trend == 0 -> the delay does not change // trend < 0 -> the delay decreases, queues are being emptied - trend = LinearFitSlope(delay_hist_).value_or(trend); + result = LinearFitSlope(delay_hist_).value_or(trend); + r_squared_hist_.emplace_back(result.r_squared); + if (r_squared_hist_.size() > settings_.window_size) + r_squared_hist_.pop_front(); + avg_r_squared = getAverage(r_squared_hist_); if (settings_.enable_cap) { absl::optional cap = ComputeSlopeCap(delay_hist_, settings_); // We only use the cap to filter out overuse detections, not // to detect additional underuses. - if (trend >= 0 && cap.has_value() && trend > cap.value()) { - trend = cap.value(); + if (trend.slope >= 0 && cap.has_value() && trend.slope > cap.value()) { + trend.slope = cap.value(); } } } - // BWE_TEST_LOGGING_PLOT(1, "trendline_slope", arrival_time_ms, trend); + MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); - Detect(trend, send_delta_ms, arrival_time_ms); + Detect(result, send_delta_ms, arrival_time_ms, avg_r_squared); } void TrendlineEstimator::Update(double recv_delta_ms, @@ -262,7 +291,7 @@ BandwidthUsage TrendlineEstimator::State() const { return network_state_predictor_ ? hypothesis_predicted_ : hypothesis_; } -void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { +void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared) { if (num_of_deltas_ < 2) { hypothesis_ = BandwidthUsage::kBwNormal; return; @@ -271,10 +300,28 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { BandwidthUsage prev_hypothesis = hypothesis_; const double modified_trend = - std::min(num_of_deltas_, kMinNumDeltas) * trend * threshold_gain_; + std::min(num_of_deltas_, kMinNumDeltas) * trend.slope * threshold_gain_; prev_modified_trend_ = modified_trend; // BWE_TEST_LOGGING_PLOT(1, "T", now_ms, modified_trend); // BWE_TEST_LOGGING_PLOT(1, "threshold", now_ms, threshold_); +/* for (auto it = delay_hist_.crbegin(); it != delay_hist_.crend(); ++it) { + MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f, raw_delay_:%f", it->arrival_time_ms, it->smoothed_delay_ms, it->raw_delay_ms); + }*/ + if (avg_r_squared > 0 && avg_r_squared < 0.50 ) { + if (avg_r_squared < 0.1) { + hypothesis_ = BandwidthUsage::kBwOverusing; + MS_DEBUG_DEV("OverUsing!"); + } else { + hypothesis_ = BandwidthUsage::kBwUnderusing; + MS_DEBUG_DEV("HOLD"); + } + + prev_trend_ = trend; + UpdateThreshold(modified_trend, now_ms); + + return; + } + if (modified_trend > threshold_) { if (time_over_using_ == -1) { // Initialize the timer. Assume that we've been @@ -286,21 +333,12 @@ void TrendlineEstimator::Detect(double trend, double ts_delta, int64_t now_ms) { time_over_using_ += ts_delta; } overuse_counter_++; - if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) { - if (trend >= prev_trend_) { + //if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) { + if (time_over_using_ > overusing_time_threshold_) { + if (trend.slope >= prev_trend_.slope) { time_over_using_ = 0; overuse_counter_ = 0; - - -/* -#if MS_LOG_DEV_LEVEL == 3 - for (auto& kv : delay_hist_) { - MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f", kv.first, kv.second); - } -#endif -*/ - - hypothesis_ = BandwidthUsage::kBwOverusing; + hypothesis_ = BandwidthUsage::kBwOverusing; if (hypothesis_ != prev_hypothesis) MS_DEBUG_DEV("hypothesis_: BandwidthUsage::kBwOverusing"); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index 6ae5b263bd..5adc009e68 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -98,9 +98,21 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double raw_delay_ms; }; + struct RegressionResult { + RegressionResult(double slope, + double r_squared) + : slope(slope), + r_squared(r_squared) {} + RegressionResult() + : slope(0.0), + r_squared(0.0) {} + double slope; + double r_squared; + }; + private: friend class GoogCcStatePrinter; - void Detect(double trend, double ts_delta, int64_t now_ms); + void Detect(RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared); void UpdateThreshold(double modified_offset, int64_t now_ms); @@ -117,6 +129,8 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double smoothed_delay_; // Linear least squares regression. std::deque delay_hist_; + // + std::deque r_squared_hist_; const double k_up_; const double k_down_; @@ -124,7 +138,7 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double threshold_; double prev_modified_trend_; int64_t last_update_ms_; - double prev_trend_; + RegressionResult prev_trend_; double time_over_using_; int overuse_counter_; BandwidthUsage hypothesis_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index dd401846d3..008f56b0f0 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -275,9 +275,9 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input, return; ChangeState(input, at_time); - MS_DEBUG_DEV("[estimated_throughput %lld, link_capacity_: %lld]", +/* MS_DEBUG_DEV("[estimated_throughput %lld, link_capacity_: %lld]", estimated_throughput.bps(), - link_capacity_.has_estimate() ? link_capacity_.estimate().bps() : -1); + link_capacity_.has_estimate() ? link_capacity_.estimate().bps() : -1);*/ switch (rate_control_state_) { case RateControlState::kRcHold: break; @@ -337,6 +337,7 @@ void AimdRateControl::ChangeBitrate(const RateControlInput& input, // Set bit rate to something slightly lower than the measured throughput // to get rid of any self-induced delay. decreased_bitrate = estimated_throughput * beta_; + MS_DEBUG_DEV("estimated_throughput: %lld, decreased_bitrate: %lld", estimated_throughput.bps(), decreased_bitrate.bps()); if (decreased_bitrate > current_bitrate_ && !link_capacity_fix_) { // TODO(terelius): The link_capacity estimate may be based on old // throughput measurements. Relying on them may lead to unnecessary diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index 61ec65eb4c..d520cd4ac5 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/" + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" }; }; diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 3b0d6310e4..bf6b11425d 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -38,7 +38,7 @@ namespace RTC webrtc::GoogCcFactoryConfig config; // Provide RTCP feedback as well as Receiver Reports. - config.feedback_only = false; + config.feedback_only = true; this->controllerFactory = new webrtc::GoogCcNetworkControllerFactory(std::move(config)); } From e001c75845c0faff4666b7a38ce88f10e3ae7987 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 9 Dec 2022 00:47:47 +0200 Subject: [PATCH 32/70] Adjust settings in delay bwe, add debounce in loss estimator with backoff --- .../bitrate_controller/loss_based_bwe_v2.cc | 47 ++++++++++++++----- .../bitrate_controller/loss_based_bwe_v2.h | 5 ++ .../goog_cc/goog_cc_network_control.cc | 2 +- .../goog_cc/probe_controller.cc | 14 +++--- .../goog_cc/trendline_estimator.cc | 9 ++-- .../aimd_rate_control.cc | 2 +- worker/include/Settings.hpp | 2 +- 7 files changed, 57 insertions(+), 24 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 66299fba13..35ab336b89 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ #define MS_CLASS "webrtc::LossBasedBweV2" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #include "modules/bitrate_controller/loss_based_bwe_v2.h" @@ -34,6 +34,7 @@ #include "rtc_base/experiments/field_trial_list.h" #include "rtc_base/experiments/field_trial_parser.h" +#include "DepLibUV.hpp" #include "Logger.hpp" namespace webrtc { @@ -123,23 +124,29 @@ LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) temporal_weights_.resize(config_->observation_window_size); instant_upper_bound_temporal_weights_.resize( config_->observation_window_size); + instant_loos_debounce_duration = (config_->observation_window_size / 2) * config_->observation_duration_lower_bound; CalculateTemporalWeights(); } void LossBasedBweV2::Reset() { current_estimate_.inherent_loss = config_->initial_inherent_loss_estimate; - //current_estimate_.loss_limited_bandwidth = config_->bandwidth_rampup_upper_bound_factor; + current_estimate_.loss_limited_bandwidth = max_bitrate_; observations_.clear(); - temporal_weights_.clear(); - instant_upper_bound_temporal_weights_.clear(); - observations_.resize(config_->observation_window_size); - temporal_weights_.resize(config_->observation_window_size); - instant_upper_bound_temporal_weights_.resize( - config_->observation_window_size); - - CalculateTemporalWeights(); + num_observations_ = 0; + partial_observation_.num_lost_packets = 0; + partial_observation_.num_packets = 0; + last_send_time_most_recent_observation_ = Timestamp::PlusInfinity(); + last_time_estimate_reduced_ = Timestamp::MinusInfinity(); + cached_instant_upper_bound_ = absl::nullopt; + delay_detector_states_.clear(); + recovering_after_loss_timestamp_ = Timestamp::MinusInfinity(); + bandwidth_limit_in_current_window_ = DataRate::PlusInfinity(); + current_state_ = LossBasedState::kDelayBasedEstimate; + probe_bitrate_ = DataRate::PlusInfinity(); + delay_based_estimate_ = DataRate::PlusInfinity(); + upper_link_capacity_ = DataRate::PlusInfinity(); } bool LossBasedBweV2::IsEnabled() const { @@ -388,7 +395,7 @@ absl::optional LossBasedBweV2::CreateConfig( "DelayBasedCandidate", false); FieldTrialParameter observation_duration_lower_bound( "ObservationDurationLowerBound", TimeDelta::seconds(1)); - FieldTrialParameter observation_window_size("ObservationWindowSize", 20); + FieldTrialParameter observation_window_size("ObservationWindowSize", 50); FieldTrialParameter sending_rate_smoothing_factor( "SendingRateSmoothingFactor", 0.0); FieldTrialParameter instant_upper_bound_temporal_weight_factor( @@ -973,7 +980,23 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { const double average_reported_loss_ratio = GetAverageReportedLossRatio(); if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { - + // MS_NOTE: Here we create debounce mechanism, that must help in + // bursts smoothening. Initially we reduce to 85% of previous BW estimate, + // if that will not help after debounce counter, we will reduce further with f + // formula based on bw balance. If we do not continue to overshoot limit in half of the + // observation duration window size, we reset. + if (!instant_loss_debounce_start.IsFinite()) { + instant_loss_debounce_start = Timestamp::ms(DepLibUV::GetTimeMsInt64()); + cached_instant_upper_bound_ = current_estimate_.loss_limited_bandwidth * 0.85; + } + instant_loos_debounce_counter_ += 1; + if (Timestamp::ms(DepLibUV::GetTimeMsInt64()) > instant_loss_debounce_start + instant_loos_debounce_duration) { + instant_loos_debounce_counter_ = 0; + instant_loss_debounce_start = Timestamp::MinusInfinity(); + } + if (kInstantLossDebounce < instant_loos_debounce_counter_) { + return; + } DataRate bandwidth_balance = config_->instant_upper_bound_bandwidth_balance; // MS_NOTE: In case of high sending rate the value of balance (75kbps) is too small, diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 641204db16..d8ba221906 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -200,6 +200,11 @@ class LossBasedBweV2 { DataRate max_bitrate_ = DataRate::PlusInfinity(); TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); double static constexpr kBwBalanceMultiplicator = 1.3; + double static constexpr kInstantLossDebounce = 3; + double instant_loos_debounce_counter_ = 0; + TimeDelta instant_loos_debounce_duration = TimeDelta::seconds(0); + Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); + }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index c45ca8ec0a..efa79878e8 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -545,7 +545,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( DelayBasedBwe::Result result; result = delay_based_bwe_->IncomingPacketFeedbackVector( - report, acknowledged_bitrate, probe_bitrate, estimate_, + report, bandwidth_estimation_->target_rate(), probe_bitrate, estimate_, alr_start_time.has_value()); if (result.updated) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 0f777ff1fb..78b6d10e21 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeController" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "api/units/data_rate.h" @@ -172,16 +172,15 @@ std::vector ProbeController::SetBitrates( } else if (start_bitrate_.IsZero()) { start_bitrate_ = min_bitrate; } - MS_DEBUG_DEV( - "[old_max_bitrate_bps:%lld, max_bitrate_bps:%lld]", - max_bitrate_bps_, - max_bitrate_bps); // The reason we use the variable `old_max_bitrate_pbs` is because we // need to set `max_bitrate_` before we call InitiateProbing. DataRate old_max_bitrate = max_bitrate_; max_bitrate_ = max_bitrate.IsFinite() ? max_bitrate : kDefaultMaxProbingBitrate; - + MS_DEBUG_DEV( + "[old_max_bitrate_bps:%lld, max_bitrate_bps:%lld]", + old_max_bitrate.bps(), + max_bitrate_.bps()); switch (state_) { case State::kInit: if (network_available_) @@ -354,6 +353,7 @@ void ProbeController::SetAlrEndedTimeMs(int64_t alr_end_time_ms) { std::vector ProbeController::RequestProbe( Timestamp at_time) { + MS_DEBUG_DEV("Requesting probe"); // Called once we have returned to normal state after a large drop in // estimated bandwidth. The current response is to initiate a single probe // session (if not already probing) at the previous bitrate. @@ -364,6 +364,7 @@ std::vector ProbeController::RequestProbe( bool alr_ended_recently = (alr_end_time_.has_value() && at_time - alr_end_time_.value() < kAlrEndedTimeout); + MS_DEBUG_DEV("in_alr: %d, alr_ended_recently:%d, in_rapid_recovery_experiment_:%d, state: %d", in_alr, alr_ended_recently, in_rapid_recovery_experiment_, state_); if (in_alr || alr_ended_recently || in_rapid_recovery_experiment_) { if (state_ == State::kProbingComplete) { DataRate suggested_probe = @@ -372,6 +373,7 @@ std::vector ProbeController::RequestProbe( (1 - kProbeUncertainty) * suggested_probe; TimeDelta time_since_drop = at_time - time_of_last_large_drop_; TimeDelta time_since_probe = at_time - last_bwe_drop_probing_time_; + MS_DEBUG_DEV("min_expected_probe_result: %lld, estimated_bitrate_:%lld, time_since_drop:%lld, time_since_probe: %lld", min_expected_probe_result.bps(), estimated_bitrate_.bps(), time_since_drop.seconds(), time_since_probe.seconds()); if (min_expected_probe_result > estimated_bitrate_ && time_since_drop < kBitrateDropTimeout && time_since_probe > kMinTimeBetweenAlrProbes) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index e5f7efc7cf..6e1beacce6 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -307,11 +307,14 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub /* for (auto it = delay_hist_.crbegin(); it != delay_hist_.crend(); ++it) { MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f, raw_delay_:%f", it->arrival_time_ms, it->smoothed_delay_ms, it->raw_delay_ms); }*/ - if (avg_r_squared > 0 && avg_r_squared < 0.50 ) { - if (avg_r_squared < 0.1) { + if (avg_r_squared > 0 && trend.slope > 0.0 && avg_r_squared < 0.6) { + if (avg_r_squared < 0.09) { hypothesis_ = BandwidthUsage::kBwOverusing; + MS_DEBUG_DEV("Instant OverUsing!"); + } else if (avg_r_squared < 0.2) { MS_DEBUG_DEV("OverUsing!"); - } else { + hypothesis_ = BandwidthUsage::kBwOverusing; + } else { hypothesis_ = BandwidthUsage::kBwUnderusing; MS_DEBUG_DEV("HOLD"); } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 008f56b0f0..54667a4871 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -32,7 +32,7 @@ namespace webrtc { namespace { constexpr TimeDelta kDefaultRtt = TimeDelta::Millis<200>(); -constexpr double kDefaultBackoffFactor = 0.85; +constexpr double kDefaultBackoffFactor = 0.95; constexpr char kBweBackOffFactorExperiment[] = "WebRTC-BweBackOffFactor"; diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index d520cd4ac5..7ee4544a21 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" + "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:100ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" }; }; From b988f54bfd5602ad58467f5c02c25c1dde1afbde Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 13 Dec 2022 17:01:41 +0200 Subject: [PATCH 33/70] Debounce instant loss, adjust default filed trial string --- .../bitrate_controller/loss_based_bwe_v2.cc | 128 +++++++++++++----- .../bitrate_controller/loss_based_bwe_v2.h | 4 +- .../goog_cc/probe_controller.cc | 2 +- .../goog_cc/trendline_estimator.cc | 10 +- worker/include/Settings.hpp | 2 +- 5 files changed, 100 insertions(+), 46 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 35ab336b89..3e6476faba 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -124,7 +124,7 @@ LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) temporal_weights_.resize(config_->observation_window_size); instant_upper_bound_temporal_weights_.resize( config_->observation_window_size); - instant_loos_debounce_duration = (config_->observation_window_size / 2) * config_->observation_duration_lower_bound; + //instant_loos_debounce_duration = (config_->observation_window_size / 2) * config_->observation_duration_lower_bound; CalculateTemporalWeights(); } @@ -411,7 +411,7 @@ absl::optional LossBasedBweV2::CreateConfig( FieldTrialParameter trendline_integration_enabled( "TrendlineIntegrationEnabled", false); FieldTrialParameter trendline_observations_window_size( - "TrendlineObservationsWindowSize", 20); + "TrendlineObservationsWindowSize", 15); FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1000.0); FieldTrialParameter delayed_increase_window( "DelayedIncreaseWindow", TimeDelta::ms(300)); @@ -978,62 +978,118 @@ DataRate LossBasedBweV2::GetInstantUpperBound() const { void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { DataRate instant_limit = max_bitrate_; const double average_reported_loss_ratio = GetAverageReportedLossRatio(); + auto now = Timestamp::ms(DepLibUV::GetTimeMsInt64()); + if (instant_loss_debounce_start.IsFinite()) { + if (now - instant_loss_debounce_start > instant_loss_debounce_duration) { + instant_loss_debounce_counter_ = 0; + instant_loss_debounce_start = Timestamp::MinusInfinity(); + MS_DEBUG_DEV("Resetting"); + } + } + if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) + { + MS_DEBUG_DEV( + "average_reported_loss_ratio %f, config_->instant_upper_bound_loss_offset %f", + average_reported_loss_ratio, + config_->instant_upper_bound_loss_offset); + + DataRate current_estimate = DataRate::MinusInfinity(); + if (IsValid(delay_based_estimate_)) + { + current_estimate = + std::min({ current_estimate_.loss_limited_bandwidth, delay_based_estimate_ }); + } + else + { + current_estimate = current_estimate_.loss_limited_bandwidth; + } - if (average_reported_loss_ratio > config_->instant_upper_bound_loss_offset) { + instant_loss_debounce_counter_ += 1; + auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 4); // MS_NOTE: Here we create debounce mechanism, that must help in // bursts smoothening. Initially we reduce to 85% of previous BW estimate, // if that will not help after debounce counter, we will reduce further with f // formula based on bw balance. If we do not continue to overshoot limit in half of the // observation duration window size, we reset. - if (!instant_loss_debounce_start.IsFinite()) { - instant_loss_debounce_start = Timestamp::ms(DepLibUV::GetTimeMsInt64()); - cached_instant_upper_bound_ = current_estimate_.loss_limited_bandwidth * 0.85; + if (!instant_loss_debounce_start.IsFinite()) + { + instant_loss_debounce_start = now; + MS_DEBUG_DEV("First Instant Loss"); } - instant_loos_debounce_counter_ += 1; - if (Timestamp::ms(DepLibUV::GetTimeMsInt64()) > instant_loss_debounce_start + instant_loos_debounce_duration) { - instant_loos_debounce_counter_ = 0; - instant_loss_debounce_start = Timestamp::MinusInfinity(); + + if ((now - instant_loss_debounce_start) < reduce_debounce_time && instant_loss_debounce_counter_ > 1) + { + MS_DEBUG_DEV( + "Debouncing loss estimate decease as %lld < %lld", + (now - instant_loss_debounce_start).ms(), + reduce_debounce_time.ms()); + return; + } + + auto weight_idx = (instant_loss_debounce_counter_ < config_->observation_window_size) + ? instant_loss_debounce_counter_ + : 20; + auto reduce_factor = std::max(temporal_weights_[weight_idx], 0.75); + + MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), reduce_factor); + + cached_instant_upper_bound_ = current_estimate * reduce_factor; + + MS_DEBUG_DEV("cached_instant_upper_bound_ %lld", cached_instant_upper_bound_->bps()); + + if (now - instant_loss_debounce_start > instant_loss_debounce_duration) + { + instant_loss_debounce_counter_ = 0; + instant_loss_debounce_start = Timestamp::MinusInfinity(); + MS_DEBUG_DEV("Resetting"); } - if (kInstantLossDebounce < instant_loos_debounce_counter_) { + else + { + instant_loss_debounce_start = now; + MS_DEBUG_DEV("Updating instant_loss_debounce_start"); return; } + DataRate bandwidth_balance = config_->instant_upper_bound_bandwidth_balance; // MS_NOTE: In case of high sending rate the value of balance (75kbps) is too small, // and leads to big BW drops even in the case of small loss ratio. - if (sending_rate.bps() > config_->instant_upper_bound_bandwidth_balance.bps() * 100) { + if (sending_rate.bps() > config_->instant_upper_bound_bandwidth_balance.bps() * 100) + { bandwidth_balance = DataRate::bps((sending_rate.bps() / 100) * kBwBalanceMultiplicator); } - instant_limit = bandwidth_balance / - (average_reported_loss_ratio - - config_->instant_upper_bound_loss_offset); - + instant_limit = + bandwidth_balance / (average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); - MS_DEBUG_DEV("Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 ", average_reported_loss_ratio %f, diff: %f, sending rate: %lld", - bandwidth_balance.bps(), - instant_limit.IsFinite() ? instant_limit.bps() : 0, - average_reported_loss_ratio, - average_reported_loss_ratio - config_->instant_upper_bound_loss_offset, - sending_rate.bps()); + MS_DEBUG_DEV( + "Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 + ", average_reported_loss_ratio %f, diff: %f, sending rate: %lld", + bandwidth_balance.bps(), + instant_limit.IsFinite() ? instant_limit.bps() : 0, + average_reported_loss_ratio, + average_reported_loss_ratio - config_->instant_upper_bound_loss_offset, + sending_rate.bps()); - if (average_reported_loss_ratio > config_->high_loss_rate_threshold) { + if (average_reported_loss_ratio > config_->high_loss_rate_threshold) + { instant_limit = std::min( - instant_limit, DataRate::kbps(std::max( - static_cast(min_bitrate_.kbps()), - config_->bandwidth_cap_at_high_loss_rate.kbps() - - config_->slope_of_bwe_high_loss_func * - average_reported_loss_ratio))); + instant_limit, + DataRate::kbps(std::max( + static_cast(min_bitrate_.kbps()), + config_->bandwidth_cap_at_high_loss_rate.kbps() - + config_->slope_of_bwe_high_loss_func * average_reported_loss_ratio))); } - } - if (IsBandwidthLimitedDueToLoss()) { - if (IsValid(upper_link_capacity_) && - config_->bound_by_upper_link_capacity_when_loss_limited) { - instant_limit = std::min(instant_limit, upper_link_capacity_); - } - } - cached_instant_upper_bound_ = instant_limit; + if (IsBandwidthLimitedDueToLoss()) + { + if (IsValid(upper_link_capacity_) && config_->bound_by_upper_link_capacity_when_loss_limited) + { + instant_limit = std::min(instant_limit, upper_link_capacity_); + } + } + cached_instant_upper_bound_ = instant_limit; + } } void LossBasedBweV2::CalculateTemporalWeights() { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index d8ba221906..996b72984e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -201,8 +201,8 @@ class LossBasedBweV2 { TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); double static constexpr kBwBalanceMultiplicator = 1.3; double static constexpr kInstantLossDebounce = 3; - double instant_loos_debounce_counter_ = 0; - TimeDelta instant_loos_debounce_duration = TimeDelta::seconds(0); + size_t instant_loss_debounce_counter_ = 0; + TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(2); Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 78b6d10e21..bf5faf698f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeController" -#define MS_LOG_DEV_LEVEL 3 +//#define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "api/units/data_rate.h" diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 6e1beacce6..df274f4008 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -127,7 +127,7 @@ double getAverage(std::deque const& hist) { } constexpr double kMaxAdaptOffsetMs = 15.0; -constexpr double kOverUsingTimeThreshold = 5; +constexpr double kOverUsingTimeThreshold = 10; constexpr int kMinNumDeltas = 60; constexpr int kDeltaCounterMax = 1000; @@ -307,13 +307,11 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub /* for (auto it = delay_hist_.crbegin(); it != delay_hist_.crend(); ++it) { MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f, raw_delay_:%f", it->arrival_time_ms, it->smoothed_delay_ms, it->raw_delay_ms); }*/ - if (avg_r_squared > 0 && trend.slope > 0.0 && avg_r_squared < 0.6) { - if (avg_r_squared < 0.09) { + + if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < 0.4) { + if (avg_r_squared < 0.15) { hypothesis_ = BandwidthUsage::kBwOverusing; - MS_DEBUG_DEV("Instant OverUsing!"); - } else if (avg_r_squared < 0.2) { MS_DEBUG_DEV("OverUsing!"); - hypothesis_ = BandwidthUsage::kBwOverusing; } else { hypothesis_ = BandwidthUsage::kBwUnderusing; MS_DEBUG_DEV("HOLD"); diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index 7ee4544a21..16745e7617 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:100ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" + "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" }; }; From 64c00cbfa3faaf5146b4f836877353ef4cc123a1 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 13 Dec 2022 17:05:27 +0200 Subject: [PATCH 34/70] try fix maxlen --- node/src/Worker.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index fcbc13bc93..f6310736a5 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -70,6 +70,7 @@ export type WorkerSettings = * * NOTE: For advanced users only. An invalid value will make the worker crash. * Default value is + * eslint-disable-next-line max-len * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". */ libwebrtcFieldTrials?: string; From 71f94592bd92cfa1fc2adbe71f158549cb33e1cc Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 13 Dec 2022 17:09:30 +0200 Subject: [PATCH 35/70] Try update to C++14 --- worker/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/meson.build b/worker/meson.build index b93ca83098..18ae24fb1f 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -3,7 +3,7 @@ project( ['c', 'cpp'], default_options : [ 'warning_level=1', - 'cpp_std=c++11', + 'cpp_std=c++14', 'default_library=static', ], meson_version: '>= 0.58', From 9a61385ae488d61a6efbb510fd81026b29ca3dc0 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 13 Dec 2022 17:32:03 +0200 Subject: [PATCH 36/70] Fix Lint for long field trial string --- node/src/Worker.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index f6310736a5..b7fcda84f3 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -64,16 +64,17 @@ export type WorkerSettings = */ dtlsPrivateKeyFile?: string; + /* eslint-disable max-len */ /** * Field trials for libwebrtc. * @private * * NOTE: For advanced users only. An invalid value will make the worker crash. * Default value is - * eslint-disable-next-line max-len - * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". + * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". // eslint-disable max-len */ libwebrtcFieldTrials?: string; + /* eslint-enable max-len */ /** * Custom application data. From a71c28947d92cc26b279fc8b98e1448498cdcfda Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 13 Dec 2022 22:17:57 +0200 Subject: [PATCH 37/70] Add EventEmitter migrate to c++14 --- worker/.clang-format | 2 +- worker/Makefile | 2 +- worker/deps/libwebrtc/libwebrtc.gyp | 4 +- .../bitrate_controller/loss_based_bwe_v2.h | 3 +- worker/deps/libwebrtc/meson.build | 1 + worker/include/EventEmitter.hpp | 94 +++++++++++++++++++ worker/scripts/cppcheck.sh | 2 +- 7 files changed, 102 insertions(+), 6 deletions(-) create mode 100644 worker/include/EventEmitter.hpp diff --git a/worker/.clang-format b/worker/.clang-format index e9d4091214..b51c5cea53 100644 --- a/worker/.clang-format +++ b/worker/.clang-format @@ -83,6 +83,6 @@ SpacesInCStyleCastParentheses: false SpacesInContainerLiterals: true SpacesInParentheses: false SpacesInSquareBrackets: false -Standard: c++11 +Standard: c++14 TabWidth: 2 UseTab: ForIndentation diff --git a/worker/Makefile b/worker/Makefile index 2b8a5771e0..de2bd0eca4 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -229,7 +229,7 @@ tidy: $(PYTHON) ./scripts/clang-tidy.py \ -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy \ -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements \ - -header-filter='(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)' \ + -header-filter='(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|EventEmitter.hpp|handles/**/*.hpp)' \ -p=$(BUILD_DIR) \ -j=$(CORES) \ -checks=$(MEDIASOUP_TIDY_CHECKS) \ diff --git a/worker/deps/libwebrtc/libwebrtc.gyp b/worker/deps/libwebrtc/libwebrtc.gyp index eb84186549..aadb853f6c 100644 --- a/worker/deps/libwebrtc/libwebrtc.gyp +++ b/worker/deps/libwebrtc/libwebrtc.gyp @@ -143,13 +143,13 @@ # Platform-specifics. [ 'OS != "win"', { - 'cflags': [ '-std=c++11' ] + 'cflags': [ '-std=c++14' ] }], [ 'OS == "mac"', { 'xcode_settings': { - 'OTHER_CPLUSPLUSFLAGS' : [ '-std=c++11' ] + 'OTHER_CPLUSPLUSFLAGS' : [ '-std=c++14' ] } }] ] diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 996b72984e..be083ad07a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -23,6 +23,7 @@ #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/transport/webrtc_key_value_config.h" +#include "EventEmitter.hpp" namespace webrtc { @@ -204,7 +205,7 @@ class LossBasedBweV2 { size_t instant_loss_debounce_counter_ = 0; TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(2); Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); - + EventEmitter events; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 78076c8e6c..5145c9dc18 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -73,6 +73,7 @@ libwebrtc = library( libuv_proj.get_variable('libuv_dep'), ], include_directories: libwebrtc_include_directories, + override_options : ['c_std=c11', 'cpp_std=c++14'], cpp_args: cpp_args, ) diff --git a/worker/include/EventEmitter.hpp b/worker/include/EventEmitter.hpp new file mode 100644 index 0000000000..7489a8dea0 --- /dev/null +++ b/worker/include/EventEmitter.hpp @@ -0,0 +1,94 @@ +// +// Created by Eugene Voityuk on 13.12.2022. +// +#ifndef MS_DEP_EVENT_EMITTER_HPP +#define MS_DEP_EVENT_EMITTER_HPP + +#include +#include +#include +#include + +struct BaseEvent +{ + virtual ~BaseEvent() = default; +protected: + static size_t getNextType(); +}; + +size_t BaseEvent::getNextType() +{ + static size_t type_count = 0; + return type_count++; +} + + +template +struct Event : BaseEvent +{ + static size_t type() + { + static size_t t_type = BaseEvent::getNextType(); + return t_type; + } + explicit Event(const EventType& event) : event_(event) {} + const EventType& event_; +}; + +class EventEmitter +{ +private: + template + using call_type = std::function; + +public: + template + void subscribe(const call_type callable) + { + // When events such as COLLISION don't derive + // from Event, you have to get the type by + // using one more level of indirection. + size_t type = Event::type(); + if (type >= m_subscribers.size()) + m_subscribers.resize(type+1); + m_subscribers[type].push_back(CallbackWrapper(callable)); + } + +public: + template + void emit(const EventType& event) + { + size_t type = Event::type(); + if (m_subscribers[type].empty()) + return; + if (type >= m_subscribers.size()) + m_subscribers.resize(type+1); + + Event wrappedEvent(event); + for (auto& receiver : m_subscribers[type]) + receiver(wrappedEvent); + } +private: + template + struct CallbackWrapper + { + explicit CallbackWrapper(call_type callable) : m_callable(callable) {} + + void operator() (const BaseEvent& event) { + // The event handling code requires a small change too. + // A reference to the EventType object is stored + // in Event. You get the EventType reference from the + // Event and make the final call. + m_callable(static_cast&>(event).event_); + } + + call_type m_callable; + }; +public: + void removeAllListeners() { + m_subscribers.clear(); + } +private: + std::vector > > m_subscribers; +}; +#endif // MS_EVENTEMITTER_HPP diff --git a/worker/scripts/cppcheck.sh b/worker/scripts/cppcheck.sh index 14ca7d5bd6..99fe7082b6 100755 --- a/worker/scripts/cppcheck.sh +++ b/worker/scripts/cppcheck.sh @@ -30,7 +30,7 @@ XML_FILE="/tmp/mediasoup-worker-cppcheck.xml" HTML_REPORT_DIR="/tmp/mediasoup-worker-cppcheck-report" echo ">>> [INFO] running cppcheck ..." -cppcheck --std=c++11 --enable=${CPPCHECKS} -v --quiet --report-progress --inline-suppr --error-exitcode=69 -I include src --xml-version=2 2> $XML_FILE +cppcheck --std=c++14 --enable=${CPPCHECKS} -v --quiet --report-progress --inline-suppr --error-exitcode=69 -I include src --xml-version=2 2> $XML_FILE # If exit code is 1 it means that some cppcheck option is wrong, so abort. if [ $? -eq 1 ] ; then From 86a423f25bf44323038733b320c226c3fa43f4e5 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 00:01:24 +0200 Subject: [PATCH 38/70] Fix maxlen for fieldtrial string commnet --- node/src/Worker.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index f6310736a5..f50aed53b3 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -64,6 +64,7 @@ export type WorkerSettings = */ dtlsPrivateKeyFile?: string; + /* eslint-disable max-len */ /** * Field trials for libwebrtc. * @private @@ -74,6 +75,7 @@ export type WorkerSettings = * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". */ libwebrtcFieldTrials?: string; + /* eslint-enable max-len */ /** * Custom application data. From 965a5c10d8e96317ceb72d1186295213e626c0df Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 00:08:43 +0200 Subject: [PATCH 39/70] Fix maxlen for field trial string comment --- node/src/Worker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index f6310736a5..f249f7a272 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -63,17 +63,17 @@ export type WorkerSettings = * certificate is dynamically created. */ dtlsPrivateKeyFile?: string; - + /* eslint-disable max-len */ /** * Field trials for libwebrtc. * @private * * NOTE: For advanced users only. An invalid value will make the worker crash. * Default value is - * eslint-disable-next-line max-len * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". */ libwebrtcFieldTrials?: string; + /* eslint-enable max-len */ /** * Custom application data. From 96ddaa4c63a1d09ebb775961615902aba132ea29 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 00:10:35 +0200 Subject: [PATCH 40/70] Fix maxlen for field trial string comment --- node/src/Worker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index d3d3f9daba..f249f7a272 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -63,7 +63,7 @@ export type WorkerSettings = * certificate is dynamically created. */ dtlsPrivateKeyFile?: string; - + /* eslint-disable max-len */ /** * Field trials for libwebrtc. * @private From b2daa7faf1d02c6215a70f29da80225e7e55746c Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 01:27:16 +0200 Subject: [PATCH 41/70] Fix EventEmitter --- .../bitrate_controller/loss_based_bwe_v2.cc | 1 + .../bitrate_controller/loss_based_bwe_v2.h | 4 +- .../send_side_bandwidth_estimation.cc | 5 + worker/include/EventEmitter.h | 92 +++++++++++++++++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 worker/include/EventEmitter.h diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 3e6476faba..f393b5e728 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -1002,6 +1002,7 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { else { current_estimate = current_estimate_.loss_limited_bandwidth; + events.emit(current_estimate_.loss_limited_bandwidth); } instant_loss_debounce_counter_ += 1; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 996b72984e..16749119cf 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -23,6 +23,7 @@ #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/transport/webrtc_key_value_config.h" +#include "EventEmitter.h" namespace webrtc { @@ -57,7 +58,7 @@ class LossBasedBweV2 { // Returns `DataRate::PlusInfinity` if no BWE can be calculated. Result GetLossBasedResult() const; - + EventEmitter events; void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); void SetBandwidthEstimate(DataRate bandwidth_estimate); void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); @@ -204,7 +205,6 @@ class LossBasedBweV2 { size_t instant_loss_debounce_counter_ = 0; TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(2); Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); - }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 21cbcaa692..3d86c8941c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -374,6 +374,11 @@ void SendSideBandwidthEstimation::UpdateLossBasedEstimator( loss_based_bandwidth_estimator_v2_.UpdateBandwidthEstimate( report.packet_feedbacks, delay_based_limit_, delay_detector_state, probe_bitrate, upper_link_capacity); + + loss_based_bandwidth_estimator_v2_.events.subscribe([&](auto &event) { + MS_DEBUG_DEV("loss bitrate %lld", event.bps()); + }); + UpdateEstimate(report.feedback_time); } } diff --git a/worker/include/EventEmitter.h b/worker/include/EventEmitter.h new file mode 100644 index 0000000000..ab67c88040 --- /dev/null +++ b/worker/include/EventEmitter.h @@ -0,0 +1,92 @@ +// +// Created by Eugene Voityuk on 14.12.2022. +// + +#ifndef MEDIASOUP_EVENTEMITTER_H +#define MEDIASOUP_EVENTEMITTER_H +#include +#include +#include +#include +#include + +class BaseEvent { +public: + ~BaseEvent() = default; + static size_t getNextType() + { + static size_t type_count = 0; + return type_count++; + } +}; + + +template +struct Event : BaseEvent +{ + static size_t type() + { + static size_t t_type = BaseEvent::getNextType(); + return t_type; + } + Event(const EventType& event) : event(event) {} + const EventType& event; +}; + +class EventEmitter +{ +private: + template + using call_type = std::function; + +public: + template + void subscribe(const call_type callable) + { + // When events such as COLLISION don't derive + // from Event, you have to get the type by + // using one more level of indirection. + size_t type = Event::type(); + if (type >= m_subscribers.size()) + m_subscribers.resize(type+1); + m_subscribers[type].push_back(CallbackWrapper(callable)); + } + +public: + template + void emit(const EventType& event) + { + size_t type = Event::type(); + if (m_subscribers[type].empty()) + return; + if (type >= m_subscribers.size()) + m_subscribers.resize(type+1); + + Event wrappedEvent(event); + for (auto& receiver : m_subscribers[type]) + receiver(wrappedEvent); + } +private: + template + struct CallbackWrapper + { + CallbackWrapper(call_type callable) : m_callable(callable) {} + + void operator() (const BaseEvent& event) { + // The event handling code requires a small change too. + // A reference to the EventType object is stored + // in Event. You get the EventType reference from the + // Event and make the final call. + m_callable(static_cast&>(event).event); + } + + call_type m_callable; + }; +public: + void removeAllListeners() { + m_subscribers.clear(); + } +private: + std::vector>> m_subscribers; +}; +#endif // MEDIASOUP_EVENTEMITTER_H From e76b9fd521895d499c1638cb36596c98bdb0fee5 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 01:42:27 +0200 Subject: [PATCH 42/70] Remove old event emitter --- worker/include/EventEmitter.hpp | 94 --------------------------------- 1 file changed, 94 deletions(-) delete mode 100644 worker/include/EventEmitter.hpp diff --git a/worker/include/EventEmitter.hpp b/worker/include/EventEmitter.hpp deleted file mode 100644 index 7489a8dea0..0000000000 --- a/worker/include/EventEmitter.hpp +++ /dev/null @@ -1,94 +0,0 @@ -// -// Created by Eugene Voityuk on 13.12.2022. -// -#ifndef MS_DEP_EVENT_EMITTER_HPP -#define MS_DEP_EVENT_EMITTER_HPP - -#include -#include -#include -#include - -struct BaseEvent -{ - virtual ~BaseEvent() = default; -protected: - static size_t getNextType(); -}; - -size_t BaseEvent::getNextType() -{ - static size_t type_count = 0; - return type_count++; -} - - -template -struct Event : BaseEvent -{ - static size_t type() - { - static size_t t_type = BaseEvent::getNextType(); - return t_type; - } - explicit Event(const EventType& event) : event_(event) {} - const EventType& event_; -}; - -class EventEmitter -{ -private: - template - using call_type = std::function; - -public: - template - void subscribe(const call_type callable) - { - // When events such as COLLISION don't derive - // from Event, you have to get the type by - // using one more level of indirection. - size_t type = Event::type(); - if (type >= m_subscribers.size()) - m_subscribers.resize(type+1); - m_subscribers[type].push_back(CallbackWrapper(callable)); - } - -public: - template - void emit(const EventType& event) - { - size_t type = Event::type(); - if (m_subscribers[type].empty()) - return; - if (type >= m_subscribers.size()) - m_subscribers.resize(type+1); - - Event wrappedEvent(event); - for (auto& receiver : m_subscribers[type]) - receiver(wrappedEvent); - } -private: - template - struct CallbackWrapper - { - explicit CallbackWrapper(call_type callable) : m_callable(callable) {} - - void operator() (const BaseEvent& event) { - // The event handling code requires a small change too. - // A reference to the EventType object is stored - // in Event. You get the EventType reference from the - // Event and make the final call. - m_callable(static_cast&>(event).event_); - } - - call_type m_callable; - }; -public: - void removeAllListeners() { - m_subscribers.clear(); - } -private: - std::vector > > m_subscribers; -}; -#endif // MS_EVENTEMITTER_HPP From e261944bded3e4886ad791b588fdd04a756410b6 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 02:23:53 +0200 Subject: [PATCH 43/70] test c++17 --- worker/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/meson.build b/worker/meson.build index 18ae24fb1f..81012a767d 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -3,7 +3,7 @@ project( ['c', 'cpp'], default_options : [ 'warning_level=1', - 'cpp_std=c++14', + 'cpp_std=c++17', 'default_library=static', ], meson_version: '>= 0.58', From becaef171cc512fe46523c2f2280a918d4601a59 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 14 Dec 2022 03:06:06 +0200 Subject: [PATCH 44/70] remain c++14 --- worker/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/meson.build b/worker/meson.build index 81012a767d..18ae24fb1f 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -3,7 +3,7 @@ project( ['c', 'cpp'], default_options : [ 'warning_level=1', - 'cpp_std=c++17', + 'cpp_std=c++14', 'default_library=static', ], meson_version: '>= 0.58', From 4b86b18862e4dfc8a21d7564746ea249b0ce630b Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 19 Dec 2022 19:18:15 +0200 Subject: [PATCH 45/70] Revert to remain on C++ 11. --- worker/meson.build | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/meson.build b/worker/meson.build index 18ae24fb1f..b93ca83098 100644 --- a/worker/meson.build +++ b/worker/meson.build @@ -3,7 +3,7 @@ project( ['c', 'cpp'], default_options : [ 'warning_level=1', - 'cpp_std=c++14', + 'cpp_std=c++11', 'default_library=static', ], meson_version: '>= 0.58', From e1333f854637f6be09784617140b7ea369a9977d Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 19 Dec 2022 19:21:44 +0200 Subject: [PATCH 46/70] Cosmetic constants. --- .../congestion_controller/goog_cc/trendline_estimator.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index df274f4008..7371231d8e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::TrendlineEstimator" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/trendline_estimator.h" @@ -30,6 +30,8 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; +constexpr double kDefaultRSquaredUpperBound = 0.4; +constexpr double kDefaultRSquaredLowerBound = 0.15; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; @@ -308,8 +310,8 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f, raw_delay_:%f", it->arrival_time_ms, it->smoothed_delay_ms, it->raw_delay_ms); }*/ - if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < 0.4) { - if (avg_r_squared < 0.15) { + if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { + if (avg_r_squared < kDefaultRSquaredLowerBound) { hypothesis_ = BandwidthUsage::kBwOverusing; MS_DEBUG_DEV("OverUsing!"); } else { From 6aa0b0374c39d05d2dd6ccb780006cdeaabdfbf9 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 19 Dec 2022 19:24:47 +0200 Subject: [PATCH 47/70] Add comment that explains what we are doing with R^2 --- .../congestion_controller/goog_cc/trendline_estimator.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 7371231d8e..a2ae128a59 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -306,10 +306,12 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub prev_modified_trend_ = modified_trend; // BWE_TEST_LOGGING_PLOT(1, "T", now_ms, modified_trend); // BWE_TEST_LOGGING_PLOT(1, "threshold", now_ms, threshold_); -/* for (auto it = delay_hist_.crbegin(); it != delay_hist_.crend(); ++it) { + /*for (auto it = delay_hist_.crbegin(); it != delay_hist_.crend(); ++it) { MS_DEBUG_DEV("arrival_time_ms - first_arrival_time_ms_:%f, smoothed_delay_:%f, raw_delay_:%f", it->arrival_time_ms, it->smoothed_delay_ms, it->raw_delay_ms); }*/ + // MS_NOTE: In case of positive slope we want to limit BW increase or even decrease + // in case we see that we have many outliers. if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { if (avg_r_squared < kDefaultRSquaredLowerBound) { hypothesis_ = BandwidthUsage::kBwOverusing; From 09a4b4c7c4d9a63a0bf790e0c85f1f3cfc36369d Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 19 Dec 2022 19:28:31 +0200 Subject: [PATCH 48/70] Get rid of EventEmitter. --- .../bitrate_controller/loss_based_bwe_v2.cc | 1 - .../bitrate_controller/loss_based_bwe_v2.h | 2 - .../send_side_bandwidth_estimation.cc | 4 - worker/include/EventEmitter.h | 92 ------------------- 4 files changed, 99 deletions(-) delete mode 100644 worker/include/EventEmitter.h diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index f393b5e728..3e6476faba 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -1002,7 +1002,6 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { else { current_estimate = current_estimate_.loss_limited_bandwidth; - events.emit(current_estimate_.loss_limited_bandwidth); } instant_loss_debounce_counter_ += 1; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 16749119cf..e6f9775e32 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -23,7 +23,6 @@ #include "api/units/time_delta.h" #include "api/units/timestamp.h" #include "api/transport/webrtc_key_value_config.h" -#include "EventEmitter.h" namespace webrtc { @@ -58,7 +57,6 @@ class LossBasedBweV2 { // Returns `DataRate::PlusInfinity` if no BWE can be calculated. Result GetLossBasedResult() const; - EventEmitter events; void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); void SetBandwidthEstimate(DataRate bandwidth_estimate); void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 3d86c8941c..4043e8a550 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -375,10 +375,6 @@ void SendSideBandwidthEstimation::UpdateLossBasedEstimator( report.packet_feedbacks, delay_based_limit_, delay_detector_state, probe_bitrate, upper_link_capacity); - loss_based_bandwidth_estimator_v2_.events.subscribe([&](auto &event) { - MS_DEBUG_DEV("loss bitrate %lld", event.bps()); - }); - UpdateEstimate(report.feedback_time); } } diff --git a/worker/include/EventEmitter.h b/worker/include/EventEmitter.h deleted file mode 100644 index ab67c88040..0000000000 --- a/worker/include/EventEmitter.h +++ /dev/null @@ -1,92 +0,0 @@ -// -// Created by Eugene Voityuk on 14.12.2022. -// - -#ifndef MEDIASOUP_EVENTEMITTER_H -#define MEDIASOUP_EVENTEMITTER_H -#include -#include -#include -#include -#include - -class BaseEvent { -public: - ~BaseEvent() = default; - static size_t getNextType() - { - static size_t type_count = 0; - return type_count++; - } -}; - - -template -struct Event : BaseEvent -{ - static size_t type() - { - static size_t t_type = BaseEvent::getNextType(); - return t_type; - } - Event(const EventType& event) : event(event) {} - const EventType& event; -}; - -class EventEmitter -{ -private: - template - using call_type = std::function; - -public: - template - void subscribe(const call_type callable) - { - // When events such as COLLISION don't derive - // from Event, you have to get the type by - // using one more level of indirection. - size_t type = Event::type(); - if (type >= m_subscribers.size()) - m_subscribers.resize(type+1); - m_subscribers[type].push_back(CallbackWrapper(callable)); - } - -public: - template - void emit(const EventType& event) - { - size_t type = Event::type(); - if (m_subscribers[type].empty()) - return; - if (type >= m_subscribers.size()) - m_subscribers.resize(type+1); - - Event wrappedEvent(event); - for (auto& receiver : m_subscribers[type]) - receiver(wrappedEvent); - } -private: - template - struct CallbackWrapper - { - CallbackWrapper(call_type callable) : m_callable(callable) {} - - void operator() (const BaseEvent& event) { - // The event handling code requires a small change too. - // A reference to the EventType object is stored - // in Event. You get the EventType reference from the - // Event and make the final call. - m_callable(static_cast&>(event).event); - } - - call_type m_callable; - }; -public: - void removeAllListeners() { - m_subscribers.clear(); - } -private: - std::vector>> m_subscribers; -}; -#endif // MEDIASOUP_EVENTEMITTER_H From 47657fb12adb521b6745bd4cf295fb374b024e61 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 19 Dec 2022 19:41:24 +0200 Subject: [PATCH 49/70] More C++ 14 cleanup. --- worker/.clang-format | 2 +- worker/Makefile | 2 +- worker/deps/libwebrtc/libwebrtc.gyp | 4 ++-- worker/deps/libwebrtc/meson.build | 1 - worker/scripts/cppcheck.sh | 2 +- 5 files changed, 5 insertions(+), 6 deletions(-) diff --git a/worker/.clang-format b/worker/.clang-format index b51c5cea53..e9d4091214 100644 --- a/worker/.clang-format +++ b/worker/.clang-format @@ -83,6 +83,6 @@ SpacesInCStyleCastParentheses: false SpacesInContainerLiterals: true SpacesInParentheses: false SpacesInSquareBrackets: false -Standard: c++14 +Standard: c++11 TabWidth: 2 UseTab: ForIndentation diff --git a/worker/Makefile b/worker/Makefile index de2bd0eca4..2b8a5771e0 100644 --- a/worker/Makefile +++ b/worker/Makefile @@ -229,7 +229,7 @@ tidy: $(PYTHON) ./scripts/clang-tidy.py \ -clang-tidy-binary=./scripts/node_modules/.bin/clang-tidy \ -clang-apply-replacements-binary=./scripts/node_modules/.bin/clang-apply-replacements \ - -header-filter='(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|EventEmitter.hpp|handles/**/*.hpp)' \ + -header-filter='(Channel/**/*.hpp|DepLibSRTP.hpp|DepLibUV.hpp|DepLibWebRTC.hpp|DepOpenSSL.hpp|DepUsrSCTP.hpp|LogLevel.hpp|Logger.hpp|MediaSoupError.hpp|RTC/**/*.hpp|Settings.hpp|Utils.hpp|Worker.hpp|common.hpp|handles/**/*.hpp)' \ -p=$(BUILD_DIR) \ -j=$(CORES) \ -checks=$(MEDIASOUP_TIDY_CHECKS) \ diff --git a/worker/deps/libwebrtc/libwebrtc.gyp b/worker/deps/libwebrtc/libwebrtc.gyp index aadb853f6c..eb84186549 100644 --- a/worker/deps/libwebrtc/libwebrtc.gyp +++ b/worker/deps/libwebrtc/libwebrtc.gyp @@ -143,13 +143,13 @@ # Platform-specifics. [ 'OS != "win"', { - 'cflags': [ '-std=c++14' ] + 'cflags': [ '-std=c++11' ] }], [ 'OS == "mac"', { 'xcode_settings': { - 'OTHER_CPLUSPLUSFLAGS' : [ '-std=c++14' ] + 'OTHER_CPLUSPLUSFLAGS' : [ '-std=c++11' ] } }] ] diff --git a/worker/deps/libwebrtc/meson.build b/worker/deps/libwebrtc/meson.build index 5145c9dc18..78076c8e6c 100644 --- a/worker/deps/libwebrtc/meson.build +++ b/worker/deps/libwebrtc/meson.build @@ -73,7 +73,6 @@ libwebrtc = library( libuv_proj.get_variable('libuv_dep'), ], include_directories: libwebrtc_include_directories, - override_options : ['c_std=c11', 'cpp_std=c++14'], cpp_args: cpp_args, ) diff --git a/worker/scripts/cppcheck.sh b/worker/scripts/cppcheck.sh index 99fe7082b6..14ca7d5bd6 100755 --- a/worker/scripts/cppcheck.sh +++ b/worker/scripts/cppcheck.sh @@ -30,7 +30,7 @@ XML_FILE="/tmp/mediasoup-worker-cppcheck.xml" HTML_REPORT_DIR="/tmp/mediasoup-worker-cppcheck-report" echo ">>> [INFO] running cppcheck ..." -cppcheck --std=c++14 --enable=${CPPCHECKS} -v --quiet --report-progress --inline-suppr --error-exitcode=69 -I include src --xml-version=2 2> $XML_FILE +cppcheck --std=c++11 --enable=${CPPCHECKS} -v --quiet --report-progress --inline-suppr --error-exitcode=69 -I include src --xml-version=2 2> $XML_FILE # If exit code is 1 it means that some cppcheck option is wrong, so abort. if [ $? -eq 1 ] ; then From fc46a65e48821258d01f35cdd6e3916c6531d061 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 23 Dec 2022 16:41:19 +0200 Subject: [PATCH 50/70] Backport most recent libwebrtc changes, also fix some issues iwth caching of instant loss and casting. --- node/src/Worker.ts | 2 +- rust/src/worker.rs | 2 +- .../bitrate_controller/loss_based_bwe_v2.cc | 74 ++++++--- .../bitrate_controller/loss_based_bwe_v2.h | 153 +++++++++--------- .../goog_cc/delay_based_bwe.h | 2 +- .../goog_cc/goog_cc_network_control.cc | 43 +++-- .../goog_cc/probe_controller.cc | 38 ++--- .../goog_cc/probe_controller.h | 14 +- .../goog_cc/trendline_estimator.cc | 4 +- .../aimd_rate_control.cc | 3 +- worker/include/Settings.hpp | 2 +- 11 files changed, 183 insertions(+), 154 deletions(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index f249f7a272..08bd8443e3 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -70,7 +70,7 @@ export type WorkerSettings = * * NOTE: For advanced users only. An invalid value will make the worker crash. * Default value is - * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". + * "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" */ libwebrtcFieldTrials?: string; /* eslint-enable max-len */ diff --git a/rust/src/worker.rs b/rust/src/worker.rs index df834aeff0..806dd9532f 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -186,7 +186,7 @@ pub struct WorkerSettings { /// /// NOTE: For advanced users only. An invalid value will make the worker crash. /// Default value is - /// "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,SendingRateSmoothingFactor:0.6/". + /// "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" #[doc(hidden)] pub libwebrtc_field_trials: Option, /// Function that will be called under worker thread before worker starts, can be used for diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 3e6476faba..0a9b7db5b4 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -90,10 +90,10 @@ double GetLossProbability(double inherent_loss, inherent_loss = std::min(std::max(inherent_loss, 0.0), 1.0); } if (!sending_rate.IsFinite()) { - MS_WARN_TAG(bwe, "The sending rate must be finite: %ld", sending_rate.bps()); + MS_WARN_TAG(bwe, "The sending rate must be finite: %" PRIi64 "", sending_rate.bps()); } if (!loss_limited_bandwidth.IsFinite()) { - MS_WARN_TAG(bwe, "The loss limited bandwidth must be finite: %ld", loss_limited_bandwidth.bps()); + MS_WARN_TAG(bwe, "The loss limited bandwidth must be finite: %" PRIi64 "", loss_limited_bandwidth.bps()); } double loss_probability = inherent_loss; @@ -129,16 +129,31 @@ LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) } void LossBasedBweV2::Reset() { + acknowledged_bitrate_ = absl::nullopt; + current_estimate_.inherent_loss = config_->initial_inherent_loss_estimate; current_estimate_.loss_limited_bandwidth = max_bitrate_; observations_.clear(); + temporal_weights_.clear(); + instant_upper_bound_temporal_weights_.clear(); + + observations_.resize(config_->observation_window_size); + temporal_weights_.resize(config_->observation_window_size); + instant_upper_bound_temporal_weights_.resize( + config_->observation_window_size); + + CalculateTemporalWeights(); num_observations_ = 0; + partial_observation_.num_lost_packets = 0; partial_observation_.num_packets = 0; + partial_observation_.size = DataSize::Zero(); + last_send_time_most_recent_observation_ = Timestamp::PlusInfinity(); last_time_estimate_reduced_ = Timestamp::MinusInfinity(); + cached_instant_upper_bound_ = absl::nullopt; delay_detector_states_.clear(); recovering_after_loss_timestamp_ = Timestamp::MinusInfinity(); @@ -147,6 +162,10 @@ void LossBasedBweV2::Reset() { probe_bitrate_ = DataRate::PlusInfinity(); delay_based_estimate_ = DataRate::PlusInfinity(); upper_link_capacity_ = DataRate::PlusInfinity(); + + instant_loss_debounce_counter_ = 0; + instant_loss_debounce_duration = TimeDelta::seconds(2); + instant_loss_debounce_start = Timestamp::MinusInfinity(); } bool LossBasedBweV2::IsEnabled() const { @@ -362,64 +381,64 @@ bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited( // configuration for the `LossBasedBweV2` which is explicitly enabled. absl::optional LossBasedBweV2::CreateConfig( const WebRtcKeyValueConfig* key_value_config) { - FieldTrialParameter enabled("Enabled", false); + FieldTrialParameter enabled("Enabled", true); FieldTrialParameter bandwidth_rampup_upper_bound_factor( - "BwRampupUpperBoundFactor", 1.1); + "BwRampupUpperBoundFactor", 1000000.0); FieldTrialParameter rampup_acceleration_max_factor( "BwRampupAccelMaxFactor", 0.0); FieldTrialParameter rampup_acceleration_maxout_time( "BwRampupAccelMaxoutTime", TimeDelta::seconds(60)); FieldTrialList candidate_factors("CandidateFactors", - {1.05, 1.0, 0.95}); + {1.02, 1.0, 0.95}); FieldTrialParameter higher_bandwidth_bias_factor("HigherBwBiasFactor", - 0.00001); + 0.0002); FieldTrialParameter higher_log_bandwidth_bias_factor( - "HigherLogBwBiasFactor", 0.001); + "HigherLogBwBiasFactor", 0.02); FieldTrialParameter inherent_loss_lower_bound( "InherentLossLowerBound", 1.0e-3); FieldTrialParameter loss_threshold_of_high_bandwidth_preference( - "LossThresholdOfHighBandwidthPreference", 0.99); + "LossThresholdOfHighBandwidthPreference", 0.15); FieldTrialParameter bandwidth_preference_smoothing_factor( "BandwidthPreferenceSmoothingFactor", 0.002); FieldTrialParameter inherent_loss_upper_bound_bandwidth_balance( - "InherentLossUpperBoundBwBalance", DataRate::kbps(15.0)); + "InherentLossUpperBoundBwBalance", DataRate::kbps(75.0)); FieldTrialParameter inherent_loss_upper_bound_offset( "InherentLossUpperBoundOffset", 0.05); FieldTrialParameter initial_inherent_loss_estimate( "InitialInherentLossEstimate", 0.01); FieldTrialParameter newton_iterations("NewtonIterations", 1); - FieldTrialParameter newton_step_size("NewtonStepSize", 0.5); + FieldTrialParameter newton_step_size("NewtonStepSize", 0.75); FieldTrialParameter append_acknowledged_rate_candidate( "AckedRateCandidate", true); FieldTrialParameter append_delay_based_estimate_candidate( - "DelayBasedCandidate", false); + "DelayBasedCandidate", true); FieldTrialParameter observation_duration_lower_bound( - "ObservationDurationLowerBound", TimeDelta::seconds(1)); - FieldTrialParameter observation_window_size("ObservationWindowSize", 50); + "ObservationDurationLowerBound", TimeDelta::ms(250)); + FieldTrialParameter observation_window_size("ObservationWindowSize", 20); FieldTrialParameter sending_rate_smoothing_factor( "SendingRateSmoothingFactor", 0.0); FieldTrialParameter instant_upper_bound_temporal_weight_factor( - "InstantUpperBoundTemporalWeightFactor", 0.99); + "InstantUpperBoundTemporalWeightFactor", 0.9); FieldTrialParameter instant_upper_bound_bandwidth_balance( - "InstantUpperBoundBwBalance", DataRate::kbps(15.0)); + "InstantUpperBoundBwBalance", DataRate::kbps(75.0)); FieldTrialParameter instant_upper_bound_loss_offset( "InstantUpperBoundLossOffset", 0.05); FieldTrialParameter temporal_weight_factor("TemporalWeightFactor", - 0.99); + 0.9); FieldTrialParameter bandwidth_backoff_lower_bound_factor( "BwBackoffLowerBoundFactor", 1.0); FieldTrialParameter trendline_integration_enabled( "TrendlineIntegrationEnabled", false); FieldTrialParameter trendline_observations_window_size( - "TrendlineObservationsWindowSize", 15); - FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1000.0); + "TrendlineObservationsWindowSize", 20); + FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1.3); FieldTrialParameter delayed_increase_window( "DelayedIncreaseWindow", TimeDelta::ms(300)); FieldTrialParameter use_acked_bitrate_only_when_overusing( "UseAckedBitrateOnlyWhenOverusing", false); FieldTrialParameter not_increase_if_inherent_loss_less_than_average_loss( - "NotIncreaseIfInherentLossLessThanAverageLoss", false); + "NotIncreaseIfInherentLossLessThanAverageLoss", true); FieldTrialParameter high_loss_rate_threshold("HighLossRateThreshold", 1.0); FieldTrialParameter bandwidth_cap_at_high_loss_rate( @@ -595,7 +614,7 @@ bool LossBasedBweV2::IsConfigValid() const { valid = false; } if (config_->rampup_acceleration_maxout_time <= TimeDelta::Zero()) { - MS_WARN_TAG(bwe, "The rampup acceleration maxout time must be above zero: %ld ", + MS_WARN_TAG(bwe, "The rampup acceleration maxout time must be above zero: %" PRIi64 "", config_->rampup_acceleration_maxout_time.seconds()); valid = false; } @@ -644,7 +663,7 @@ bool LossBasedBweV2::IsConfigValid() const { } if (config_->inherent_loss_upper_bound_bandwidth_balance <= DataRate::Zero()) { - MS_WARN_TAG(bwe, "The inherent loss upper bound bandwidth balance must be positive: %ld", + MS_WARN_TAG(bwe, "The inherent loss upper bound bandwidth balance must be positive: %" PRIi64 "", config_->inherent_loss_upper_bound_bandwidth_balance.bps()); valid = false; } @@ -804,6 +823,8 @@ std::vector LossBasedBweV2::GetCandidates() if (!can_increase_bitrate && candidate_factor > 1.0) { continue; } + MS_DEBUG_DEV("Pushing loss_limited_bandwidth candidate rate: %lld", (candidate_factor * + current_estimate_.loss_limited_bandwidth).bps()); bandwidths.push_back(candidate_factor * current_estimate_.loss_limited_bandwidth); } @@ -811,6 +832,7 @@ std::vector LossBasedBweV2::GetCandidates() if (acknowledged_bitrate_.has_value() && config_->append_acknowledged_rate_candidate && TrendlineEsimateAllowEmergencyBackoff()) { + MS_DEBUG_DEV("Pushing acknowledged_bitrate_ candidate rate: %lld", (*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor).bps()); bandwidths.push_back(*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor); } @@ -818,7 +840,8 @@ std::vector LossBasedBweV2::GetCandidates() if (IsValid(delay_based_estimate_) && config_->append_delay_based_estimate_candidate) { if (can_increase_bitrate && - delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) { + delay_based_estimate_ < current_estimate_.loss_limited_bandwidth) { + MS_DEBUG_DEV("Pushing delay_based_estimate_ candidate rate: %lld", delay_based_estimate_.bps()); bandwidths.push_back(delay_based_estimate_); } } @@ -839,6 +862,7 @@ std::vector LossBasedBweV2::GetCandidates() candidate_bandwidth_upper_bound)); } candidate.inherent_loss = GetFeasibleInherentLoss(candidate); + MS_DEBUG_DEV("Candidate loss_limited_bandwidth: %lld, inherent_loss: %f", candidate.loss_limited_bandwidth.bps(), candidate.inherent_loss); candidates[i] = candidate; } return candidates; @@ -1026,9 +1050,9 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { return; } - auto weight_idx = (instant_loss_debounce_counter_ < config_->observation_window_size) + auto weight_idx = (instant_loss_debounce_counter_ < static_cast(config_->observation_window_size)) ? instant_loss_debounce_counter_ - : 20; + : static_cast(20); auto reduce_factor = std::max(temporal_weights_[weight_idx], 0.75); MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), reduce_factor); @@ -1089,6 +1113,8 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { } } cached_instant_upper_bound_ = instant_limit; + } else { + cached_instant_upper_bound_ = absl::nullopt; } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index e6f9775e32..598453bcd0 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -24,15 +24,17 @@ #include "api/units/timestamp.h" #include "api/transport/webrtc_key_value_config.h" -namespace webrtc { - -// State of the loss based estimate, which can be either increasing/decreasing -// when network is loss limited, or equal to the delay based estimate. -enum class LossBasedState { - kIncreasing = 0, - kDecreasing = 1, - kDelayBasedEstimate = 2 -}; +namespace webrtc +{ + + // State of the loss based estimate, which can be either increasing/decreasing + // when network is loss limited, or equal to the delay based estimate. + enum class LossBasedState + { + kIncreasing = 0, + kDecreasing = 1, + kDelayBasedEstimate = 2 + }; class LossBasedBweV2 { public: @@ -45,72 +47,73 @@ class LossBasedBweV2 { // `key_value_config` is not valid. explicit LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config); - LossBasedBweV2(const LossBasedBweV2&) = delete; - LossBasedBweV2& operator=(const LossBasedBweV2&) = delete; - - ~LossBasedBweV2() = default; - - bool IsEnabled() const; - // Returns true iff a BWE can be calculated, i.e., the estimator has been - // initialized with a BWE and then has received enough `PacketResult`s. - bool IsReady() const; - - // Returns `DataRate::PlusInfinity` if no BWE can be calculated. - Result GetLossBasedResult() const; - void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); - void SetBandwidthEstimate(DataRate bandwidth_estimate); - void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); - void UpdateBandwidthEstimate( - std::vector packet_results, - DataRate delay_based_estimate, - BandwidthUsage delay_detector_state, - absl::optional probe_bitrate, + LossBasedBweV2(const LossBasedBweV2&) = delete; + LossBasedBweV2& operator=(const LossBasedBweV2&) = delete; + + ~LossBasedBweV2() = default; + + bool IsEnabled() const; + // Returns true iff a BWE can be calculated, i.e., the estimator has been + // initialized with a BWE and then has received enough `PacketResult`s. + bool IsReady() const; + + // Returns `DataRate::PlusInfinity` if no BWE can be calculated. + Result GetLossBasedResult() const; + void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); + void SetBandwidthEstimate(DataRate bandwidth_estimate); + void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); + void UpdateBandwidthEstimate( + std::vector packet_results, + DataRate delay_based_estimate, + BandwidthUsage delay_detector_state, + absl::optional probe_bitrate, DataRate upper_link_capacity); - private: - struct ChannelParameters { - double inherent_loss = 0.0; - DataRate loss_limited_bandwidth = DataRate::MinusInfinity(); - }; - - struct Config { - double bandwidth_rampup_upper_bound_factor = 0.0; - double rampup_acceleration_max_factor = 0.0; - TimeDelta rampup_acceleration_maxout_time = TimeDelta::Zero(); - std::vector candidate_factors; - double higher_bandwidth_bias_factor = 0.0; - double higher_log_bandwidth_bias_factor = 0.0; - double inherent_loss_lower_bound = 0.0; - double loss_threshold_of_high_bandwidth_preference = 0.0; - double bandwidth_preference_smoothing_factor = 0.0; - DataRate inherent_loss_upper_bound_bandwidth_balance = - DataRate::MinusInfinity(); - double inherent_loss_upper_bound_offset = 0.0; - double initial_inherent_loss_estimate = 0.0; - int newton_iterations = 0; - double newton_step_size = 0.0; - bool append_acknowledged_rate_candidate = true; - bool append_delay_based_estimate_candidate = false; - TimeDelta observation_duration_lower_bound = TimeDelta::Zero(); - int observation_window_size = 0; - double sending_rate_smoothing_factor = 0.0; - double instant_upper_bound_temporal_weight_factor = 0.0; - DataRate instant_upper_bound_bandwidth_balance = DataRate::MinusInfinity(); - double instant_upper_bound_loss_offset = 0.0; - double temporal_weight_factor = 0.0; - double bandwidth_backoff_lower_bound_factor = 0.0; - bool trendline_integration_enabled = false; - int trendline_observations_window_size = 0; - double max_increase_factor = 0.0; - TimeDelta delayed_increase_window = TimeDelta::Zero(); - bool use_acked_bitrate_only_when_overusing = false; - bool not_increase_if_inherent_loss_less_than_average_loss = false; - double high_loss_rate_threshold = 1.0; - DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity(); - double slope_of_bwe_high_loss_func = 1000.0; - bool probe_integration_enabled = false; - bool bound_by_upper_link_capacity_when_loss_limited = false; - }; + private: + struct ChannelParameters + { + double inherent_loss = 0.0; + DataRate loss_limited_bandwidth = DataRate::MinusInfinity(); + }; + + struct Config + { + double bandwidth_rampup_upper_bound_factor = 0.0; + double rampup_acceleration_max_factor = 0.0; + TimeDelta rampup_acceleration_maxout_time = TimeDelta::Zero(); + std::vector candidate_factors; + double higher_bandwidth_bias_factor = 0.0; + double higher_log_bandwidth_bias_factor = 0.0; + double inherent_loss_lower_bound = 0.0; + double loss_threshold_of_high_bandwidth_preference = 0.0; + double bandwidth_preference_smoothing_factor = 0.0; + DataRate inherent_loss_upper_bound_bandwidth_balance = DataRate::MinusInfinity(); + double inherent_loss_upper_bound_offset = 0.0; + double initial_inherent_loss_estimate = 0.0; + int newton_iterations = 0; + double newton_step_size = 0.0; + bool append_acknowledged_rate_candidate = true; + bool append_delay_based_estimate_candidate = false; + TimeDelta observation_duration_lower_bound = TimeDelta::Zero(); + int observation_window_size = 0; + double sending_rate_smoothing_factor = 0.0; + double instant_upper_bound_temporal_weight_factor = 0.0; + DataRate instant_upper_bound_bandwidth_balance = DataRate::MinusInfinity(); + double instant_upper_bound_loss_offset = 0.0; + double temporal_weight_factor = 0.0; + double bandwidth_backoff_lower_bound_factor = 0.0; + bool trendline_integration_enabled = false; + int trendline_observations_window_size = 0; + double max_increase_factor = 0.0; + TimeDelta delayed_increase_window = TimeDelta::Zero(); + bool use_acked_bitrate_only_when_overusing = false; + bool not_increase_if_inherent_loss_less_than_average_loss = false; + double high_loss_rate_threshold = 1.0; + DataRate bandwidth_cap_at_high_loss_rate = DataRate::MinusInfinity(); + double slope_of_bwe_high_loss_func = 1000.0; + bool probe_integration_enabled = false; + bool bound_by_upper_link_capacity_when_loss_limited = false; + }; struct Derivatives { double first = 0.0; @@ -205,6 +208,6 @@ class LossBasedBweV2 { Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); }; -} // namespace webrtc +} // namespace webrtc -#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_LOSS_BASED_BWE_V2_H_ +#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_LOSS_BASED_BWE_V2_H_ diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h index a6a2cf6936..5f6db7113f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -83,7 +83,7 @@ class DelayBasedBwe { DataRate TriggerOveruse(Timestamp at_time, absl::optional link_capacity); DataRate last_estimate() const { return prev_bitrate_; } - + BandwidthUsage last_state() const { return prev_state_; } private: friend class GoogCcStatePrinter; void IncomingPacketFeedback(const PacketResult& packet_feedback, diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index efa79878e8..6b4384e628 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -56,15 +56,22 @@ bool IsNotDisabled(const WebRtcKeyValueConfig* config, absl::string_view key) { return config->Lookup(key).find("Disabled") != 0; } BandwidthLimitedCause GetBandwidthLimitedCause( - LossBasedState loss_based_state) { - switch (loss_based_state) { - case LossBasedState::kDecreasing: - return BandwidthLimitedCause::kLossLimitedBweDecreasing; - case LossBasedState::kIncreasing: - return BandwidthLimitedCause::kLossLimitedBweIncreasing; - default: - return BandwidthLimitedCause::kDelayBasedLimited; - } + LossBasedState loss_based_state, + BandwidthUsage bandwidth_usage, + bool not_probe_if_delay_increased) { + if (not_probe_if_delay_increased && + (bandwidth_usage == BandwidthUsage::kBwOverusing || + bandwidth_usage == BandwidthUsage::kBwUnderusing)) { + return BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased; + } + switch (loss_based_state) { + case LossBasedState::kDecreasing: + return BandwidthLimitedCause::kLossLimitedBweDecreasing; + case LossBasedState::kIncreasing: + return BandwidthLimitedCause::kLossLimitedBweIncreasing; + default: + return BandwidthLimitedCause::kDelayBasedLimited; + } } } // namespace @@ -92,7 +99,7 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, new ProbeController(key_value_config_)), congestion_window_pushback_controller_( rate_control_settings_.UseCongestionWindowPushback() - ? absl::make_unique( + ? std::make_unique( key_value_config_) : nullptr), bandwidth_estimation_( @@ -544,8 +551,13 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( bool recovered_from_overuse = false; DelayBasedBwe::Result result; + // MS_NOTE: I am not sure why we are passing here acknowledged_bitrate + // instead of bandwidth_estimation_->target_rate(), because, when we are + // backing off we in AIMD we should backoff from target rate rather than + // acknowledged_bitrate, otherwise we get big BW drops, bigger that default + // AIMD 0.85 backof factor result = delay_based_bwe_->IncomingPacketFeedbackVector( - report, bandwidth_estimation_->target_rate(), probe_bitrate, estimate_, + report, acknowledged_bitrate, probe_bitrate, estimate_, alr_start_time.has_value()); if (result.updated) { @@ -683,16 +695,19 @@ void GoogCcNetworkController::MaybeTriggerOnNetworkChanged( auto probes = probe_controller_->SetEstimatedBitrate( loss_based_target_rate, - GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state()), + GetBandwidthLimitedCause( + bandwidth_estimation_->loss_based_state(), + delay_based_bwe_->last_state(), + probe_controller_->DontProbeIfDelayIncreased()), at_time); update->probe_cluster_configs.insert(update->probe_cluster_configs.end(), probes.begin(), probes.end()); update->pacer_config = GetPacingRates(at_time); - MS_DEBUG_DEV("bwe [at_time:%" PRIu64", pushback_target_bps:%lld, estimate_bps:%lld]", +/* MS_DEBUG_DEV("bwe [at_time:%" PRIu64", pushback_target_bps:%lld, estimate_bps:%lld]", at_time.ms(), last_pushback_target_rate_.bps(), - last_raw_target_rate_.bps()); + last_raw_target_rate_.bps());*/ } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index bf5faf698f..97bed651ec 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -105,7 +105,8 @@ ProbeControllerConfig::ProbeControllerConfig( loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", - 0.0) { + 0.0), + not_probe_if_delay_increased("not_probe_if_delay_increased", false) { ParseFieldTrial({&first_exponential_probe_scale, &second_exponential_probe_scale, &further_exponential_probe_scale, @@ -125,7 +126,8 @@ ProbeControllerConfig::ProbeControllerConfig( &min_probe_packets_sent, &limit_probe_target_rate_to_loss_bwe, &loss_limited_probe_scale, - &skip_if_estimate_larger_than_fraction_of_max}, + &skip_if_estimate_larger_than_fraction_of_max, + ¬_probe_if_delay_increased}, key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration")); // Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration @@ -195,17 +197,6 @@ std::vector ProbeController::SetBitrates( // estimate then initiate probing. if (!estimated_bitrate_.IsZero() && old_max_bitrate < max_bitrate_ && estimated_bitrate_ < max_bitrate_) { - // The assumption is that if we jump more than 20% in the bandwidth - // estimate or if the bandwidth estimate is within 90% of the new - // max bitrate then the probing attempt was successful. - mid_call_probing_succcess_threshold_ = - std::min(estimated_bitrate_ * 1.2, max_bitrate_ * 0.9); - mid_call_probing_waiting_for_result_ = true; - mid_call_probing_bitrate_ = max_bitrate_; - - // RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Initiated", - // max_bitrate_bps_ / 1000); - return InitiateProbing(at_time, {max_bitrate_}, false); } break; @@ -295,15 +286,6 @@ std::vector ProbeController::SetEstimatedBitrate( bitrate_before_last_large_drop_ = estimated_bitrate_; } estimated_bitrate_ = bitrate; - - if (mid_call_probing_waiting_for_result_ && - bitrate >= mid_call_probing_succcess_threshold_) { - // RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.Success", - // mid_call_probing_bitrate_bps_ / 1000); - // RTC_HISTOGRAM_COUNTS_10000("WebRTC.BWE.MidCallProbing.ProbedKbps", - // bitrate_bps / 1000); - mid_call_probing_waiting_for_result_ = false; - } if (state_ == State::kWaitingForProbingResult) { // Continue probing if probing results indicate channel has greater // capacity. @@ -408,7 +390,6 @@ void ProbeController::Reset(Timestamp at_time) { Timestamp now = at_time; last_bwe_drop_probing_time_ = now; alr_end_time_.reset(); - mid_call_probing_waiting_for_result_ = false; time_of_last_large_drop_ = now; bitrate_before_last_large_drop_ = DataRate::Zero(); max_total_allocated_bitrate_ = DataRate::Zero(); @@ -459,8 +440,6 @@ bool ProbeController::TimeForNetworkStateProbe(Timestamp at_time) const { std::vector ProbeController::Process(Timestamp at_time) { if (at_time - time_last_probing_initiated_ > kMaxWaitingTimeForProbingResult) { - mid_call_probing_waiting_for_result_ = false; - if (state_ == State::kWaitingForProbingResult) { MS_WARN_TAG(bwe, "kWaitingForProbingResult: timeout"); state_ = State::kProbingComplete; @@ -476,7 +455,6 @@ std::vector ProbeController::Process(Timestamp at_time) { } return std::vector(); } - std::vector ProbeController::InitiateProbing( Timestamp now, std::vector bitrates_to_probe, @@ -496,7 +474,6 @@ std::vector ProbeController::InitiateProbing( return {}; } } - DataRate max_probe_bitrate = max_bitrate_; if (max_total_allocated_bitrate_ > DataRate::Zero()) { // If a max allocated bitrate has been configured, allow probing up to 2x @@ -523,8 +500,15 @@ std::vector ProbeController::InitiateProbing( break; case BandwidthLimitedCause::kDelayBasedLimited: break; + default: + break; } } + if (config_.not_probe_if_delay_increased && + bandwidth_limited_cause_ == + BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased) { + return {}; + } if (config_.network_state_estimate_probing_interval->IsFinite() && network_estimate_ && network_estimate_->link_capacity_upper.IsFinite()) { if (network_estimate_->link_capacity_upper.IsZero()) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h index 6cdc70c832..8502ea6b24 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.h @@ -74,6 +74,8 @@ struct ProbeControllerConfig { // Dont send a probe if min(estimate, network state estimate) is larger than // this fraction of the set max bitrate. FieldTrialParameter skip_if_estimate_larger_than_fraction_of_max; + // Do not send probes if network is either overusing or underusing. + FieldTrialParameter not_probe_if_delay_increased; }; // Reason that bandwidth estimate is limited. Bandwidth estimate can be limited @@ -82,7 +84,8 @@ struct ProbeControllerConfig { enum class BandwidthLimitedCause { kLossLimitedBweIncreasing = 0, kLossLimitedBweDecreasing = 1, - kDelayBasedLimited = 2 + kDelayBasedLimited = 2, + kDelayBasedLimitedDelayIncreased = 3, }; // This class controls initiation of probing to estimate initial channel @@ -132,7 +135,10 @@ class ProbeController { ABSL_MUST_USE_RESULT std::vector Process( Timestamp at_time); - + // Gets the value of field trial not_probe_if_delay_increased. + bool DontProbeIfDelayIncreased() { + return config_.not_probe_if_delay_increased; + } private: enum class State { // Initial state where no probing has been triggered yet. @@ -171,10 +177,6 @@ class ProbeController { DataRate max_total_allocated_bitrate_ = DataRate::Zero(); const bool in_rapid_recovery_experiment_; - // For WebRTC.BWE.MidCallProbing.* metric. - bool mid_call_probing_waiting_for_result_; - DataRate mid_call_probing_bitrate_ = DataRate::Zero(); - DataRate mid_call_probing_succcess_threshold_ = DataRate::Zero(); // RtcEventLog* event_log_; int32_t next_probe_cluster_id_ = 1; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index a2ae128a59..c7d90fef89 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -30,8 +30,8 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.4; -constexpr double kDefaultRSquaredLowerBound = 0.15; +constexpr double kDefaultRSquaredUpperBound = 0.3; +constexpr double kDefaultRSquaredLowerBound = 0.05; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index 54667a4871..a07b177410 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -389,8 +389,7 @@ DataRate AimdRateControl::ClampBitrate(DataRate new_bitrate) const { } new_bitrate = std::min(upper_bound, new_bitrate); } - if (estimate_bounded_backoff_ && network_estimate_ && - network_estimate_->link_capacity_lower.IsFinite() && + if (network_estimate_ && network_estimate_->link_capacity_lower.IsFinite() && new_bitrate < current_bitrate_) { new_bitrate = std::min( current_bitrate_, diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index 16745e7617..db287ccfdc 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/Enabled:true,CandidateFactors:1.02|1.0|0.95,DelayBasedCandidate:true,HigherBwBiasFactor:0.0002,HigherLogBwBiasFactor:0.02,ObservationDurationLowerBound:250ms,InstantUpperBoundBwBalance:75kbps,BwRampupUpperBoundFactor:1000000.0,InstantUpperBoundTemporalWeightFactor:0.9,TemporalWeightFactor:0.9,MaxIncreaseFactor:1.3,NewtonStepSize:0.75,InherentLossUpperBoundBwBalance:75kbps,LossThresholdOfHighBandwidthPreference:0.15,NotIncreaseIfInherentLossLessThanAverageLoss:true,TrendlineIntegrationEnabled:true,TrendlineObservationsWindowSize:2,SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" + "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" }; }; From a040b276d7b6f4836d5e6bd3061807bfdc0cf868 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Fri, 23 Dec 2022 16:47:13 +0200 Subject: [PATCH 51/70] fix std -> absl --- .../congestion_controller/goog_cc/goog_cc_network_control.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 6b4384e628..1d3e5ea659 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -99,7 +99,7 @@ GoogCcNetworkController::GoogCcNetworkController(NetworkControllerConfig config, new ProbeController(key_value_config_)), congestion_window_pushback_controller_( rate_control_settings_.UseCongestionWindowPushback() - ? std::make_unique( + ? absl::make_unique( key_value_config_) : nullptr), bandwidth_estimation_( From 9f4093ce26dd122fc9e0bba7ef542e05a6f0a16b Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 26 Dec 2022 14:46:37 +0200 Subject: [PATCH 52/70] Be more resilient to bursts fixes here and there. --- .../bitrate_controller/loss_based_bwe_v2.cc | 162 ++++++++---------- .../bitrate_controller/loss_based_bwe_v2.h | 2 +- .../goog_cc/delay_based_bwe.cc | 6 +- .../goog_cc/trendline_estimator.cc | 20 ++- worker/include/Settings.hpp | 2 +- 5 files changed, 90 insertions(+), 102 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 0a9b7db5b4..d05f4a727a 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -124,7 +124,6 @@ LossBasedBweV2::LossBasedBweV2(const WebRtcKeyValueConfig* key_value_config) temporal_weights_.resize(config_->observation_window_size); instant_upper_bound_temporal_weights_.resize( config_->observation_window_size); - //instant_loos_debounce_duration = (config_->observation_window_size / 2) * config_->observation_duration_lower_bound; CalculateTemporalWeights(); } @@ -199,11 +198,13 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { } auto instant_limit = GetInstantUpperBound(); -/* MS_DEBUG_DEV("Using %s, Inherent Loss limit %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 "", + MS_DEBUG_DEV("Using %s, Inherent Loss limit %f, %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 ", acknowledged bitrate %" PRIi64 "", current_estimate_.loss_limited_bandwidth.bps() <= delay_based_estimate_.bps() ? "Loss" : "Delay", + current_estimate_.inherent_loss, current_estimate_.loss_limited_bandwidth.bps(), delay_based_estimate_.IsFinite() ? delay_based_estimate_.bps() : 0, - instant_limit.IsFinite() ? instant_limit.bps() : 0);*/ + instant_limit.IsFinite() ? instant_limit.bps() : 0, + IsValid(acknowledged_bitrate_) ? acknowledged_bitrate_->bps() : -1); if (IsValid(delay_based_estimate_)) { result.bandwidth_estimate = std::min({current_estimate_.loss_limited_bandwidth, @@ -249,6 +250,7 @@ void LossBasedBweV2::SetMinMaxBitrate(DataRate min_bitrate, void LossBasedBweV2::SetProbeBitrate(absl::optional probe_bitrate) { if (probe_bitrate.has_value() && IsValid(probe_bitrate.value())) { if (!IsValid(probe_bitrate_) || probe_bitrate_ > probe_bitrate.value()) { + MS_DEBUG_DEV("Probe bitrate = %lld", probe_bitrate.value().bps()); probe_bitrate_ = probe_bitrate.value(); } } @@ -307,6 +309,10 @@ void LossBasedBweV2::UpdateBandwidthEstimate( current_estimate_.loss_limited_bandwidth; } + if (IsValid(delay_based_estimate_) && current_estimate_.inherent_loss > config_->inherent_loss_upper_bound_offset) { + best_candidate.loss_limited_bandwidth = delay_based_estimate_; + } + if (IsBandwidthLimitedDueToLoss()) { // Bound the estimate increase if: // 1. The estimate has been increased for less than @@ -368,87 +374,65 @@ void LossBasedBweV2::UpdateBandwidthEstimate( } bool LossBasedBweV2::IsEstimateIncreasingWhenLossLimited( - const ChannelParameters& best_candidate) { - return (current_estimate_.loss_limited_bandwidth < - best_candidate.loss_limited_bandwidth || - (current_estimate_.loss_limited_bandwidth == - best_candidate.loss_limited_bandwidth && - current_state_ == LossBasedState::kIncreasing)) && - IsBandwidthLimitedDueToLoss(); + const ChannelParameters& best_candidate) +{ + return (current_estimate_.loss_limited_bandwidth < best_candidate.loss_limited_bandwidth || + (current_estimate_.loss_limited_bandwidth == best_candidate.loss_limited_bandwidth && + current_state_ == LossBasedState::kIncreasing)) && + IsBandwidthLimitedDueToLoss(); } - // Returns a `LossBasedBweV2::Config` iff the `key_value_config` specifies a // configuration for the `LossBasedBweV2` which is explicitly enabled. absl::optional LossBasedBweV2::CreateConfig( - const WebRtcKeyValueConfig* key_value_config) { - FieldTrialParameter enabled("Enabled", true); - FieldTrialParameter bandwidth_rampup_upper_bound_factor( - "BwRampupUpperBoundFactor", 1000000.0); - FieldTrialParameter rampup_acceleration_max_factor( - "BwRampupAccelMaxFactor", 0.0); - FieldTrialParameter rampup_acceleration_maxout_time( - "BwRampupAccelMaxoutTime", TimeDelta::seconds(60)); - FieldTrialList candidate_factors("CandidateFactors", - {1.02, 1.0, 0.95}); - FieldTrialParameter higher_bandwidth_bias_factor("HigherBwBiasFactor", - 0.0002); - FieldTrialParameter higher_log_bandwidth_bias_factor( - "HigherLogBwBiasFactor", 0.02); - FieldTrialParameter inherent_loss_lower_bound( - "InherentLossLowerBound", 1.0e-3); - FieldTrialParameter loss_threshold_of_high_bandwidth_preference( - "LossThresholdOfHighBandwidthPreference", 0.15); - FieldTrialParameter bandwidth_preference_smoothing_factor( - "BandwidthPreferenceSmoothingFactor", 0.002); - FieldTrialParameter inherent_loss_upper_bound_bandwidth_balance( - "InherentLossUpperBoundBwBalance", DataRate::kbps(75.0)); - FieldTrialParameter inherent_loss_upper_bound_offset( - "InherentLossUpperBoundOffset", 0.05); - FieldTrialParameter initial_inherent_loss_estimate( - "InitialInherentLossEstimate", 0.01); - FieldTrialParameter newton_iterations("NewtonIterations", 1); - FieldTrialParameter newton_step_size("NewtonStepSize", 0.75); - FieldTrialParameter append_acknowledged_rate_candidate( - "AckedRateCandidate", true); - FieldTrialParameter append_delay_based_estimate_candidate( - "DelayBasedCandidate", true); - FieldTrialParameter observation_duration_lower_bound( - "ObservationDurationLowerBound", TimeDelta::ms(250)); - FieldTrialParameter observation_window_size("ObservationWindowSize", 20); - FieldTrialParameter sending_rate_smoothing_factor( - "SendingRateSmoothingFactor", 0.0); - FieldTrialParameter instant_upper_bound_temporal_weight_factor( - "InstantUpperBoundTemporalWeightFactor", 0.9); - FieldTrialParameter instant_upper_bound_bandwidth_balance( - "InstantUpperBoundBwBalance", DataRate::kbps(75.0)); - FieldTrialParameter instant_upper_bound_loss_offset( - "InstantUpperBoundLossOffset", 0.05); - FieldTrialParameter temporal_weight_factor("TemporalWeightFactor", - 0.9); - FieldTrialParameter bandwidth_backoff_lower_bound_factor( - "BwBackoffLowerBoundFactor", 1.0); - FieldTrialParameter trendline_integration_enabled( - "TrendlineIntegrationEnabled", false); - FieldTrialParameter trendline_observations_window_size( - "TrendlineObservationsWindowSize", 20); - FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1.3); - FieldTrialParameter delayed_increase_window( - "DelayedIncreaseWindow", TimeDelta::ms(300)); - FieldTrialParameter use_acked_bitrate_only_when_overusing( - "UseAckedBitrateOnlyWhenOverusing", false); - FieldTrialParameter - not_increase_if_inherent_loss_less_than_average_loss( - "NotIncreaseIfInherentLossLessThanAverageLoss", true); - FieldTrialParameter high_loss_rate_threshold("HighLossRateThreshold", - 1.0); - FieldTrialParameter bandwidth_cap_at_high_loss_rate( - "BandwidthCapAtHighLossRate", DataRate::kbps(500.0)); - FieldTrialParameter slope_of_bwe_high_loss_func( - "SlopeOfBweHighLossFunc", 1000); - FieldTrialParameter probe_integration_enabled("ProbeIntegrationEnabled", - false); - FieldTrialParameter bound_by_upper_link_capacity_when_loss_limited( - "BoundByUpperLinkCapacityWhenLossLimited", true); + const WebRtcKeyValueConfig* key_value_config) +{ + FieldTrialParameter enabled("Enabled", true); + FieldTrialParameter bandwidth_rampup_upper_bound_factor( + "BwRampupUpperBoundFactor", 1000000.0); + FieldTrialParameter rampup_acceleration_max_factor("BwRampupAccelMaxFactor", 0.0); + FieldTrialParameter rampup_acceleration_maxout_time("BwRampupAccelMaxoutTime", TimeDelta::seconds(60)); + FieldTrialList candidate_factors("CandidateFactors", { 1.02, 1.0, 0.95 }); + FieldTrialParameter higher_bandwidth_bias_factor("HigherBwBiasFactor", 0.0002); + FieldTrialParameter higher_log_bandwidth_bias_factor("HigherLogBwBiasFactor", 0.02); + FieldTrialParameter inherent_loss_lower_bound("InherentLossLowerBound", 1.0e-3); + FieldTrialParameter loss_threshold_of_high_bandwidth_preference( + "LossThresholdOfHighBandwidthPreference", 0.15); + FieldTrialParameter bandwidth_preference_smoothing_factor( + "BandwidthPreferenceSmoothingFactor", 0.002); + FieldTrialParameter inherent_loss_upper_bound_bandwidth_balance( + "InherentLossUpperBoundBwBalance", DataRate::kbps(75.0)); + FieldTrialParameter inherent_loss_upper_bound_offset("InherentLossUpperBoundOffset", 0.05); + FieldTrialParameter initial_inherent_loss_estimate("InitialInherentLossEstimate", 0.01); + FieldTrialParameter newton_iterations("NewtonIterations", 1); + FieldTrialParameter newton_step_size("NewtonStepSize", 0.75); + FieldTrialParameter append_acknowledged_rate_candidate("AckedRateCandidate", true); + FieldTrialParameter append_delay_based_estimate_candidate("DelayBasedCandidate", true); + FieldTrialParameter observation_duration_lower_bound( + "ObservationDurationLowerBound", TimeDelta::ms(250)); + FieldTrialParameter observation_window_size("ObservationWindowSize", 20); + FieldTrialParameter sending_rate_smoothing_factor("SendingRateSmoothingFactor", 0.0); + FieldTrialParameter instant_upper_bound_temporal_weight_factor( + "InstantUpperBoundTemporalWeightFactor", 0.9); + FieldTrialParameter instant_upper_bound_bandwidth_balance( + "InstantUpperBoundBwBalance", DataRate::kbps(75.0)); + FieldTrialParameter instant_upper_bound_loss_offset("InstantUpperBoundLossOffset", 0.05); + FieldTrialParameter temporal_weight_factor("TemporalWeightFactor", 0.9); + FieldTrialParameter bandwidth_backoff_lower_bound_factor("BwBackoffLowerBoundFactor", 1.0); + FieldTrialParameter trendline_integration_enabled("TrendlineIntegrationEnabled", false); + FieldTrialParameter trendline_observations_window_size("TrendlineObservationsWindowSize", 20); + FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1.3); + FieldTrialParameter delayed_increase_window("DelayedIncreaseWindow", TimeDelta::ms(300)); + FieldTrialParameter use_acked_bitrate_only_when_overusing( + "UseAckedBitrateOnlyWhenOverusing", false); + FieldTrialParameter not_increase_if_inherent_loss_less_than_average_loss( + "NotIncreaseIfInherentLossLessThanAverageLoss", true); + FieldTrialParameter high_loss_rate_threshold("HighLossRateThreshold", 1.0); + FieldTrialParameter bandwidth_cap_at_high_loss_rate( + "BandwidthCapAtHighLossRate", DataRate::kbps(500.0)); + FieldTrialParameter slope_of_bwe_high_loss_func("SlopeOfBweHighLossFunc", 1000); + FieldTrialParameter probe_integration_enabled("ProbeIntegrationEnabled", false); + FieldTrialParameter bound_by_upper_link_capacity_when_loss_limited( + "BoundByUpperLinkCapacityWhenLossLimited", true); if (key_value_config) { ParseFieldTrial({&enabled, &bandwidth_rampup_upper_bound_factor, @@ -823,8 +807,7 @@ std::vector LossBasedBweV2::GetCandidates() if (!can_increase_bitrate && candidate_factor > 1.0) { continue; } - MS_DEBUG_DEV("Pushing loss_limited_bandwidth candidate rate: %lld", (candidate_factor * - current_estimate_.loss_limited_bandwidth).bps()); + MS_DEBUG_DEV("Pushing loss_limited_bandwidth candidate rate: %lld", (candidate_factor * current_estimate_.loss_limited_bandwidth).bps()); bandwidths.push_back(candidate_factor * current_estimate_.loss_limited_bandwidth); } @@ -840,7 +823,7 @@ std::vector LossBasedBweV2::GetCandidates() if (IsValid(delay_based_estimate_) && config_->append_delay_based_estimate_candidate) { if (can_increase_bitrate && - delay_based_estimate_ < current_estimate_.loss_limited_bandwidth) { + delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) { MS_DEBUG_DEV("Pushing delay_based_estimate_ candidate rate: %lld", delay_based_estimate_.bps()); bandwidths.push_back(delay_based_estimate_); } @@ -862,7 +845,6 @@ std::vector LossBasedBweV2::GetCandidates() candidate_bandwidth_upper_bound)); } candidate.inherent_loss = GetFeasibleInherentLoss(candidate); - MS_DEBUG_DEV("Candidate loss_limited_bandwidth: %lld, inherent_loss: %f", candidate.loss_limited_bandwidth.bps(), candidate.inherent_loss); candidates[i] = candidate; } return candidates; @@ -1029,7 +1011,7 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { } instant_loss_debounce_counter_ += 1; - auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 4); + auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 10); // MS_NOTE: Here we create debounce mechanism, that must help in // bursts smoothening. Initially we reduce to 85% of previous BW estimate, // if that will not help after debounce counter, we will reduce further with f @@ -1050,10 +1032,8 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { return; } - auto weight_idx = (instant_loss_debounce_counter_ < static_cast(config_->observation_window_size)) - ? instant_loss_debounce_counter_ - : static_cast(20); - auto reduce_factor = std::max(temporal_weights_[weight_idx], 0.75); + float reduce_factor = 0.9; + MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), reduce_factor); @@ -1112,10 +1092,8 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { instant_limit = std::min(instant_limit, upper_link_capacity_); } } - cached_instant_upper_bound_ = instant_limit; - } else { - cached_instant_upper_bound_ = absl::nullopt; } + cached_instant_upper_bound_ = instant_limit; } void LossBasedBweV2::CalculateTemporalWeights() { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 598453bcd0..9c418d80a2 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -204,7 +204,7 @@ class LossBasedBweV2 { double static constexpr kBwBalanceMultiplicator = 1.3; double static constexpr kInstantLossDebounce = 3; size_t instant_loss_debounce_counter_ = 0; - TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(2); + TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(5); Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc index 413cbab96f..9941a55f0f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -201,7 +201,9 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( rate_control_.TimeToReduceFurther(at_time, *acked_bitrate)) { result.updated = UpdateEstimate(at_time, acked_bitrate, &result.target_bitrate); - } else if (!acked_bitrate && rate_control_.ValidEstimate() && + } + // MS_NOTE: This is the job of loss estimator + /*else if (!acked_bitrate && rate_control_.ValidEstimate() && rate_control_.InitialTimeToReduceFurther(at_time)) { // Overusing before we have a measured acknowledged bitrate. Reduce send // rate by 50% every 200 ms. @@ -212,7 +214,7 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate( result.updated = true; result.probe = false; result.target_bitrate = rate_control_.LatestEstimate(); - } + }*/ } else { if (probe_bitrate) { MS_DEBUG_DEV("probe bitrate: %lld", probe_bitrate.value().bps()); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index c7d90fef89..934387ff72 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -30,8 +30,8 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.3; -constexpr double kDefaultRSquaredLowerBound = 0.05; +constexpr double kDefaultRSquaredUpperBound = 0.2; +constexpr double kDefaultRSquaredLowerBound = 0.1; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; @@ -312,7 +312,7 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub // MS_NOTE: In case of positive slope we want to limit BW increase or even decrease // in case we see that we have many outliers. - if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { +/* if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { if (avg_r_squared < kDefaultRSquaredLowerBound) { hypothesis_ = BandwidthUsage::kBwOverusing; MS_DEBUG_DEV("OverUsing!"); @@ -325,7 +325,15 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub UpdateThreshold(modified_trend, now_ms); return; - } + }*/ +/* if (avg_r_squared < kDefaultRSquaredLowerBound) { + hypothesis_ = BandwidthUsage::kBwOverusing; + MS_DEBUG_DEV("OverUsing!"); + prev_trend_ = trend; + UpdateThreshold(modified_trend, now_ms); + return ; + }*/ + if (modified_trend > threshold_) { if (time_over_using_ == -1) { @@ -338,8 +346,8 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub time_over_using_ += ts_delta; } overuse_counter_++; - //if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) { - if (time_over_using_ > overusing_time_threshold_) { + if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) { + //if (time_over_using_ > overusing_time_threshold_) { if (trend.slope >= prev_trend_.slope) { time_over_using_ = 0; overuse_counter_ = 0; diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index db287ccfdc..a3196443fc 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1,InstantUpperBoundLossOffset:0.08/" }; }; From 91b6923baef982eea7e16628338bd4b6eaba9103 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 26 Dec 2022 17:23:23 +0200 Subject: [PATCH 53/70] Be more resilient to bursts fixes here and there. --- .../bitrate_controller/loss_based_bwe_v2.cc | 14 ++++++++------ worker/include/Settings.hpp | 2 +- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index d05f4a727a..02f52386f6 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -8,7 +8,7 @@ * be found in the AUTHORS file in the root of the source tree. */ #define MS_CLASS "webrtc::LossBasedBweV2" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/bitrate_controller/loss_based_bwe_v2.h" @@ -198,13 +198,14 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { } auto instant_limit = GetInstantUpperBound(); - MS_DEBUG_DEV("Using %s, Inherent Loss limit %f, %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 ", acknowledged bitrate %" PRIi64 "", +/* MS_DEBUG_DEV("Using %s, Inherent Loss limit %f, %" PRIi64 ", Delay limit %" PRIi64 ", Instant Loss limit %" PRIi64 ",average loss ratio is %f, acknowledged bitrate %" PRIi64 "", current_estimate_.loss_limited_bandwidth.bps() <= delay_based_estimate_.bps() ? "Loss" : "Delay", current_estimate_.inherent_loss, current_estimate_.loss_limited_bandwidth.bps(), delay_based_estimate_.IsFinite() ? delay_based_estimate_.bps() : 0, instant_limit.IsFinite() ? instant_limit.bps() : 0, - IsValid(acknowledged_bitrate_) ? acknowledged_bitrate_->bps() : -1); + GetAverageReportedLossRatio(), + IsValid(acknowledged_bitrate_) ? acknowledged_bitrate_->bps() : -1);*/ if (IsValid(delay_based_estimate_)) { result.bandwidth_estimate = std::min({current_estimate_.loss_limited_bandwidth, @@ -807,7 +808,7 @@ std::vector LossBasedBweV2::GetCandidates() if (!can_increase_bitrate && candidate_factor > 1.0) { continue; } - MS_DEBUG_DEV("Pushing loss_limited_bandwidth candidate rate: %lld", (candidate_factor * current_estimate_.loss_limited_bandwidth).bps()); + //MS_DEBUG_DEV("Pushing loss_limited_bandwidth candidate rate: %lld", (candidate_factor * current_estimate_.loss_limited_bandwidth).bps()); bandwidths.push_back(candidate_factor * current_estimate_.loss_limited_bandwidth); } @@ -815,7 +816,7 @@ std::vector LossBasedBweV2::GetCandidates() if (acknowledged_bitrate_.has_value() && config_->append_acknowledged_rate_candidate && TrendlineEsimateAllowEmergencyBackoff()) { - MS_DEBUG_DEV("Pushing acknowledged_bitrate_ candidate rate: %lld", (*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor).bps()); + // MS_DEBUG_DEV("Pushing acknowledged_bitrate_ candidate rate: %lld", (*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor).bps()); bandwidths.push_back(*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor); } @@ -824,7 +825,7 @@ std::vector LossBasedBweV2::GetCandidates() config_->append_delay_based_estimate_candidate) { if (can_increase_bitrate && delay_based_estimate_ > current_estimate_.loss_limited_bandwidth) { - MS_DEBUG_DEV("Pushing delay_based_estimate_ candidate rate: %lld", delay_based_estimate_.bps()); + // MS_DEBUG_DEV("Pushing delay_based_estimate_ candidate rate: %lld", delay_based_estimate_.bps()); bandwidths.push_back(delay_based_estimate_); } } @@ -845,6 +846,7 @@ std::vector LossBasedBweV2::GetCandidates() candidate_bandwidth_upper_bound)); } candidate.inherent_loss = GetFeasibleInherentLoss(candidate); + // MS_DEBUG_DEV("candidate.loss_limited_bandwidth: %lld, candidate.inherent_loss: %f", candidate.loss_limited_bandwidth.bps(), candidate.inherent_loss); candidates[i] = candidate; } return candidates; diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index a3196443fc..1e617a009b 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1,InstantUpperBoundLossOffset:0.08/" + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1/" }; }; From a61ea7db85727d46c78c404cc20a620d33a4579d Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 2 Jan 2023 23:10:20 +0200 Subject: [PATCH 54/70] Reduce trendline window size to faster react to changes, push only values from positive slope to r_squared_histogram, cap loss limited bitrate at first instant loss, adjust some coefficients, enable trendline integration into loss estimator back. --- .../bitrate_controller/loss_based_bwe_v2.cc | 35 +++++++++---------- .../bitrate_controller/loss_based_bwe_v2.h | 1 + .../goog_cc/trendline_estimator.cc | 25 ++++++------- .../goog_cc/trendline_estimator.h | 2 +- worker/include/Settings.hpp | 2 +- 5 files changed, 30 insertions(+), 35 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 02f52386f6..dc189c73d8 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -402,7 +402,7 @@ absl::optional LossBasedBweV2::CreateConfig( "BandwidthPreferenceSmoothingFactor", 0.002); FieldTrialParameter inherent_loss_upper_bound_bandwidth_balance( "InherentLossUpperBoundBwBalance", DataRate::kbps(75.0)); - FieldTrialParameter inherent_loss_upper_bound_offset("InherentLossUpperBoundOffset", 0.05); + FieldTrialParameter inherent_loss_upper_bound_offset("InherentLossUpperBoundOffset", 0.03); FieldTrialParameter initial_inherent_loss_estimate("InitialInherentLossEstimate", 0.01); FieldTrialParameter newton_iterations("NewtonIterations", 1); FieldTrialParameter newton_step_size("NewtonStepSize", 0.75); @@ -416,11 +416,11 @@ absl::optional LossBasedBweV2::CreateConfig( "InstantUpperBoundTemporalWeightFactor", 0.9); FieldTrialParameter instant_upper_bound_bandwidth_balance( "InstantUpperBoundBwBalance", DataRate::kbps(75.0)); - FieldTrialParameter instant_upper_bound_loss_offset("InstantUpperBoundLossOffset", 0.05); + FieldTrialParameter instant_upper_bound_loss_offset("InstantUpperBoundLossOffset", 0.07); FieldTrialParameter temporal_weight_factor("TemporalWeightFactor", 0.9); FieldTrialParameter bandwidth_backoff_lower_bound_factor("BwBackoffLowerBoundFactor", 1.0); FieldTrialParameter trendline_integration_enabled("TrendlineIntegrationEnabled", false); - FieldTrialParameter trendline_observations_window_size("TrendlineObservationsWindowSize", 20); + FieldTrialParameter trendline_observations_window_size("TrendlineObservationsWindowSize", 5); FieldTrialParameter max_increase_factor("MaxIncreaseFactor", 1.3); FieldTrialParameter delayed_increase_window("DelayedIncreaseWindow", TimeDelta::ms(300)); FieldTrialParameter use_acked_bitrate_only_when_overusing( @@ -1001,19 +1001,10 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { average_reported_loss_ratio, config_->instant_upper_bound_loss_offset); - DataRate current_estimate = DataRate::MinusInfinity(); - if (IsValid(delay_based_estimate_)) - { - current_estimate = - std::min({ current_estimate_.loss_limited_bandwidth, delay_based_estimate_ }); - } - else - { - current_estimate = current_estimate_.loss_limited_bandwidth; - } + DataRate current_estimate = current_estimate_.loss_limited_bandwidth; instant_loss_debounce_counter_ += 1; - auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 10); + auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 15); // MS_NOTE: Here we create debounce mechanism, that must help in // bursts smoothening. Initially we reduce to 85% of previous BW estimate, // if that will not help after debounce counter, we will reduce further with f @@ -1023,6 +1014,15 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { { instant_loss_debounce_start = now; MS_DEBUG_DEV("First Instant Loss"); + + MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), kInstantLossReduceFactor); + + cached_instant_upper_bound_ = current_estimate * kInstantLossReduceFactor; + + current_estimate_.loss_limited_bandwidth = cached_instant_upper_bound_.value(); + + MS_DEBUG_DEV("cached_instant_upper_bound_ %lld", cached_instant_upper_bound_->bps()); + return ; } if ((now - instant_loss_debounce_start) < reduce_debounce_time && instant_loss_debounce_counter_ > 1) @@ -1034,12 +1034,11 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { return; } - float reduce_factor = 0.9; - + MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), kInstantLossReduceFactor); - MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), reduce_factor); + cached_instant_upper_bound_ = current_estimate * kInstantLossReduceFactor; - cached_instant_upper_bound_ = current_estimate * reduce_factor; + current_estimate_.loss_limited_bandwidth = cached_instant_upper_bound_.value(); MS_DEBUG_DEV("cached_instant_upper_bound_ %lld", cached_instant_upper_bound_->bps()); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 9c418d80a2..bd917fe544 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -206,6 +206,7 @@ class LossBasedBweV2 { size_t instant_loss_debounce_counter_ = 0; TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(5); Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); + float kInstantLossReduceFactor = 0.9; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 934387ff72..bf3f8923c7 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -29,9 +29,9 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; -constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.2; -constexpr double kDefaultRSquaredLowerBound = 0.1; +constexpr double kDefaultTrendlineThresholdGain = 5.0; +constexpr double kDefaultRSquaredUpperBound = 0.1; +constexpr double kDefaultRSquaredLowerBound = 0.01; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; @@ -255,9 +255,11 @@ void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, // trend == 0 -> the delay does not change // trend < 0 -> the delay decreases, queues are being emptied result = LinearFitSlope(delay_hist_).value_or(trend); - r_squared_hist_.emplace_back(result.r_squared); - if (r_squared_hist_.size() > settings_.window_size) - r_squared_hist_.pop_front(); + if (result.slope > 0) { + r_squared_hist_.emplace_back(result.r_squared); + if (r_squared_hist_.size() > settings_.window_size) + r_squared_hist_.pop_front(); + } avg_r_squared = getAverage(r_squared_hist_); if (settings_.enable_cap) { absl::optional cap = ComputeSlopeCap(delay_hist_, settings_); @@ -312,7 +314,7 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub // MS_NOTE: In case of positive slope we want to limit BW increase or even decrease // in case we see that we have many outliers. -/* if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { + if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { if (avg_r_squared < kDefaultRSquaredLowerBound) { hypothesis_ = BandwidthUsage::kBwOverusing; MS_DEBUG_DEV("OverUsing!"); @@ -325,14 +327,7 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub UpdateThreshold(modified_trend, now_ms); return; - }*/ -/* if (avg_r_squared < kDefaultRSquaredLowerBound) { - hypothesis_ = BandwidthUsage::kBwOverusing; - MS_DEBUG_DEV("OverUsing!"); - prev_trend_ = trend; - UpdateThreshold(modified_trend, now_ms); - return ; - }*/ + } if (modified_trend > threshold_) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index 5adc009e68..21b3d42595 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -26,7 +26,7 @@ namespace webrtc { struct TrendlineEstimatorSettings { static constexpr char kKey[] = "WebRTC-Bwe-TrendlineEstimatorSettings"; - static constexpr unsigned kDefaultTrendlineWindowSize = 20; + static constexpr unsigned kDefaultTrendlineWindowSize = 10; TrendlineEstimatorSettings() = delete; explicit TrendlineEstimatorSettings(const WebRtcKeyValueConfig* key_value_config); diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index 1e617a009b..00f32ea206 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1/" + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1,TrendlineIntegrationEnabled:true/" }; }; From 97d61ce2d75f71ec5bf0041c67a3c6947f2f5492 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 3 Jan 2023 00:49:48 +0200 Subject: [PATCH 55/70] Adjust coefficients, enable robust estimator as acknowledged estimator by defaullt, increase overuse counter, pass target bitrate instead of acknowledged to delay based estimator, to have proper backoff --- .../bitrate_controller/loss_based_bwe_v2.cc | 8 ++++---- .../acknowledged_bitrate_estimator_interface.h | 4 ++-- .../goog_cc/goog_cc_network_control.cc | 2 +- .../goog_cc/trendline_estimator.cc | 14 ++++++++------ worker/include/Settings.hpp | 2 +- 5 files changed, 16 insertions(+), 14 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index dc189c73d8..9396d2d75e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -410,7 +410,7 @@ absl::optional LossBasedBweV2::CreateConfig( FieldTrialParameter append_delay_based_estimate_candidate("DelayBasedCandidate", true); FieldTrialParameter observation_duration_lower_bound( "ObservationDurationLowerBound", TimeDelta::ms(250)); - FieldTrialParameter observation_window_size("ObservationWindowSize", 20); + FieldTrialParameter observation_window_size("ObservationWindowSize", 50); FieldTrialParameter sending_rate_smoothing_factor("SendingRateSmoothingFactor", 0.0); FieldTrialParameter instant_upper_bound_temporal_weight_factor( "InstantUpperBoundTemporalWeightFactor", 0.9); @@ -813,13 +813,13 @@ std::vector LossBasedBweV2::GetCandidates() current_estimate_.loss_limited_bandwidth); } - if (acknowledged_bitrate_.has_value() && +/* if (acknowledged_bitrate_.has_value() && config_->append_acknowledged_rate_candidate && TrendlineEsimateAllowEmergencyBackoff()) { // MS_DEBUG_DEV("Pushing acknowledged_bitrate_ candidate rate: %lld", (*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor).bps()); bandwidths.push_back(*acknowledged_bitrate_ * config_->bandwidth_backoff_lower_bound_factor); - } + }*/ if (IsValid(delay_based_estimate_) && config_->append_delay_based_estimate_candidate) { @@ -1004,7 +1004,7 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { DataRate current_estimate = current_estimate_.loss_limited_bandwidth; instant_loss_debounce_counter_ += 1; - auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 15); + auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 20); // MS_NOTE: Here we create debounce mechanism, that must help in // bursts smoothening. Initially we reduce to 85% of previous BW estimate, // if that will not help after debounce counter, we will reduce further with f diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h index 38354707e9..a8c1330190 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/acknowledged_bitrate_estimator_interface.h @@ -46,9 +46,9 @@ struct RobustThroughputEstimatorSettings { // reasons), and never longer than max_window_duration (to avoid very old // packets influencing the estimate for example when sending is paused). unsigned window_packets = 20; - unsigned max_window_packets = 500; + unsigned max_window_packets = 50; TimeDelta min_window_duration = TimeDelta::Seconds<1>(); - TimeDelta max_window_duration = TimeDelta::Seconds<5>(); + TimeDelta max_window_duration = TimeDelta::Seconds<3>(); // The estimator window requires at least `required_packets` packets // to produce an estimate. diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 1d3e5ea659..53672c10dd 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -557,7 +557,7 @@ NetworkControlUpdate GoogCcNetworkController::OnTransportPacketsFeedback( // acknowledged_bitrate, otherwise we get big BW drops, bigger that default // AIMD 0.85 backof factor result = delay_based_bwe_->IncomingPacketFeedbackVector( - report, acknowledged_bitrate, probe_bitrate, estimate_, + report, bandwidth_estimation_->target_rate(), probe_bitrate, estimate_, alr_start_time.has_value()); if (result.updated) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index bf3f8923c7..3d65509ebc 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -28,10 +28,10 @@ namespace webrtc { namespace { // Parameters for linear least squares fit of regression line to noisy data. -constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; -constexpr double kDefaultTrendlineThresholdGain = 5.0; -constexpr double kDefaultRSquaredUpperBound = 0.1; -constexpr double kDefaultRSquaredLowerBound = 0.01; +constexpr double kDefaultTrendlineSmoothingCoeff = 0.8; +constexpr double kDefaultTrendlineThresholdGain = 4.0; +constexpr double kDefaultRSquaredUpperBound = 0.2; +constexpr double kDefaultRSquaredLowerBound = 0.05; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; @@ -270,7 +270,7 @@ void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, } } } - MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); + Detect(result, send_delta_ms, arrival_time_ms, avg_r_squared); } @@ -317,9 +317,11 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { if (avg_r_squared < kDefaultRSquaredLowerBound) { hypothesis_ = BandwidthUsage::kBwOverusing; + MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); MS_DEBUG_DEV("OverUsing!"); } else { hypothesis_ = BandwidthUsage::kBwUnderusing; + MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); MS_DEBUG_DEV("HOLD"); } @@ -341,7 +343,7 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub time_over_using_ += ts_delta; } overuse_counter_++; - if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) { + if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 3) { //if (time_over_using_ > overusing_time_threshold_) { if (trend.slope >= prev_trend_.slope) { time_over_using_ = 0; diff --git a/worker/include/Settings.hpp b/worker/include/Settings.hpp index 00f32ea206..5a4f08f7cf 100644 --- a/worker/include/Settings.hpp +++ b/worker/include/Settings.hpp @@ -39,7 +39,7 @@ class Settings std::string dtlsCertificateFile; std::string dtlsPrivateKeyFile; std::string libwebrtcFieldTrials{ - "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1,TrendlineIntegrationEnabled:true/" + "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1,TrendlineIntegrationEnabled:true/WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled/" }; }; From 4c0e7e10a65301e661dcc68c8720d1137712de1d Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 3 Jan 2023 01:23:15 +0200 Subject: [PATCH 56/70] Adjust coefficients more --- .../congestion_controller/goog_cc/trendline_estimator.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 3d65509ebc..f6865ba964 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -30,8 +30,8 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.8; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.2; -constexpr double kDefaultRSquaredLowerBound = 0.05; +constexpr double kDefaultRSquaredUpperBound = 0.15; +constexpr double kDefaultRSquaredLowerBound = 0.03; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; From ec9be0da71df8fe0ff837639b3e2bf677071598c Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Thu, 5 Jan 2023 22:49:30 +0200 Subject: [PATCH 57/70] Refactor instant loss debounce mechanism. Add overuse counter for R squared mechanism in trendline estimator. Update default field trial string. --- node/src/Worker.ts | 2 +- rust/src/worker.rs | 2 +- .../bitrate_controller/loss_based_bwe_v2.cc | 129 +++++++++--------- .../bitrate_controller/loss_based_bwe_v2.h | 8 +- .../goog_cc/trendline_estimator.cc | 13 +- 5 files changed, 77 insertions(+), 77 deletions(-) diff --git a/node/src/Worker.ts b/node/src/Worker.ts index 08bd8443e3..f35cd6eeed 100644 --- a/node/src/Worker.ts +++ b/node/src/Worker.ts @@ -70,7 +70,7 @@ export type WorkerSettings = * * NOTE: For advanced users only. An invalid value will make the worker crash. * Default value is - * "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" + * "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1,TrendlineIntegrationEnabled:true/WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled/" */ libwebrtcFieldTrials?: string; /* eslint-enable max-len */ diff --git a/rust/src/worker.rs b/rust/src/worker.rs index 806dd9532f..0215238781 100644 --- a/rust/src/worker.rs +++ b/rust/src/worker.rs @@ -186,7 +186,7 @@ pub struct WorkerSettings { /// /// NOTE: For advanced users only. An invalid value will make the worker crash. /// Default value is - /// "WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled:true/WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/SendingRateSmoothingFactor:0.6,InstantUpperBoundLossOffset:0.1/" + /// "WebRTC-Bwe-AlrLimitedBackoff/Enabled/WebRTC-Bwe-LossBasedBweV2/BwRampupUpperBoundFactor:1.1,TrendlineIntegrationEnabled:true/WebRTC-Bwe-RobustThroughputEstimatorSettings/enabled/" #[doc(hidden)] pub libwebrtc_field_trials: Option, /// Function that will be called under worker thread before worker starts, can be used for diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 9396d2d75e..61904e0a3d 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -163,8 +163,9 @@ void LossBasedBweV2::Reset() { upper_link_capacity_ = DataRate::PlusInfinity(); instant_loss_debounce_counter_ = 0; - instant_loss_debounce_duration = TimeDelta::seconds(2); - instant_loss_debounce_start = Timestamp::MinusInfinity(); + kInstantLossDebounceDuration = TimeDelta::seconds(2); + instant_loss_debounce_start_ = Timestamp::MinusInfinity(); + instant_loss_threshold_ = Timestamp::MinusInfinity(); } bool LossBasedBweV2::IsEnabled() const { @@ -987,10 +988,10 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { DataRate instant_limit = max_bitrate_; const double average_reported_loss_ratio = GetAverageReportedLossRatio(); auto now = Timestamp::ms(DepLibUV::GetTimeMsInt64()); - if (instant_loss_debounce_start.IsFinite()) { - if (now - instant_loss_debounce_start > instant_loss_debounce_duration) { - instant_loss_debounce_counter_ = 0; - instant_loss_debounce_start = Timestamp::MinusInfinity(); + if (instant_loss_debounce_start_.IsFinite()) { + if (average_reported_loss_ratio < config_->instant_upper_bound_loss_offset) { + instant_loss_debounce_start_ = Timestamp::MinusInfinity(); + instant_loss_threshold_ = Timestamp::MinusInfinity(); MS_DEBUG_DEV("Resetting"); } } @@ -1003,94 +1004,90 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { DataRate current_estimate = current_estimate_.loss_limited_bandwidth; - instant_loss_debounce_counter_ += 1; - auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 20); + auto reduce_debounce_time = TimeDelta::ms(config_->observation_duration_lower_bound.ms() * 10); // MS_NOTE: Here we create debounce mechanism, that must help in - // bursts smoothening. Initially we reduce to 85% of previous BW estimate, - // if that will not help after debounce counter, we will reduce further with f - // formula based on bw balance. If we do not continue to overshoot limit in half of the - // observation duration window size, we reset. - if (!instant_loss_debounce_start.IsFinite()) + // bursts smoothening. We reduce by first time by 0.85 all further times + // we reduce by 0.95 for 10 seconds with throttling of 2.5 s. If that does not help + // we fall back to old mechanism with BW balance. + if (!instant_loss_debounce_start_.IsFinite()) { - instant_loss_debounce_start = now; + instant_loss_debounce_start_ = now; + instant_loss_threshold_ = now; MS_DEBUG_DEV("First Instant Loss"); - MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), kInstantLossReduceFactor); + MS_DEBUG_DEV( + "Reducing current estimate %lld by factor %f", + current_estimate.bps(), + 0.85); - cached_instant_upper_bound_ = current_estimate * kInstantLossReduceFactor; + cached_instant_upper_bound_ = current_estimate * 0.85; current_estimate_.loss_limited_bandwidth = cached_instant_upper_bound_.value(); MS_DEBUG_DEV("cached_instant_upper_bound_ %lld", cached_instant_upper_bound_->bps()); - return ; + return; } - if ((now - instant_loss_debounce_start) < reduce_debounce_time && instant_loss_debounce_counter_ > 1) + if ((now - instant_loss_threshold_) < reduce_debounce_time) { MS_DEBUG_DEV( "Debouncing loss estimate decease as %lld < %lld", - (now - instant_loss_debounce_start).ms(), + (now - instant_loss_threshold_).ms(), reduce_debounce_time.ms()); return; - } - - MS_DEBUG_DEV("Reducing current estimate %lld by factor %f", current_estimate.bps(), kInstantLossReduceFactor); - - cached_instant_upper_bound_ = current_estimate * kInstantLossReduceFactor; + } else if ((now - instant_loss_threshold_) > reduce_debounce_time && (now - instant_loss_debounce_start_ < kInstantLossDebounceDuration)) { + MS_DEBUG_DEV( + "Reducing current estimate %lld by factor %f", current_estimate.bps(), kInstantLossReduceFactor); - current_estimate_.loss_limited_bandwidth = cached_instant_upper_bound_.value(); + cached_instant_upper_bound_ = current_estimate * kInstantLossReduceFactor; - MS_DEBUG_DEV("cached_instant_upper_bound_ %lld", cached_instant_upper_bound_->bps()); + current_estimate_.loss_limited_bandwidth = cached_instant_upper_bound_.value(); - if (now - instant_loss_debounce_start > instant_loss_debounce_duration) - { - instant_loss_debounce_counter_ = 0; - instant_loss_debounce_start = Timestamp::MinusInfinity(); - MS_DEBUG_DEV("Resetting"); - } - else - { - instant_loss_debounce_start = now; - MS_DEBUG_DEV("Updating instant_loss_debounce_start"); + MS_DEBUG_DEV("cached_instant_upper_bound_ %lld", cached_instant_upper_bound_->bps()); + instant_loss_threshold_ = now; return; } - DataRate bandwidth_balance = config_->instant_upper_bound_bandwidth_balance; - - // MS_NOTE: In case of high sending rate the value of balance (75kbps) is too small, - // and leads to big BW drops even in the case of small loss ratio. - if (sending_rate.bps() > config_->instant_upper_bound_bandwidth_balance.bps() * 100) + if (now - instant_loss_debounce_start_ > kInstantLossDebounceDuration) { - bandwidth_balance = DataRate::bps((sending_rate.bps() / 100) * kBwBalanceMultiplicator); - } + MS_DEBUG_DEV("Reducing by BW balance formula"); + DataRate bandwidth_balance = config_->instant_upper_bound_bandwidth_balance; - instant_limit = - bandwidth_balance / (average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); + // MS_NOTE: In case of high sending rate the value of balance (75kbps) is too small, + // and leads to big BW drops even in the case of small loss ratio. + if (sending_rate.bps() > config_->instant_upper_bound_bandwidth_balance.bps() * 100) + { + bandwidth_balance = DataRate::bps((sending_rate.bps() / 100) * kBwBalanceMultiplicator); + } - MS_DEBUG_DEV( - "Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 - ", average_reported_loss_ratio %f, diff: %f, sending rate: %lld", - bandwidth_balance.bps(), - instant_limit.IsFinite() ? instant_limit.bps() : 0, - average_reported_loss_ratio, - average_reported_loss_ratio - config_->instant_upper_bound_loss_offset, - sending_rate.bps()); + instant_limit = + bandwidth_balance / (average_reported_loss_ratio - config_->instant_upper_bound_loss_offset); - if (average_reported_loss_ratio > config_->high_loss_rate_threshold) - { - instant_limit = std::min( - instant_limit, - DataRate::kbps(std::max( - static_cast(min_bitrate_.kbps()), - config_->bandwidth_cap_at_high_loss_rate.kbps() - - config_->slope_of_bwe_high_loss_func * average_reported_loss_ratio))); - } + MS_DEBUG_DEV( + "Instant Limit!, BW balance %" PRIi64 ", instant_limit %" PRIi64 + ", average_reported_loss_ratio %f, diff: %f, sending rate: %lld", + bandwidth_balance.bps(), + instant_limit.IsFinite() ? instant_limit.bps() : 0, + average_reported_loss_ratio, + average_reported_loss_ratio - config_->instant_upper_bound_loss_offset, + sending_rate.bps()); + + if (average_reported_loss_ratio > config_->high_loss_rate_threshold) + { + instant_limit = std::min( + instant_limit, + DataRate::kbps(std::max( + static_cast(min_bitrate_.kbps()), + config_->bandwidth_cap_at_high_loss_rate.kbps() - + config_->slope_of_bwe_high_loss_func * average_reported_loss_ratio))); + } - if (IsBandwidthLimitedDueToLoss()) - { - if (IsValid(upper_link_capacity_) && config_->bound_by_upper_link_capacity_when_loss_limited) + if (IsBandwidthLimitedDueToLoss()) { - instant_limit = std::min(instant_limit, upper_link_capacity_); + if (IsValid(upper_link_capacity_) && config_->bound_by_upper_link_capacity_when_loss_limited) + { + instant_limit = std::min(instant_limit, upper_link_capacity_); + } } } } diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index bd917fe544..d280aeaeac 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -202,11 +202,11 @@ class LossBasedBweV2 { DataRate max_bitrate_ = DataRate::PlusInfinity(); TimeDelta max_observation_duration_before_reset_ = TimeDelta::seconds(4); double static constexpr kBwBalanceMultiplicator = 1.3; - double static constexpr kInstantLossDebounce = 3; size_t instant_loss_debounce_counter_ = 0; - TimeDelta instant_loss_debounce_duration = TimeDelta::seconds(5); - Timestamp instant_loss_debounce_start = Timestamp::MinusInfinity(); - float kInstantLossReduceFactor = 0.9; + TimeDelta kInstantLossDebounceDuration = TimeDelta::seconds(10); + Timestamp instant_loss_debounce_start_ = Timestamp::MinusInfinity(); + Timestamp instant_loss_threshold_ = Timestamp::MinusInfinity(); + float kInstantLossReduceFactor = 0.95; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index f6865ba964..5377f54d71 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -316,13 +316,18 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub // in case we see that we have many outliers. if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { if (avg_r_squared < kDefaultRSquaredLowerBound) { - hypothesis_ = BandwidthUsage::kBwOverusing; - MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); - MS_DEBUG_DEV("OverUsing!"); + overuse_counter_++; + if (overuse_counter_ > 3) { + hypothesis_ = BandwidthUsage::kBwOverusing; + MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); + MS_DEBUG_DEV("OverUsing!"); + overuse_counter_ = 0; + } } else { hypothesis_ = BandwidthUsage::kBwUnderusing; MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); MS_DEBUG_DEV("HOLD"); + overuse_counter_ = 0; } prev_trend_ = trend; @@ -344,14 +349,12 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub } overuse_counter_++; if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 3) { - //if (time_over_using_ > overusing_time_threshold_) { if (trend.slope >= prev_trend_.slope) { time_over_using_ = 0; overuse_counter_ = 0; hypothesis_ = BandwidthUsage::kBwOverusing; if (hypothesis_ != prev_hypothesis) MS_DEBUG_DEV("hypothesis_: BandwidthUsage::kBwOverusing"); - } } } else if (modified_trend < -threshold_) { From a175c3684f214a65dc22bcc41400de94a557eac6 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 9 Jan 2023 12:30:47 +0200 Subject: [PATCH 58/70] Adjust coefficients, create separate counter for R squared overuse --- .../goog_cc/trendline_estimator.cc | 13 +++++++------ .../goog_cc/trendline_estimator.h | 1 + 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 5377f54d71..c7ccc5db9c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -30,8 +30,8 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.8; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.15; -constexpr double kDefaultRSquaredLowerBound = 0.03; +constexpr double kDefaultRSquaredUpperBound = 0.2; +constexpr double kDefaultRSquaredLowerBound = 0.02; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; @@ -202,6 +202,7 @@ TrendlineEstimator::TrendlineEstimator( prev_trend_(0.0, 0.0), time_over_using_(-1), overuse_counter_(0), + r_squared_overuse_counter_(0), hypothesis_(BandwidthUsage::kBwNormal), hypothesis_predicted_(BandwidthUsage::kBwNormal), network_state_predictor_(network_state_predictor) { @@ -316,18 +317,18 @@ void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, doub // in case we see that we have many outliers. if (trend.slope > 0.0 && avg_r_squared > 0 && avg_r_squared < kDefaultRSquaredUpperBound) { if (avg_r_squared < kDefaultRSquaredLowerBound) { - overuse_counter_++; - if (overuse_counter_ > 3) { + r_squared_overuse_counter_++; + if (r_squared_overuse_counter_ > 3) { hypothesis_ = BandwidthUsage::kBwOverusing; MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); MS_DEBUG_DEV("OverUsing!"); - overuse_counter_ = 0; + r_squared_overuse_counter_ = 0; } } else { hypothesis_ = BandwidthUsage::kBwUnderusing; MS_DEBUG_DEV("slope, r_squared, avg_r_squared [%f, %f, %f]", trend.slope, trend.r_squared, avg_r_squared); MS_DEBUG_DEV("HOLD"); - overuse_counter_ = 0; + r_squared_overuse_counter_ = 0; } prev_trend_ = trend; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index 21b3d42595..85b18f16ae 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -141,6 +141,7 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { RegressionResult prev_trend_; double time_over_using_; int overuse_counter_; + int r_squared_overuse_counter_; BandwidthUsage hypothesis_; BandwidthUsage hypothesis_predicted_; NetworkStatePredictor* network_state_predictor_; From ff76084e331081e0bc63ac9121fa4a9ac68646e6 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 9 Jan 2023 12:32:04 +0200 Subject: [PATCH 59/70] Adjust coefficients --- .../congestion_controller/goog_cc/trendline_estimator.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index c7ccc5db9c..eda5d4f312 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -30,7 +30,7 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.8; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.2; +constexpr double kDefaultRSquaredUpperBound = 0.15; constexpr double kDefaultRSquaredLowerBound = 0.02; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; From 545a910ce7c71bf56f1529d9d775459b68ba787a Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Mon, 9 Jan 2023 16:10:58 +0200 Subject: [PATCH 60/70] Limit probation rate by loss estimate rate, and don't probe when delay increasing --- .../modules/congestion_controller/goog_cc/probe_controller.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 97bed651ec..0cb7975a8c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -101,12 +101,12 @@ ProbeControllerConfig::ProbeControllerConfig( min_probe_packets_sent("min_probe_packets_sent", 5), min_probe_duration("min_probe_duration", TimeDelta::ms(15)), limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe", - false), + true), loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", 0.0), - not_probe_if_delay_increased("not_probe_if_delay_increased", false) { + not_probe_if_delay_increased("not_probe_if_delay_increased", true) { ParseFieldTrial({&first_exponential_probe_scale, &second_exponential_probe_scale, &further_exponential_probe_scale, From 2594fd74affca3a6cae56a468f1f15874ec700cb Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 10 Jan 2023 12:44:59 +0200 Subject: [PATCH 61/70] return smooth coefficient to 0.9, increase upper bound of R squared limit and decrease lower bound a bit to be able to reach higher bitrates. --- .../congestion_controller/goog_cc/trendline_estimator.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index eda5d4f312..6b657a4ed8 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -28,10 +28,10 @@ namespace webrtc { namespace { // Parameters for linear least squares fit of regression line to noisy data. -constexpr double kDefaultTrendlineSmoothingCoeff = 0.8; +constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.15; -constexpr double kDefaultRSquaredLowerBound = 0.02; +constexpr double kDefaultRSquaredUpperBound = 0.95; +constexpr double kDefaultRSquaredLowerBound = 0.01; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; From 4081d008ba81383ee0fbec1b7576c73debfe22ba Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 10 Jan 2023 18:38:51 +0200 Subject: [PATCH 62/70] Pass inner estimators states to mediasoup land. --- .../libwebrtc/api/transport/network_control.h | 8 ++++++ .../libwebrtc/api/transport/network_types.cc | 4 +++ .../libwebrtc/api/transport/network_types.h | 26 +++++++++++++++++++ .../call/rtp_transport_controller_send.cc | 7 +++++ .../call/rtp_transport_controller_send.h | 4 +++ .../rtp_transport_controller_send_interface.h | 3 +++ .../bitrate_controller/loss_based_bwe_v2.cc | 15 ++++++++--- .../bitrate_controller/loss_based_bwe_v2.h | 3 +++ .../send_side_bandwidth_estimation.cc | 4 +++ .../send_side_bandwidth_estimation.h | 1 + .../goog_cc/delay_based_bwe.h | 6 +++++ .../delay_increase_detector_interface.h | 13 ++++++++++ .../goog_cc/goog_cc_network_control.cc | 19 ++++++++++++-- .../goog_cc/goog_cc_network_control.h | 2 ++ .../goog_cc/trendline_estimator.cc | 14 +++++++--- .../goog_cc/trendline_estimator.h | 15 ++--------- .../aimd_rate_control.cc | 4 +++ .../aimd_rate_control.h | 3 +-- .../include/bwe_defines.h | 2 +- .../RTC/TransportCongestionControlClient.hpp | 6 ++++- .../RTC/TransportCongestionControlClient.cpp | 21 ++++++++++++++- 21 files changed, 153 insertions(+), 27 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h index ec1549e13e..829f582a8f 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_control.h @@ -32,6 +32,13 @@ class TargetTransferRateObserver { virtual void OnStartRateUpdate(DataRate) {} }; +class BweStatsTracer { +public: + virtual ~BweStatsTracer() = default; + virtual void OnBweStats(BweStats) = 0; +}; + + // Configuration sent to factory create function. The parameters here are // optional to use for a network controller implementation. struct NetworkControllerConfig { @@ -89,6 +96,7 @@ class NetworkControllerInterface { TransportPacketsFeedback) = 0; // Called with network state estimate updates. virtual NetworkControlUpdate OnNetworkStateEstimate(NetworkStateEstimate) = 0; + virtual BweStats GetBweStats() = 0; }; // NetworkControllerFactoryInterface is an interface for creating a network diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc index 7451940151..bf3f5ed06d 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.cc @@ -17,6 +17,10 @@ StreamsConfig::StreamsConfig() = default; StreamsConfig::StreamsConfig(const StreamsConfig&) = default; StreamsConfig::~StreamsConfig() = default; +BweStats::BweStats() = default; +BweStats::BweStats(const BweStats&) = default; +BweStats::~BweStats() = default; + TargetRateConstraints::TargetRateConstraints() = default; TargetRateConstraints::TargetRateConstraints(const TargetRateConstraints&) = default; diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index 1c8d71e361..3205b3dce3 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -15,6 +15,8 @@ #include "api/units/data_size.h" #include "api/units/time_delta.h" #include "api/units/timestamp.h" +#include "modules/congestion_controller/goog_cc/delay_increase_detector_interface.h" +#include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include #include @@ -37,6 +39,30 @@ struct BitrateAllocationLimits { DataRate max_padding_rate = DataRate::Zero(); }; +struct LossEstimatorState { + ~LossEstimatorState() = default; + absl::optional bandwidth_estimate = DataRate::Zero(); + double inherent_loss; + double avg_loss; + absl::optional sending_rate = DataRate::Zero(); +}; + +struct BweStats { + BweStats(); + BweStats(const BweStats&); + ~BweStats(); + Timestamp time = Timestamp::PlusInfinity(); + absl::optional estimated_bitrate; + absl::optional acknowledged_bitrate; + RateControlState rate_control_state; + DelayIncreaseDetectorInterface::RegressionResult trend; + TimeDelta rtt = TimeDelta::ms(0); + bool in_alr = false; + LossEstimatorState loss_estimator_state; +}; + + + // Use StreamsConfig for information about streams that is required for specific // adjustments to the algorithms in network controllers. Especially useful // for experiments. diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc index f99aaa2846..df553c7058 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc @@ -143,6 +143,12 @@ void RtpTransportControllerSend::RegisterTargetTransferRateObserver( MaybeCreateControllers(); } +void RtpTransportControllerSend::RegisterBweStatsTracer(webrtc::BweStatsTracer* tracer) { + MS_ASSERT(stats_tracer_ == nullptr, "stats_tracer already set"); + + stats_tracer_ = tracer; +} + void RtpTransportControllerSend::OnNetworkAvailability(bool network_available) { MS_DEBUG_DEV("<<<<< network_available:%s", network_available ? "true" : "false"); @@ -242,6 +248,7 @@ void RtpTransportControllerSend::OnTransportFeedback( PostUpdates(controller_->OnTransportPacketsFeedback(*feedback_msg)); pacer_.UpdateOutstandingData( transport_feedback_adapter_.GetOutstandingData().bytes()); + stats_tracer_->OnBweStats(controller_->GetBweStats()); } void RtpTransportControllerSend::OnRemoteNetworkEstimate( diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h index 7ffc321717..696abb34b5 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.h @@ -61,6 +61,8 @@ class RtpTransportControllerSend final void SetPacingFactor(float pacing_factor) override; void RegisterTargetTransferRateObserver( TargetTransferRateObserver* observer) override; + void RegisterBweStatsTracer( + BweStatsTracer* tracer) override; void OnNetworkAvailability(bool network_available) override; RtcpBandwidthObserver* GetBandwidthObserver() override; void EnablePeriodicAlrProbing(bool enable) override; @@ -102,6 +104,8 @@ class RtpTransportControllerSend final TargetTransferRateObserver* observer_; + BweStatsTracer* stats_tracer_; + NetworkControllerFactoryInterface* const controller_factory_override_; TransportFeedbackAdapter transport_feedback_adapter_; diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h index 1575f45b78..9bdbfa4dac 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send_interface.h @@ -36,6 +36,7 @@ struct NetworkRoute; namespace webrtc { class TargetTransferRateObserver; +class BweStatsTracer; class Transport; class PacedSender; class PacketFeedbackObserver; @@ -99,6 +100,8 @@ class RtpTransportControllerSendInterface { // PacketFeedbackObserver* observer) = 0; virtual void RegisterTargetTransferRateObserver( TargetTransferRateObserver* observer) = 0; + virtual void RegisterBweStatsTracer( + BweStatsTracer* tracer) = 0; virtual void OnNetworkAvailability(bool network_available) = 0; virtual RtcpBandwidthObserver* GetBandwidthObserver() = 0; virtual void EnablePeriodicAlrProbing(bool enable) = 0; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 61904e0a3d..3ae3fede1e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -745,6 +745,15 @@ bool LossBasedBweV2::IsConfigValid() const { return valid; } +LossEstimatorState LossBasedBweV2::GetState() const { + LossEstimatorState state; + state.inherent_loss = current_estimate_.inherent_loss; + state.avg_loss = GetAverageReportedLossRatio(); + state.bandwidth_estimate = current_estimate_.loss_limited_bandwidth; + state.sending_rate = last_sending_rate_; + return state; +} + double LossBasedBweV2::GetAverageReportedLossRatio() const { if (num_observations_ <= 0) { return 0.0; @@ -1194,21 +1203,21 @@ bool LossBasedBweV2::PushBackObservation( } last_send_time_most_recent_observation_ = last_send_time; - DataRate sending_rate = GetSendingRate(partial_observation_.size / observation_duration); + last_sending_rate_ = GetSendingRate(partial_observation_.size / observation_duration); Observation observation; observation.num_packets = partial_observation_.num_packets; observation.num_lost_packets = partial_observation_.num_lost_packets; observation.num_received_packets = observation.num_packets - observation.num_lost_packets; - observation.sending_rate = sending_rate; + observation.sending_rate = last_sending_rate_; observation.id = num_observations_++; observations_[observation.id % config_->observation_window_size] = observation; partial_observation_ = PartialObservation(); - CalculateInstantUpperBound(sending_rate); + CalculateInstantUpperBound(last_sending_rate_); // MS_NOTE Here we reset loss estimator if there was not traffic in // max_observation_duration_before_reset_, otherwise, we will stuck diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index d280aeaeac..8f323d1d01 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -52,6 +52,8 @@ class LossBasedBweV2 { ~LossBasedBweV2() = default; + LossEstimatorState GetState() const; + bool IsEnabled() const; // Returns true iff a BWE can be calculated, i.e., the estimator has been // initialized with a BWE and then has received enough `PacketResult`s. @@ -207,6 +209,7 @@ class LossBasedBweV2 { Timestamp instant_loss_debounce_start_ = Timestamp::MinusInfinity(); Timestamp instant_loss_threshold_ = Timestamp::MinusInfinity(); float kInstantLossReduceFactor = 0.95; + DataRate last_sending_rate_ = DataRate::PlusInfinity(); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc index 4043e8a550..0e094d6bf3 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.cc @@ -282,6 +282,10 @@ void SendSideBandwidthEstimation::SetBitrates( } } +LossEstimatorState SendSideBandwidthEstimation::GetLossEstimatorState() const { + return loss_based_bandwidth_estimator_v2_.GetState(); +} + void SendSideBandwidthEstimation::SetSendBitrate(DataRate bitrate, Timestamp at_time) { MS_DEBUG_DEV("bitrate: %lld", bitrate.bps()); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h index 90faa460ea..e7a177a1a9 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/send_side_bandwidth_estimation.h @@ -116,6 +116,7 @@ class SendSideBandwidthEstimation { BandwidthUsage delay_detector_state, absl::optional probe_bitrate, DataRate upper_link_capacity); + LossEstimatorState GetLossEstimatorState() const; private: friend class GoogCcStatePrinter; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h index 5f6db7113f..bdc220f74f 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -84,6 +84,12 @@ class DelayBasedBwe { absl::optional link_capacity); DataRate last_estimate() const { return prev_bitrate_; } BandwidthUsage last_state() const { return prev_state_; } + RateControlState GetRateControlState() const { + return rate_control_.GetRateControlState(); + } + DelayIncreaseDetectorInterface::RegressionResult GetTrend() const { + return active_delay_detector_->GetTrend(); + } private: friend class GoogCcStatePrinter; void IncomingPacketFeedback(const PacketResult& packet_feedback, diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h index af644f9271..2a05e879b9 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h @@ -36,6 +36,19 @@ class DelayIncreaseDetectorInterface { bool calculated_deltas) = 0; virtual BandwidthUsage State() const = 0; + struct RegressionResult { + RegressionResult(double slope, + double r_squared) + : slope(slope), + r_squared(r_squared) {} + RegressionResult() + : slope(0.0), + r_squared(0.0) {} + double slope; + double r_squared; + }; + + virtual RegressionResult GetTrend() = 0; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 53672c10dd..6fa9976431 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -18,15 +18,16 @@ #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "modules/remote_bitrate_estimator/include/bwe_defines.h" +#include "DepLibUV.hpp" #include "Logger.hpp" #include -#include -#include #include #include +#include #include #include +#include #include #include #include @@ -142,6 +143,20 @@ NetworkControlUpdate GoogCcNetworkController::OnNetworkAvailability( return update; } +BweStats GoogCcNetworkController::GetBweStats() +{ + BweStats stats; + stats.time = Timestamp::ms(DepLibUV::GetTimeMsInt64()); + stats.estimated_bitrate = bandwidth_estimation_->target_rate(); + stats.acknowledged_bitrate = acknowledged_bitrate_estimator_->bitrate(); + stats.rate_control_state = delay_based_bwe_->GetRateControlState(); + stats.trend = delay_based_bwe_->GetTrend(); + stats.rtt = bandwidth_estimation_->round_trip_time(); + stats.loss_estimator_state = bandwidth_estimation_->GetLossEstimatorState(); + stats.in_alr = alr_detector_->GetApplicationLimitedRegionStartTime().has_value(); + return stats; +} + NetworkControlUpdate GoogCcNetworkController::OnNetworkRouteChange( NetworkRouteChange msg) { if (safe_reset_on_route_change_) { diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h index 5d9e945568..e1429dda01 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.h @@ -69,6 +69,8 @@ class GoogCcNetworkController : public NetworkControllerInterface { NetworkControlUpdate OnNetworkStateEstimate( NetworkStateEstimate msg) override; + BweStats GetBweStats() override; + NetworkControlUpdate GetNetworkState(Timestamp at_time) const; private: diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 6b657a4ed8..bc904c64bf 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -52,7 +52,7 @@ size_t ReadTrendlineFilterWindowSize(const WebRtcKeyValueConfig* key_value_confi return TrendlineEstimatorSettings::kDefaultTrendlineWindowSize; } -absl::optional LinearFitSlope( +absl::optional LinearFitSlope( const std::deque& packets) { // RTC_DCHECK(packets.size() >= 2); // Compute the "center of mass". @@ -90,7 +90,7 @@ absl::optional LinearFitSlope( double r_squared = r_numerator / r_denominator; - return TrendlineEstimator::RegressionResult(b1, r_squared); + return DelayIncreaseDetectorInterface::RegressionResult(b1, r_squared); } absl::optional ComputeSlopeCap( @@ -247,7 +247,7 @@ void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, // Simple linear regression. auto trend = prev_trend_; - RegressionResult result; + DelayIncreaseDetectorInterface::RegressionResult result; double avg_r_squared {0.0}; if (delay_hist_.size() == settings_.window_size) { // Update trend_ if it is possible to fit a line to the data. The delay @@ -262,6 +262,7 @@ void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, r_squared_hist_.pop_front(); } avg_r_squared = getAverage(r_squared_hist_); + trend.r_squared = avg_r_squared; if (settings_.enable_cap) { absl::optional cap = ComputeSlopeCap(delay_hist_, settings_); // We only use the cap to filter out overuse detections, not @@ -296,7 +297,12 @@ BandwidthUsage TrendlineEstimator::State() const { return network_state_predictor_ ? hypothesis_predicted_ : hypothesis_; } -void TrendlineEstimator::Detect(TrendlineEstimator::RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared) { +DelayIncreaseDetectorInterface::RegressionResult TrendlineEstimator::GetTrend() +{ + return prev_trend_; +} + +void TrendlineEstimator::Detect(DelayIncreaseDetectorInterface::RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared) { if (num_of_deltas_ < 2) { hypothesis_ = BandwidthUsage::kBwNormal; return; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index 85b18f16ae..f84e815cda 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -98,18 +98,7 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double raw_delay_ms; }; - struct RegressionResult { - RegressionResult(double slope, - double r_squared) - : slope(slope), - r_squared(r_squared) {} - RegressionResult() - : slope(0.0), - r_squared(0.0) {} - double slope; - double r_squared; - }; - + DelayIncreaseDetectorInterface::RegressionResult GetTrend() override; private: friend class GoogCcStatePrinter; void Detect(RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared); @@ -138,7 +127,7 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double threshold_; double prev_modified_trend_; int64_t last_update_ms_; - RegressionResult prev_trend_; + DelayIncreaseDetectorInterface::RegressionResult prev_trend_; double time_over_using_; int overuse_counter_; int r_squared_overuse_counter_; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc index a07b177410..a3bd35f487 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.cc @@ -122,6 +122,10 @@ void AimdRateControl::SetStartBitrate(DataRate start_bitrate) { bitrate_is_initialized_ = true; } +RateControlState AimdRateControl::GetRateControlState() const { + return rate_control_state_; +}; + void AimdRateControl::SetMinBitrate(DataRate min_bitrate) { MS_DEBUG_DEV("[min_bitrate:%" PRIi64 "]", min_bitrate.bps()); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h index 6e4ead24a4..75fad29704 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/aimd_rate_control.h @@ -63,9 +63,8 @@ class AimdRateControl { double GetNearMaxIncreaseRateBpsPerSecond() const; // Returns the expected time between overuse signals (assuming steady state). TimeDelta GetExpectedBandwidthPeriod() const; - + RateControlState GetRateControlState() const; private: - enum class RateControlState { kRcHold, kRcIncrease, kRcDecrease }; friend class GoogCcStatePrinter; // Update the target bitrate based on, among other things, the current rate diff --git a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h index f3213e4904..18a4de0b88 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/remote_bitrate_estimator/include/bwe_defines.h @@ -41,7 +41,7 @@ enum BweNames { kBweNamesMax = 4 }; -enum RateControlState { kRcHold, kRcIncrease, kRcDecrease }; +enum class RateControlState { kRcHold, kRcIncrease, kRcDecrease }; struct RateControlInput { RateControlInput(BandwidthUsage bw_state, diff --git a/worker/include/RTC/TransportCongestionControlClient.hpp b/worker/include/RTC/TransportCongestionControlClient.hpp index 17f7684f04..e213c24bf5 100644 --- a/worker/include/RTC/TransportCongestionControlClient.hpp +++ b/worker/include/RTC/TransportCongestionControlClient.hpp @@ -21,7 +21,8 @@ namespace RTC class TransportCongestionControlClient : public webrtc::PacketRouter, public webrtc::TargetTransferRateObserver, - public Timer::Listener + public Timer::Listener, + public webrtc::BweStatsTracer { public: struct Bitrates @@ -97,6 +98,9 @@ namespace RTC public: void OnTargetTransferRate(webrtc::TargetTransferRate targetTransferRate) override; + public: + void OnBweStats(webrtc::BweStats) override; + /* Pure virtual methods inherited from webrtc::PacketRouter. */ public: void SendPacket(RTC::RtpPacket* packet, const webrtc::PacedPacketInfo& pacingInfo) override; diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index bf6b11425d..8dd2eb2bae 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -1,5 +1,5 @@ #define MS_CLASS "RTC::TransportCongestionControlClient" -// #define MS_LOG_DEV_LEVEL 3 +#define MS_LOG_DEV_LEVEL 3 #define USE_TREND_CALCULATOR #include "RTC/TransportCongestionControlClient.hpp" @@ -64,6 +64,7 @@ namespace RTC new webrtc::RtpTransportControllerSend(this, nullptr, this->controllerFactory, bitrateConfig); this->rtpTransportControllerSend->RegisterTargetTransferRateObserver(this); + this->rtpTransportControllerSend->RegisterBweStatsTracer(this); this->probationGenerator = new RTC::RtpProbationGenerator(); @@ -473,6 +474,24 @@ namespace RTC } } + void TransportCongestionControlClient::OnBweStats(webrtc::BweStats stats) + { + MS_DEBUG_DEV("< BWE Stats >: "); + MS_DEBUG_DEV("time: %lld", stats.time.ms()); + MS_DEBUG_DEV("estimated_bitrate: %lld", stats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV("trend.slope: %f", stats.trend.slope); + MS_DEBUG_DEV("trend.r_squared: %f", stats.trend.r_squared); + MS_DEBUG_DEV("rtt: %lld", stats.rtt.ms()); + MS_DEBUG_DEV("rate control State: %d", stats.rate_control_state); + MS_DEBUG_DEV("alr: %d", stats.in_alr); + MS_DEBUG_DEV("acknowledged_bitrate: %lld",stats.acknowledged_bitrate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV("< Loss Estimator>: "); + MS_DEBUG_DEV("inherent_loss: %f", stats.loss_estimator_state.inherent_loss); + MS_DEBUG_DEV("avg_loss: %f", stats.loss_estimator_state.avg_loss); + MS_DEBUG_DEV("bandwidth_estimate: %lld", stats.loss_estimator_state.bandwidth_estimate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV("sending_rate: %lld", stats.loss_estimator_state.sending_rate.value_or(webrtc::DataRate::Zero()).bps()); + } + void TransportCongestionControlClient::OnTargetTransferRate(webrtc::TargetTransferRate targetTransferRate) { MS_TRACE(); From eef19db12c698e69b89487499ef1a776945fb267 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 10 Jan 2023 19:27:13 +0200 Subject: [PATCH 63/70] format --- .../src/RTC/TransportCongestionControlClient.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index 8dd2eb2bae..a045b2a6b2 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -478,18 +478,25 @@ namespace RTC { MS_DEBUG_DEV("< BWE Stats >: "); MS_DEBUG_DEV("time: %lld", stats.time.ms()); - MS_DEBUG_DEV("estimated_bitrate: %lld", stats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV( + "estimated_bitrate: %lld", stats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps()); MS_DEBUG_DEV("trend.slope: %f", stats.trend.slope); MS_DEBUG_DEV("trend.r_squared: %f", stats.trend.r_squared); MS_DEBUG_DEV("rtt: %lld", stats.rtt.ms()); MS_DEBUG_DEV("rate control State: %d", stats.rate_control_state); MS_DEBUG_DEV("alr: %d", stats.in_alr); - MS_DEBUG_DEV("acknowledged_bitrate: %lld",stats.acknowledged_bitrate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV( + "acknowledged_bitrate: %lld", + stats.acknowledged_bitrate.value_or(webrtc::DataRate::Zero()).bps()); MS_DEBUG_DEV("< Loss Estimator>: "); MS_DEBUG_DEV("inherent_loss: %f", stats.loss_estimator_state.inherent_loss); MS_DEBUG_DEV("avg_loss: %f", stats.loss_estimator_state.avg_loss); - MS_DEBUG_DEV("bandwidth_estimate: %lld", stats.loss_estimator_state.bandwidth_estimate.value_or(webrtc::DataRate::Zero()).bps()); - MS_DEBUG_DEV("sending_rate: %lld", stats.loss_estimator_state.sending_rate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV( + "bandwidth_estimate: %lld", + stats.loss_estimator_state.bandwidth_estimate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV( + "sending_rate: %lld", + stats.loss_estimator_state.sending_rate.value_or(webrtc::DataRate::Zero()).bps()); } void TransportCongestionControlClient::OnTargetTransferRate(webrtc::TargetTransferRate targetTransferRate) From eac1e6f4977db9d52af0e95949127c734b599204 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 10 Jan 2023 19:39:32 +0200 Subject: [PATCH 64/70] Add probe bitrate estimator to stats. --- worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h | 1 + .../congestion_controller/goog_cc/goog_cc_network_control.cc | 1 + worker/src/RTC/TransportCongestionControlClient.cpp | 1 + 3 files changed, 3 insertions(+) diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index 3205b3dce3..1b2dea0e73 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -59,6 +59,7 @@ struct BweStats { TimeDelta rtt = TimeDelta::ms(0); bool in_alr = false; LossEstimatorState loss_estimator_state; + absl::optional probe_bitrate; }; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index 6fa9976431..a5ed31d32c 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -154,6 +154,7 @@ BweStats GoogCcNetworkController::GetBweStats() stats.rtt = bandwidth_estimation_->round_trip_time(); stats.loss_estimator_state = bandwidth_estimation_->GetLossEstimatorState(); stats.in_alr = alr_detector_->GetApplicationLimitedRegionStartTime().has_value(); + stats.probe_bitrate = probe_bitrate_estimator_->last_estimate(); return stats; } diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index a045b2a6b2..b10a59b16e 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -488,6 +488,7 @@ namespace RTC MS_DEBUG_DEV( "acknowledged_bitrate: %lld", stats.acknowledged_bitrate.value_or(webrtc::DataRate::Zero()).bps()); + MS_DEBUG_DEV("probe_bitrate: %lld", stats.probe_bitrate.value_or(webrtc::DataRate::Zero()).bps()); MS_DEBUG_DEV("< Loss Estimator>: "); MS_DEBUG_DEV("inherent_loss: %f", stats.loss_estimator_state.inherent_loss); MS_DEBUG_DEV("avg_loss: %f", stats.loss_estimator_state.avg_loss); From 05cfade109249555b63d9f07a30c69973a5df505 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 11 Jan 2023 14:08:32 +0200 Subject: [PATCH 65/70] Pass stats to nodejs land via trace event bweStats --- node/src/Transport.ts | 2 +- worker/include/RTC/Transport.hpp | 4 ++ .../RTC/TransportCongestionControlClient.hpp | 3 ++ worker/src/RTC/Transport.cpp | 44 ++++++++++++++++++- .../RTC/TransportCongestionControlClient.cpp | 25 +---------- 5 files changed, 53 insertions(+), 25 deletions(-) diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 839af7c8d9..57f5f4542c 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -56,7 +56,7 @@ export type TransportTuple = /** * Valid types for 'trace' event. */ -export type TransportTraceEventType = 'probation' | 'bwe'; +export type TransportTraceEventType = 'probation' | 'bwe' | 'bweStats'; /** * 'trace' event data. diff --git a/worker/include/RTC/Transport.hpp b/worker/include/RTC/Transport.hpp index c52a197616..180499030c 100644 --- a/worker/include/RTC/Transport.hpp +++ b/worker/include/RTC/Transport.hpp @@ -117,6 +117,7 @@ namespace RTC { bool probation{ false }; bool bwe{ false }; + bool bweStats{ false }; }; public: @@ -267,6 +268,9 @@ namespace RTC RTC::TransportCongestionControlClient* tccClient, RTC::RtpPacket* packet, const webrtc::PacedPacketInfo& pacingInfo) override; + void OnTransportCongestionControlClientBweStats( + const webrtc::BweStats& bweStats, + RTC::TransportCongestionControlClient::Bitrates& bitrates) override; /* Pure virtual methods inherited from RTC::TransportCongestionControlServer::Listener. */ public: diff --git a/worker/include/RTC/TransportCongestionControlClient.hpp b/worker/include/RTC/TransportCongestionControlClient.hpp index e213c24bf5..8252f0c2af 100644 --- a/worker/include/RTC/TransportCongestionControlClient.hpp +++ b/worker/include/RTC/TransportCongestionControlClient.hpp @@ -50,6 +50,9 @@ namespace RTC RTC::TransportCongestionControlClient* tccClient, RTC::RtpPacket* packet, const webrtc::PacedPacketInfo& pacingInfo) = 0; + virtual void OnTransportCongestionControlClientBweStats( + const webrtc::BweStats& bweStats, + RTC::TransportCongestionControlClient::Bitrates& bitrates) = 0; }; public: diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 33ed8288d1..c210c845b9 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -440,6 +440,8 @@ namespace RTC traceEventTypes.emplace_back("probation"); if (this->traceEventTypes.bwe) traceEventTypes.emplace_back("bwe"); + if (this->traceEventTypes.bweStats) + traceEventTypes.emplace_back("bweStats"); if (!traceEventTypes.empty()) { @@ -1288,11 +1290,12 @@ namespace RTC MS_THROW_TYPE_ERROR("wrong type (not a string)"); std::string typeStr = type.get(); - if (typeStr == "probation") newTraceEventTypes.probation = true; if (typeStr == "bwe") newTraceEventTypes.bwe = true; + if (typeStr == "bweStats") + newTraceEventTypes.bweStats = true; } this->traceEventTypes = newTraceEventTypes; @@ -2942,6 +2945,45 @@ namespace RTC EmitTraceEventBweType(bitrates); } + inline void Transport::OnTransportCongestionControlClientBweStats( + const webrtc::BweStats& bweStats, RTC::TransportCongestionControlClient::Bitrates& bitrates) + { + MS_TRACE(); + + if (!this->traceEventTypes.bweStats) + return; + + json data = json::object(); + + data["type"] = "bweStats"; + data["timestamp"] = bweStats.time.ms(); + data["direction"] = "out"; + data["info"]["estimatedBitrate"] = + bweStats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps(); + data["info"]["delay"]["slope"] = bweStats.trend.slope; + data["info"]["delay"]["rSquared"] = bweStats.trend.r_squared; + data["info"]["delay"]["rtt"] = bweStats.rtt.ms(); + data["info"]["delay"]["rateControlState"] = bweStats.rate_control_state; + data["info"]["alr"] = bweStats.in_alr; + data["info"]["probe"]["estimatedBitrate"] = + bweStats.probe_bitrate.value_or(webrtc::DataRate::Zero()).bps(); + data["info"]["loss"]["inherent"] = bweStats.loss_estimator_state.inherent_loss; + data["info"]["loss"]["avg"] = bweStats.loss_estimator_state.avg_loss; + data["info"]["loss"]["estimatedBitrate"] = + bweStats.loss_estimator_state.bandwidth_estimate.value_or(webrtc::DataRate::Zero()).bps(); + data["info"]["loss"]["sendingRate"] = + bweStats.loss_estimator_state.sending_rate.value_or(webrtc::DataRate::Zero()).bps(); + data["info"]["desiredBitrate"] = bitrates.desiredBitrate; + data["info"]["effectiveDesiredBitrate"] = bitrates.effectiveDesiredBitrate; + data["info"]["minBitrate"] = bitrates.minBitrate; + data["info"]["maxBitrate"] = bitrates.maxBitrate; + data["info"]["startBitrate"] = bitrates.startBitrate; + data["info"]["maxPaddingBitrate"] = bitrates.maxPaddingBitrate; + data["info"]["availableBitrate"] = bitrates.availableBitrate; + + this->shared->channelNotifier->Emit(this->id, "trace", data); + } + inline void Transport::OnTransportCongestionControlClientSendRtpPacket( RTC::TransportCongestionControlClient* tccClient, RTC::RtpPacket* packet, diff --git a/worker/src/RTC/TransportCongestionControlClient.cpp b/worker/src/RTC/TransportCongestionControlClient.cpp index b10a59b16e..c1f36f52bc 100644 --- a/worker/src/RTC/TransportCongestionControlClient.cpp +++ b/worker/src/RTC/TransportCongestionControlClient.cpp @@ -1,5 +1,5 @@ #define MS_CLASS "RTC::TransportCongestionControlClient" -#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #define USE_TREND_CALCULATOR #include "RTC/TransportCongestionControlClient.hpp" @@ -476,28 +476,7 @@ namespace RTC void TransportCongestionControlClient::OnBweStats(webrtc::BweStats stats) { - MS_DEBUG_DEV("< BWE Stats >: "); - MS_DEBUG_DEV("time: %lld", stats.time.ms()); - MS_DEBUG_DEV( - "estimated_bitrate: %lld", stats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps()); - MS_DEBUG_DEV("trend.slope: %f", stats.trend.slope); - MS_DEBUG_DEV("trend.r_squared: %f", stats.trend.r_squared); - MS_DEBUG_DEV("rtt: %lld", stats.rtt.ms()); - MS_DEBUG_DEV("rate control State: %d", stats.rate_control_state); - MS_DEBUG_DEV("alr: %d", stats.in_alr); - MS_DEBUG_DEV( - "acknowledged_bitrate: %lld", - stats.acknowledged_bitrate.value_or(webrtc::DataRate::Zero()).bps()); - MS_DEBUG_DEV("probe_bitrate: %lld", stats.probe_bitrate.value_or(webrtc::DataRate::Zero()).bps()); - MS_DEBUG_DEV("< Loss Estimator>: "); - MS_DEBUG_DEV("inherent_loss: %f", stats.loss_estimator_state.inherent_loss); - MS_DEBUG_DEV("avg_loss: %f", stats.loss_estimator_state.avg_loss); - MS_DEBUG_DEV( - "bandwidth_estimate: %lld", - stats.loss_estimator_state.bandwidth_estimate.value_or(webrtc::DataRate::Zero()).bps()); - MS_DEBUG_DEV( - "sending_rate: %lld", - stats.loss_estimator_state.sending_rate.value_or(webrtc::DataRate::Zero()).bps()); + this->listener->OnTransportCongestionControlClientBweStats(stats, this->bitrates); } void TransportCongestionControlClient::OnTargetTransferRate(webrtc::TargetTransferRate targetTransferRate) From f5acf13ed2b88da7a326938d0a494dfb6cb60910 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 11 Jan 2023 15:04:54 +0200 Subject: [PATCH 66/70] Refactor. Add missing fields. --- .../libwebrtc/api/transport/network_types.h | 10 ++++++++-- .../goog_cc/delay_based_bwe.cc | 10 ++++++++++ .../goog_cc/delay_based_bwe.h | 7 +------ .../goog_cc/delay_increase_detector_interface.h | 1 + .../goog_cc/goog_cc_network_control.cc | 3 +-- .../goog_cc/trendline_estimator.cc | 5 ----- .../goog_cc/trendline_estimator.h | 11 ++++++++++- worker/src/RTC/Transport.cpp | 17 +++++++++++------ 8 files changed, 42 insertions(+), 22 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h index 1b2dea0e73..02d94553bb 100644 --- a/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h +++ b/worker/deps/libwebrtc/libwebrtc/api/transport/network_types.h @@ -47,6 +47,13 @@ struct LossEstimatorState { absl::optional sending_rate = DataRate::Zero(); }; +struct DelayBasedBweState { + RateControlState rate_control_state; + DelayIncreaseDetectorInterface::RegressionResult trend; + BandwidthUsage delay_detector_state; + double threshold; +}; + struct BweStats { BweStats(); BweStats(const BweStats&); @@ -54,8 +61,7 @@ struct BweStats { Timestamp time = Timestamp::PlusInfinity(); absl::optional estimated_bitrate; absl::optional acknowledged_bitrate; - RateControlState rate_control_state; - DelayIncreaseDetectorInterface::RegressionResult trend; + DelayBasedBweState delay; TimeDelta rtt = TimeDelta::ms(0); bool in_alr = false; LossEstimatorState loss_estimator_state; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc index 9941a55f0f..10122ea914 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.cc @@ -293,4 +293,14 @@ TimeDelta DelayBasedBwe::GetExpectedBwePeriod() const { return rate_control_.GetExpectedBandwidthPeriod(); } +DelayBasedBweState DelayBasedBwe::GetState() const +{ + DelayBasedBweState state; + state.rate_control_state = rate_control_.GetRateControlState(); + state.delay_detector_state = prev_state_; + state.trend = active_delay_detector_->GetTrend(); + state.threshold = active_delay_detector_->GetThreshold(); + return state; +} + } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h index bdc220f74f..3d5c28a261 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_based_bwe.h @@ -84,12 +84,7 @@ class DelayBasedBwe { absl::optional link_capacity); DataRate last_estimate() const { return prev_bitrate_; } BandwidthUsage last_state() const { return prev_state_; } - RateControlState GetRateControlState() const { - return rate_control_.GetRateControlState(); - } - DelayIncreaseDetectorInterface::RegressionResult GetTrend() const { - return active_delay_detector_->GetTrend(); - } + DelayBasedBweState GetState() const; private: friend class GoogCcStatePrinter; void IncomingPacketFeedback(const PacketResult& packet_feedback, diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h index 2a05e879b9..a3bdbf81d5 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/delay_increase_detector_interface.h @@ -49,6 +49,7 @@ class DelayIncreaseDetectorInterface { }; virtual RegressionResult GetTrend() = 0; + virtual double GetThreshold() = 0; }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc index a5ed31d32c..36b9b6ab6e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/goog_cc_network_control.cc @@ -149,8 +149,7 @@ BweStats GoogCcNetworkController::GetBweStats() stats.time = Timestamp::ms(DepLibUV::GetTimeMsInt64()); stats.estimated_bitrate = bandwidth_estimation_->target_rate(); stats.acknowledged_bitrate = acknowledged_bitrate_estimator_->bitrate(); - stats.rate_control_state = delay_based_bwe_->GetRateControlState(); - stats.trend = delay_based_bwe_->GetTrend(); + stats.delay = delay_based_bwe_->GetState(); stats.rtt = bandwidth_estimation_->round_trip_time(); stats.loss_estimator_state = bandwidth_estimation_->GetLossEstimatorState(); stats.in_alr = alr_detector_->GetApplicationLimitedRegionStartTime().has_value(); diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index bc904c64bf..649f8eb489 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -297,11 +297,6 @@ BandwidthUsage TrendlineEstimator::State() const { return network_state_predictor_ ? hypothesis_predicted_ : hypothesis_; } -DelayIncreaseDetectorInterface::RegressionResult TrendlineEstimator::GetTrend() -{ - return prev_trend_; -} - void TrendlineEstimator::Detect(DelayIncreaseDetectorInterface::RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared) { if (num_of_deltas_ < 2) { hypothesis_ = BandwidthUsage::kBwNormal; diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index f84e815cda..32b3d04e01 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -98,7 +98,16 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double raw_delay_ms; }; - DelayIncreaseDetectorInterface::RegressionResult GetTrend() override; + //DelayIncreaseDetectorInterface::RegressionResult GetTrend() override; + DelayIncreaseDetectorInterface::RegressionResult GetTrend() override + { + return prev_trend_; + } + + double GetThreshold() override + { + return threshold_; + } private: friend class GoogCcStatePrinter; void Detect(RegressionResult trend, double ts_delta, int64_t now_ms, double avg_r_squared); diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index c210c845b9..03b5d4ecce 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2960,13 +2960,19 @@ namespace RTC data["direction"] = "out"; data["info"]["estimatedBitrate"] = bweStats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps(); - data["info"]["delay"]["slope"] = bweStats.trend.slope; - data["info"]["delay"]["rSquared"] = bweStats.trend.r_squared; - data["info"]["delay"]["rtt"] = bweStats.rtt.ms(); - data["info"]["delay"]["rateControlState"] = bweStats.rate_control_state; - data["info"]["alr"] = bweStats.in_alr; + data["info"]["delay"]["slope"] = bweStats.delay.trend.slope; + data["info"]["delay"]["rSquared"] = bweStats.delay.trend.r_squared; + data["info"]["delay"]["threshold"] = bweStats.delay.threshold; + data["info"]["delay"]["rtt"] = bweStats.rtt.ms(); + data["info"]["delay"]["rateControlState"] = bweStats.delay.rate_control_state; + data["info"]["delay"]["delayDetectorState"] = bweStats.delay.delay_detector_state; + data["info"]["alr"] = bweStats.in_alr; data["info"]["probe"]["estimatedBitrate"] = bweStats.probe_bitrate.value_or(webrtc::DataRate::Zero()).bps(); + data["info"]["ackBitrate"] = + bweStats.acknowledged_bitrate.value_or(webrtc::DataRate::Zero()).bps(); + + bweStats.probe_bitrate.value_or(webrtc::DataRate::Zero()).bps(); data["info"]["loss"]["inherent"] = bweStats.loss_estimator_state.inherent_loss; data["info"]["loss"]["avg"] = bweStats.loss_estimator_state.avg_loss; data["info"]["loss"]["estimatedBitrate"] = @@ -2979,7 +2985,6 @@ namespace RTC data["info"]["maxBitrate"] = bitrates.maxBitrate; data["info"]["startBitrate"] = bitrates.startBitrate; data["info"]["maxPaddingBitrate"] = bitrates.maxPaddingBitrate; - data["info"]["availableBitrate"] = bitrates.availableBitrate; this->shared->channelNotifier->Emit(this->id, "trace", data); } From 81f724dd44e84f341323e768fff7368ec52c04e7 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 11 Jan 2023 15:57:24 +0200 Subject: [PATCH 67/70] Add typing for bweStats info, add sending rate field. --- node/src/Transport.ts | 35 ++++++++++++++++++++++++++++++++++- worker/src/RTC/Transport.cpp | 1 + 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 57f5f4542c..6dce6d168a 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -58,6 +58,39 @@ export type TransportTuple = */ export type TransportTraceEventType = 'probation' | 'bwe' | 'bweStats'; +/** + * bweStats typings for trace event + */ +export type TransportTraceEventBweStatsInfo = { + estimatedBitrate: number; + delay: { + slope: number; + rSquared: number; + threshold: number; + rtt: number; + rateControlState: number; + delayDetectorState: number; + }; + probe: { + estimatedBitrate: number; + }; + loss: { + inherent: number; + avg: number; + estimatedBitrate: number; + sendingRate: number; + } + alr: boolean; + ackBitrate: number; + desiredBitrate: number; + effectiveDesiredBitrate: number; + minBitrate: number; + maxBitrate: number; + startBitrate: number; + maxPaddingBitrate: number; + sendingRate: number; +} + /** * 'trace' event data. */ @@ -81,7 +114,7 @@ export type TransportTraceEventData = /** * Per type information. */ - info: any; + info: TransportTraceEventBweStatsInfo | any; }; export type SctpState = 'new' | 'connecting' | 'connected' | 'failed' | 'closed'; diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 03b5d4ecce..2105c055cb 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2985,6 +2985,7 @@ namespace RTC data["info"]["maxBitrate"] = bitrates.maxBitrate; data["info"]["startBitrate"] = bitrates.startBitrate; data["info"]["maxPaddingBitrate"] = bitrates.maxPaddingBitrate; + data["info"]["sendingRate"] = sendTransmission.GetRate(DepLibUV::GetTimeMsInt64()); this->shared->channelNotifier->Emit(this->id, "trace", data); } From edb3af640c2e0f1b40c04fd5c01b5602543593f4 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 11 Jan 2023 16:18:22 +0200 Subject: [PATCH 68/70] Add dot in the end of comment. --- node/src/Transport.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 6dce6d168a..744f2efa2a 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -59,7 +59,7 @@ export type TransportTuple = export type TransportTraceEventType = 'probation' | 'bwe' | 'bweStats'; /** - * bweStats typings for trace event + * bweStats typings for trace event. */ export type TransportTraceEventBweStatsInfo = { estimatedBitrate: number; From 8c12a70c7401beeaf87d0f952c9751f0cebfc8b1 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Wed, 11 Jan 2023 17:01:50 +0200 Subject: [PATCH 69/70] Make linter happy --- node/src/Transport.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/node/src/Transport.ts b/node/src/Transport.ts index 744f2efa2a..c33516de4c 100644 --- a/node/src/Transport.ts +++ b/node/src/Transport.ts @@ -79,7 +79,7 @@ export type TransportTraceEventBweStatsInfo = { avg: number; estimatedBitrate: number; sendingRate: number; - } + }; alr: boolean; ackBitrate: number; desiredBitrate: number; @@ -89,7 +89,7 @@ export type TransportTraceEventBweStatsInfo = { startBitrate: number; maxPaddingBitrate: number; sendingRate: number; -} +}; /** * 'trace' event data. From 16f67a880047111a6e192eccc6f1c6095afe89f3 Mon Sep 17 00:00:00 2001 From: Eugene Voityuk Date: Tue, 24 Jan 2023 15:22:37 +0200 Subject: [PATCH 70/70] Fixes here and there, try to recover bitrate when recovered from instant loss. Extract rtx bitrate from available outgoing bitrate when distributing. --- .../call/rtp_transport_controller_send.cc | 1 + .../bitrate_controller/loss_based_bwe_v2.cc | 25 +++++++++++++++---- .../bitrate_controller/loss_based_bwe_v2.h | 5 +++- .../goog_cc/probe_controller.cc | 6 ++--- .../goog_cc/trendline_estimator.cc | 16 ++++++------ .../goog_cc/trendline_estimator.h | 1 - worker/src/RTC/Transport.cpp | 8 ++++++ 7 files changed, 45 insertions(+), 17 deletions(-) diff --git a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc index df553c7058..b9fe0c2b30 100644 --- a/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc +++ b/worker/deps/libwebrtc/libwebrtc/call/rtp_transport_controller_send.cc @@ -61,6 +61,7 @@ RtpTransportControllerSend::RtpTransportControllerSend( : packet_router_(packet_router), pacer_(packet_router_), observer_(nullptr), + stats_tracer_(nullptr), controller_factory_override_(controller_factory), process_interval_(controller_factory_override_->GetProcessInterval()), last_report_block_time_(Timestamp::ms(DepLibUV::GetTimeMsInt64())), diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc index 3ae3fede1e..d5af11a137 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.cc @@ -178,7 +178,7 @@ bool LossBasedBweV2::IsReady() const { num_observations_ > 0; } -LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { +LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() { Result result; result.state = current_state_; if (!IsReady()) { @@ -207,6 +207,20 @@ LossBasedBweV2::Result LossBasedBweV2::GetLossBasedResult() const { instant_limit.IsFinite() ? instant_limit.bps() : 0, GetAverageReportedLossRatio(), IsValid(acknowledged_bitrate_) ? acknowledged_bitrate_->bps() : -1);*/ + if (instant_loss_debounce_stop_.IsFinite() && (DepLibUV::GetTimeMsInt64() - instant_loss_debounce_stop_.ms()) < 500) { + auto decreased_rate = rate_before_last_instant_loss_ * 0.85; + MS_DEBUG_DEV("recently recovered from instant loss [rate_before_loss: %lld, recover_rate: %lld]", + rate_before_last_instant_loss_.bps(), + decreased_rate.bps() + ); + + result.bandwidth_estimate = decreased_rate; + current_estimate_.loss_limited_bandwidth = decreased_rate; + return result; + } else if (instant_loss_debounce_stop_.IsFinite() && (DepLibUV::GetTimeMsInt64() - instant_loss_debounce_stop_.ms()) > 500) { + instant_loss_debounce_stop_ = Timestamp::MinusInfinity(); + } + if (IsValid(delay_based_estimate_)) { result.bandwidth_estimate = std::min({current_estimate_.loss_limited_bandwidth, @@ -311,9 +325,9 @@ void LossBasedBweV2::UpdateBandwidthEstimate( current_estimate_.loss_limited_bandwidth; } - if (IsValid(delay_based_estimate_) && current_estimate_.inherent_loss > config_->inherent_loss_upper_bound_offset) { +/* if (IsValid(delay_based_estimate_) && current_estimate_.inherent_loss > config_->inherent_loss_upper_bound_offset) { best_candidate.loss_limited_bandwidth = delay_based_estimate_; - } + }*/ if (IsBandwidthLimitedDueToLoss()) { // Bound the estimate increase if: @@ -750,7 +764,7 @@ LossEstimatorState LossBasedBweV2::GetState() const { state.inherent_loss = current_estimate_.inherent_loss; state.avg_loss = GetAverageReportedLossRatio(); state.bandwidth_estimate = current_estimate_.loss_limited_bandwidth; - state.sending_rate = last_sending_rate_; + state.sending_rate = last_sending_rate_.IsFinite() ? last_sending_rate_ : DataRate::bps(0); return state; } @@ -1001,6 +1015,7 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { if (average_reported_loss_ratio < config_->instant_upper_bound_loss_offset) { instant_loss_debounce_start_ = Timestamp::MinusInfinity(); instant_loss_threshold_ = Timestamp::MinusInfinity(); + instant_loss_debounce_stop_ = now; MS_DEBUG_DEV("Resetting"); } } @@ -1023,7 +1038,7 @@ void LossBasedBweV2::CalculateInstantUpperBound(DataRate sending_rate) { instant_loss_debounce_start_ = now; instant_loss_threshold_ = now; MS_DEBUG_DEV("First Instant Loss"); - + rate_before_last_instant_loss_ = current_estimate; MS_DEBUG_DEV( "Reducing current estimate %lld by factor %f", current_estimate.bps(), diff --git a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h index 8f323d1d01..e14d44059e 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/bitrate_controller/loss_based_bwe_v2.h @@ -60,7 +60,7 @@ class LossBasedBweV2 { bool IsReady() const; // Returns `DataRate::PlusInfinity` if no BWE can be calculated. - Result GetLossBasedResult() const; + Result GetLossBasedResult(); void SetAcknowledgedBitrate(DataRate acknowledged_bitrate); void SetBandwidthEstimate(DataRate bandwidth_estimate); void SetMinMaxBitrate(DataRate min_bitrate, DataRate max_bitrate); @@ -208,8 +208,11 @@ class LossBasedBweV2 { TimeDelta kInstantLossDebounceDuration = TimeDelta::seconds(10); Timestamp instant_loss_debounce_start_ = Timestamp::MinusInfinity(); Timestamp instant_loss_threshold_ = Timestamp::MinusInfinity(); + float kInstantLossReduceFactor = 0.95; DataRate last_sending_rate_ = DataRate::PlusInfinity(); + DataRate rate_before_last_instant_loss_ = DataRate::PlusInfinity(); + Timestamp instant_loss_debounce_stop_ = Timestamp::MinusInfinity(); }; } // namespace webrtc diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc index 0cb7975a8c..d0866dd53b 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/probe_controller.cc @@ -9,7 +9,7 @@ */ #define MS_CLASS "webrtc::ProbeController" -//#define MS_LOG_DEV_LEVEL 3 +// #define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/probe_controller.h" #include "api/units/data_rate.h" @@ -101,12 +101,12 @@ ProbeControllerConfig::ProbeControllerConfig( min_probe_packets_sent("min_probe_packets_sent", 5), min_probe_duration("min_probe_duration", TimeDelta::ms(15)), limit_probe_target_rate_to_loss_bwe("limit_probe_target_rate_to_loss_bwe", - true), + false), loss_limited_probe_scale("loss_limited_scale", 1.5), skip_if_estimate_larger_than_fraction_of_max( "skip_if_est_larger_than_fraction_of_max", 0.0), - not_probe_if_delay_increased("not_probe_if_delay_increased", true) { + not_probe_if_delay_increased("not_probe_if_delay_increased", false) { ParseFieldTrial({&first_exponential_probe_scale, &second_exponential_probe_scale, &further_exponential_probe_scale, diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc index 649f8eb489..c23ed7c483 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.cc @@ -12,15 +12,16 @@ // #define MS_LOG_DEV_LEVEL 3 #include "modules/congestion_controller/goog_cc/trendline_estimator.h" - #include "modules/remote_bitrate_estimator/include/bwe_defines.h" #include "rtc_base/numerics/safe_minmax.h" +#include "DepLibUV.hpp" #include "Logger.hpp" #include -#include #include +#include +#include #include namespace webrtc { @@ -30,8 +31,8 @@ namespace { // Parameters for linear least squares fit of regression line to noisy data. constexpr double kDefaultTrendlineSmoothingCoeff = 0.9; constexpr double kDefaultTrendlineThresholdGain = 4.0; -constexpr double kDefaultRSquaredUpperBound = 0.95; -constexpr double kDefaultRSquaredLowerBound = 0.01; +constexpr double kDefaultRSquaredUpperBound = 0.20; +constexpr double kDefaultRSquaredLowerBound = 0.02; const char kBweWindowSizeInPacketsExperiment[] = "WebRTC-BweWindowSizeInPackets"; @@ -131,7 +132,7 @@ double getAverage(std::deque const& hist) { constexpr double kMaxAdaptOffsetMs = 15.0; constexpr double kOverUsingTimeThreshold = 10; constexpr int kMinNumDeltas = 60; -constexpr int kDeltaCounterMax = 1000; +constexpr int kDeltaCounterMax = 300; } // namespace @@ -256,13 +257,14 @@ void TrendlineEstimator::UpdateTrendline(double recv_delta_ms, // trend == 0 -> the delay does not change // trend < 0 -> the delay decreases, queues are being emptied result = LinearFitSlope(delay_hist_).value_or(trend); - if (result.slope > 0) { + //if (result.slope > 0) { r_squared_hist_.emplace_back(result.r_squared); if (r_squared_hist_.size() > settings_.window_size) r_squared_hist_.pop_front(); - } + //} avg_r_squared = getAverage(r_squared_hist_); trend.r_squared = avg_r_squared; + result.r_squared = avg_r_squared; if (settings_.enable_cap) { absl::optional cap = ComputeSlopeCap(delay_hist_, settings_); // We only use the cap to filter out overuse detections, not diff --git a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h index 32b3d04e01..e1a501ebb5 100644 --- a/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h +++ b/worker/deps/libwebrtc/libwebrtc/modules/congestion_controller/goog_cc/trendline_estimator.h @@ -98,7 +98,6 @@ class TrendlineEstimator : public DelayIncreaseDetectorInterface { double raw_delay_ms; }; - //DelayIncreaseDetectorInterface::RegressionResult GetTrend() override; DelayIncreaseDetectorInterface::RegressionResult GetTrend() override { return prev_trend_; diff --git a/worker/src/RTC/Transport.cpp b/worker/src/RTC/Transport.cpp index 2105c055cb..60d1093ba7 100644 --- a/worker/src/RTC/Transport.cpp +++ b/worker/src/RTC/Transport.cpp @@ -2308,7 +2308,14 @@ namespace RTC this->tccClient->RescheduleNextAvailableBitrateEvent(); + auto rtxSendBitrate = this->sendRtxTransmission.GetBitrate(DepLibUV::GetTimeMs()); + MS_DEBUG_DEV("before layer-by-layer iterations [availableBitrate:%" PRIu32 "]", availableBitrate); + MS_DEBUG_DEV( + "before layer-by-layer iterations [availableBitrate - sendRtxTransmission:%" PRIu32 "]", + availableBitrate - rtxSendBitrate); + + availableBitrate = availableBitrate - rtxSendBitrate; // Redistribute the available bitrate by allowing Consumers to increase // layer by layer. Initially try to spread the bitrate across all @@ -2960,6 +2967,7 @@ namespace RTC data["direction"] = "out"; data["info"]["estimatedBitrate"] = bweStats.estimated_bitrate.value_or(webrtc::DataRate::Zero()).bps(); + data["info"]["availableOutgoingBitrate"] = this->tccClient->GetAvailableBitrate(); data["info"]["delay"]["slope"] = bweStats.delay.trend.slope; data["info"]["delay"]["rSquared"] = bweStats.delay.trend.r_squared; data["info"]["delay"]["threshold"] = bweStats.delay.threshold;