Allow setting a bandwidth cap for relayed connections.

For now the capping is experimental and applied via a field trial.

Bug: webrtc:11434
Change-Id: Id8e6e9b948f099a0940974a9a431b5b0a43c32f0
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/171226
Commit-Queue: Christoffer Rodbro <crodbro@webrtc.org>
Reviewed-by: Sebastian Jansson <srte@webrtc.org>
Reviewed-by: Jonas Oreland <jonaso@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#30909}
This commit is contained in:
Christoffer Rodbro 2020-03-26 20:37:21 +01:00 committed by Commit Bot
parent 2a54ea96a1
commit 6404cddefb
5 changed files with 60 additions and 7 deletions

View File

@ -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",

View File

@ -79,6 +79,16 @@ RtpBitrateConfigurator::UpdateWithClientPreferences(
return UpdateConstraints(bitrate_mask.start_bitrate_bps);
}
// Relay cap can change only max bitrate.
absl::optional<BitrateConstraints> RtpBitrateConfigurator::UpdateWithRelayCap(
DataRate cap) {
if (cap.IsFinite()) {
RTC_DCHECK(!cap.IsZero());
}
max_bitrate_over_relay_ = cap;
return UpdateConstraints(absl::nullopt);
}
absl::optional<BitrateConstraints> RtpBitrateConfigurator::UpdateConstraints(
const absl::optional<int>& new_start) {
BitrateConstraints updated;
@ -89,6 +99,8 @@ absl::optional<BitrateConstraints> 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.

View File

@ -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<BitrateConstraints> UpdateWithClientPreferences(
const BitrateSettings& bitrate_mask);
// Apply a cap for relayed calls.
absl::optional<BitrateConstraints> 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

View File

@ -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<BitrateConstraints> 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<BitrateConstraints>
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) {

View File

@ -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<BitrateConstraints> 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<DataRate> relay_bandwidth_cap_;
size_t transport_overhead_bytes_per_packet_ RTC_GUARDED_BY(task_queue_);
bool network_available_ RTC_GUARDED_BY(task_queue_);