diff --git a/call/BUILD.gn b/call/BUILD.gn index a33df1542b..3ef7bfa2b6 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -198,6 +198,7 @@ rtc_library("bitrate_configurator") { # For api/bitrate_constraints.h "../api:libjingle_peerconnection_api", "../api/transport:bitrate_settings", + "../api/units:data_rate", "../rtc_base:checks", "../rtc_base:rtc_base_approved", "//third_party/abseil-cpp/absl/types:optional", diff --git a/call/rtp_bitrate_configurator.cc b/call/rtp_bitrate_configurator.cc index 99ccfc98f7..264dcdcb81 100644 --- a/call/rtp_bitrate_configurator.cc +++ b/call/rtp_bitrate_configurator.cc @@ -79,6 +79,16 @@ RtpBitrateConfigurator::UpdateWithClientPreferences( return UpdateConstraints(bitrate_mask.start_bitrate_bps); } +// Relay cap can change only max bitrate. +absl::optional RtpBitrateConfigurator::UpdateWithRelayCap( + DataRate cap) { + if (cap.IsFinite()) { + RTC_DCHECK(!cap.IsZero()); + } + max_bitrate_over_relay_ = cap; + return UpdateConstraints(absl::nullopt); +} + absl::optional RtpBitrateConfigurator::UpdateConstraints( const absl::optional& new_start) { BitrateConstraints updated; @@ -89,6 +99,8 @@ absl::optional RtpBitrateConfigurator::UpdateConstraints( updated.max_bitrate_bps = MinPositive(bitrate_config_mask_.max_bitrate_bps.value_or(-1), base_bitrate_config_.max_bitrate_bps); + updated.max_bitrate_bps = + MinPositive(updated.max_bitrate_bps, max_bitrate_over_relay_.bps_or(-1)); // If the combined min ends up greater than the combined max, the max takes // priority. diff --git a/call/rtp_bitrate_configurator.h b/call/rtp_bitrate_configurator.h index 480ed9ee7c..73c4e41f63 100644 --- a/call/rtp_bitrate_configurator.h +++ b/call/rtp_bitrate_configurator.h @@ -13,6 +13,7 @@ #include "absl/types/optional.h" #include "api/transport/bitrate_settings.h" +#include "api/units/data_rate.h" #include "rtc_base/constructor_magic.h" namespace webrtc { @@ -44,6 +45,9 @@ class RtpBitrateConfigurator { absl::optional UpdateWithClientPreferences( const BitrateSettings& bitrate_mask); + // Apply a cap for relayed calls. + absl::optional UpdateWithRelayCap(DataRate cap); + private: // Applies update to the BitrateConstraints cached in |config_|, resetting // with |new_start| if set. @@ -62,6 +66,9 @@ class RtpBitrateConfigurator { // min >= 0, start != 0, max == -1 || max > 0 BitrateConstraints base_bitrate_config_; + // Bandwidth cap applied for relayed calls. + DataRate max_bitrate_over_relay_ = DataRate::PlusInfinity(); + RTC_DISALLOW_COPY_AND_ASSIGN(RtpBitrateConfigurator); }; } // namespace webrtc diff --git a/call/rtp_transport_controller_send.cc b/call/rtp_transport_controller_send.cc index 58772910b9..3147a2886f 100644 --- a/call/rtp_transport_controller_send.cc +++ b/call/rtp_transport_controller_send.cc @@ -63,13 +63,8 @@ bool IsEnabled(const WebRtcKeyValueConfig* trials, absl::string_view key) { return trials->Lookup(key).find("Enabled") == 0; } -bool IsRelevantRouteChange(const rtc::NetworkRoute& old_route, - const rtc::NetworkRoute& new_route) { - // TODO(bugs.webrtc.org/11438): Experiment with using more information/ - // other conditions. - return old_route.connected != new_route.connected || - old_route.local.network_id() != new_route.local.network_id() || - old_route.remote.network_id() != new_route.remote.network_id(); +bool IsRelayed(const rtc::NetworkRoute& route) { + return route.local.uses_turn() || route.remote.uses_turn(); } } // namespace @@ -114,12 +109,15 @@ RtpTransportControllerSend::RtpTransportControllerSend( IsEnabled(trials, "WebRTC-SendSideBwe-WithOverhead")), add_pacing_to_cwin_( IsEnabled(trials, "WebRTC-AddPacingToCongestionWindowPushback")), + relay_bandwidth_cap_("relay_cap", DataRate::PlusInfinity()), transport_overhead_bytes_per_packet_(0), network_available_(false), retransmission_rate_limiter_(clock, kRetransmitWindowSizeMs), task_queue_(task_queue_factory->CreateTaskQueue( "rtp_send_controller", TaskQueueFactory::Priority::NORMAL)) { + ParseFieldTrial({&relay_bandwidth_cap_}, + trials->Lookup("WebRTC-Bwe-NetworkRouteConstraints")); initial_config_.constraints = ConvertConstraints(bitrate_config, clock_); initial_config_.event_log = event_log; initial_config_.key_value_config = trials; @@ -254,6 +252,24 @@ void RtpTransportControllerSend::RegisterTargetTransferRateObserver( MaybeCreateControllers(); }); } + +bool RtpTransportControllerSend::IsRelevantRouteChange( + const rtc::NetworkRoute& old_route, + const rtc::NetworkRoute& new_route) const { + // TODO(bugs.webrtc.org/11438): Experiment with using more information/ + // other conditions. + bool connected_changed = old_route.connected != new_route.connected; + bool route_ids_changed = + old_route.local.network_id() != new_route.local.network_id() || + old_route.remote.network_id() != new_route.remote.network_id(); + if (relay_bandwidth_cap_->IsFinite()) { + bool relaying_changed = IsRelayed(old_route) != IsRelayed(new_route); + return connected_changed || route_ids_changed || relaying_changed; + } else { + return connected_changed || route_ids_changed; + } +} + void RtpTransportControllerSend::OnNetworkRouteChanged( const std::string& transport_name, const rtc::NetworkRoute& network_route) { @@ -265,6 +281,9 @@ void RtpTransportControllerSend::OnNetworkRouteChanged( return; } + absl::optional relay_constraint_update = + ApplyOrLiftRelayCap(IsRelayed(network_route)); + // Check whether the network route has changed on each transport. auto result = network_routes_.insert(std::make_pair(transport_name, network_route)); @@ -279,6 +298,9 @@ void RtpTransportControllerSend::OnNetworkRouteChanged( } if (inserted) { + if (relay_constraint_update.has_value()) { + UpdateBitrateConstraints(*relay_constraint_update); + } task_queue_.PostTask([this, network_route] { RTC_DCHECK_RUN_ON(&task_queue_); transport_overhead_bytes_per_packet_ = network_route.packet_overhead; @@ -432,6 +454,12 @@ void RtpTransportControllerSend::SetClientBitratePreferences( } } +absl::optional +RtpTransportControllerSend::ApplyOrLiftRelayCap(bool is_relayed) { + DataRate cap = is_relayed ? relay_bandwidth_cap_ : DataRate::PlusInfinity(); + return bitrate_configurator_.UpdateWithRelayCap(cap); +} + void RtpTransportControllerSend::OnTransportOverheadChanged( size_t transport_overhead_bytes_per_packet) { if (transport_overhead_bytes_per_packet >= kMaxOverheadBytes) { diff --git a/call/rtp_transport_controller_send.h b/call/rtp_transport_controller_send.h index 9671ba7522..e7310334cf 100644 --- a/call/rtp_transport_controller_send.h +++ b/call/rtp_transport_controller_send.h @@ -19,6 +19,7 @@ #include "api/network_state_predictor.h" #include "api/transport/network_control.h" +#include "api/units/data_rate.h" #include "call/rtp_bitrate_configurator.h" #include "call/rtp_transport_controller_send_interface.h" #include "call/rtp_video_sender.h" @@ -131,6 +132,9 @@ class RtpTransportControllerSend final void StartProcessPeriodicTasks() RTC_RUN_ON(task_queue_); void UpdateControllerWithTimeInterval() RTC_RUN_ON(task_queue_); + absl::optional ApplyOrLiftRelayCap(bool is_relayed); + bool IsRelevantRouteChange(const rtc::NetworkRoute& old_route, + const rtc::NetworkRoute& new_route) const; void UpdateBitrateConstraints(const BitrateConstraints& updated); void UpdateStreamsConfig() RTC_RUN_ON(task_queue_); void OnReceivedRtcpReceiverReportBlocks(const ReportBlockList& report_blocks, @@ -181,6 +185,7 @@ class RtpTransportControllerSend final const bool reset_feedback_on_route_change_; const bool send_side_bwe_with_overhead_; const bool add_pacing_to_cwin_; + FieldTrialParameter relay_bandwidth_cap_; size_t transport_overhead_bytes_per_packet_ RTC_GUARDED_BY(task_queue_); bool network_available_ RTC_GUARDED_BY(task_queue_);