Merges ControlHandler and PacerController.
This is part of a series of CLs preparing to remove SendSideCongestionController as a separate class. Bug: webrtc:9586 Change-Id: I0dabd00793e7b436a679d2ef695d2e557a35ae87 Reviewed-on: https://webrtc-review.googlesource.com/c/105420 Commit-Queue: Sebastian Jansson <srte@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Cr-Commit-Position: refs/heads/master@{#25178}
This commit is contained in:

committed by
Commit Bot

parent
7341ab60d0
commit
74c066c0c5
@ -21,8 +21,6 @@ rtc_static_library("congestion_controller") {
|
|||||||
configs += [ ":bwe_test_logging" ]
|
configs += [ ":bwe_test_logging" ]
|
||||||
sources = [
|
sources = [
|
||||||
"include/send_side_congestion_controller.h",
|
"include/send_side_congestion_controller.h",
|
||||||
"pacer_controller.cc",
|
|
||||||
"pacer_controller.h",
|
|
||||||
"send_side_congestion_controller.cc",
|
"send_side_congestion_controller.cc",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -32,6 +30,7 @@ rtc_static_library("congestion_controller") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
|
":control_handler",
|
||||||
":transport_feedback",
|
":transport_feedback",
|
||||||
"../:congestion_controller",
|
"../:congestion_controller",
|
||||||
"../..:module_api",
|
"../..:module_api",
|
||||||
@ -57,6 +56,38 @@ rtc_static_library("congestion_controller") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rtc_source_set("control_handler") {
|
||||||
|
visibility = [ "*" ]
|
||||||
|
sources = [
|
||||||
|
"control_handler.cc",
|
||||||
|
"control_handler.h",
|
||||||
|
]
|
||||||
|
|
||||||
|
if (!build_with_chromium && is_clang) {
|
||||||
|
# Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
|
||||||
|
suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
deps = [
|
||||||
|
"../:congestion_controller",
|
||||||
|
"../../../api/transport:network_control",
|
||||||
|
"../../../rtc_base:checks",
|
||||||
|
"../../../rtc_base:rate_limiter",
|
||||||
|
"../../../rtc_base:safe_minmax",
|
||||||
|
"../../../rtc_base:sequenced_task_checker",
|
||||||
|
"../../../rtc_base/experiments:congestion_controller_experiment",
|
||||||
|
"../../../system_wrappers",
|
||||||
|
"../../../system_wrappers:field_trial",
|
||||||
|
"../../pacing",
|
||||||
|
"../../remote_bitrate_estimator",
|
||||||
|
"../../rtp_rtcp:rtp_rtcp_format",
|
||||||
|
"//third_party/abseil-cpp/absl/memory",
|
||||||
|
]
|
||||||
|
|
||||||
|
if (!build_with_mozilla) {
|
||||||
|
deps += [ "../../../rtc_base:rtc_base" ]
|
||||||
|
}
|
||||||
|
}
|
||||||
rtc_static_library("transport_feedback") {
|
rtc_static_library("transport_feedback") {
|
||||||
visibility = [ "*" ]
|
visibility = [ "*" ]
|
||||||
sources = [
|
sources = [
|
||||||
|
163
modules/congestion_controller/rtp/control_handler.cc
Normal file
163
modules/congestion_controller/rtp/control_handler.cc
Normal file
@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "modules/congestion_controller/rtp/control_handler.h"
|
||||||
|
|
||||||
|
#include "rtc_base/checks.h"
|
||||||
|
#include "rtc_base/logging.h"
|
||||||
|
#include "rtc_base/numerics/safe_minmax.h"
|
||||||
|
#include "system_wrappers/include/field_trial.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
// When PacerPushbackExperiment is enabled, build-up in the pacer due to
|
||||||
|
// the congestion window and/or data spikes reduces encoder allocations.
|
||||||
|
const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment";
|
||||||
|
|
||||||
|
bool IsPacerPushbackExperimentEnabled() {
|
||||||
|
return field_trial::IsEnabled(kPacerPushbackExperiment);
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
CongestionControlHandler::CongestionControlHandler(
|
||||||
|
NetworkChangedObserver* observer,
|
||||||
|
PacedSender* pacer)
|
||||||
|
: observer_(observer),
|
||||||
|
pacer_(pacer),
|
||||||
|
pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()) {
|
||||||
|
sequenced_checker_.Detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
CongestionControlHandler::~CongestionControlHandler() {}
|
||||||
|
|
||||||
|
void CongestionControlHandler::PostUpdates(NetworkControlUpdate update) {
|
||||||
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
for (const auto& probe : update.probe_cluster_configs) {
|
||||||
|
int64_t bitrate_bps = probe.target_data_rate.bps();
|
||||||
|
pacer_->CreateProbeCluster(bitrate_bps);
|
||||||
|
}
|
||||||
|
if (update.target_rate) {
|
||||||
|
current_target_rate_msg_ = *update.target_rate;
|
||||||
|
OnNetworkInvalidation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CongestionControlHandler::OnNetworkAvailability(NetworkAvailability msg) {
|
||||||
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
||||||
|
if (network_available_ != msg.network_available) {
|
||||||
|
network_available_ = msg.network_available;
|
||||||
|
pacer_->UpdateOutstandingData(0);
|
||||||
|
SetPacerState(!msg.network_available);
|
||||||
|
OnNetworkInvalidation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CongestionControlHandler::OnOutstandingData(DataSize in_flight_data) {
|
||||||
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
||||||
|
pacer_->UpdateOutstandingData(in_flight_data.bytes());
|
||||||
|
OnNetworkInvalidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CongestionControlHandler::OnPacerQueueUpdate(
|
||||||
|
TimeDelta expected_queue_time) {
|
||||||
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
||||||
|
pacer_expected_queue_ms_ = expected_queue_time.ms();
|
||||||
|
OnNetworkInvalidation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CongestionControlHandler::SetPacerState(bool paused) {
|
||||||
|
if (paused && !pacer_paused_)
|
||||||
|
pacer_->Pause();
|
||||||
|
else if (!paused && pacer_paused_)
|
||||||
|
pacer_->Resume();
|
||||||
|
pacer_paused_ = paused;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CongestionControlHandler::OnNetworkInvalidation() {
|
||||||
|
if (!current_target_rate_msg_.has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t target_bitrate_bps = current_target_rate_msg_->target_rate.bps();
|
||||||
|
int64_t rtt_ms =
|
||||||
|
current_target_rate_msg_->network_estimate.round_trip_time.ms();
|
||||||
|
float loss_rate_ratio =
|
||||||
|
current_target_rate_msg_->network_estimate.loss_rate_ratio;
|
||||||
|
|
||||||
|
int loss_ratio_255 = loss_rate_ratio * 255;
|
||||||
|
uint8_t fraction_loss =
|
||||||
|
rtc::dchecked_cast<uint8_t>(rtc::SafeClamp(loss_ratio_255, 0, 255));
|
||||||
|
|
||||||
|
int64_t probing_interval_ms =
|
||||||
|
current_target_rate_msg_->network_estimate.bwe_period.ms();
|
||||||
|
|
||||||
|
if (!network_available_) {
|
||||||
|
target_bitrate_bps = 0;
|
||||||
|
} else if (!pacer_pushback_experiment_) {
|
||||||
|
target_bitrate_bps = IsSendQueueFull() ? 0 : target_bitrate_bps;
|
||||||
|
} else {
|
||||||
|
int64_t queue_length_ms = pacer_expected_queue_ms_;
|
||||||
|
|
||||||
|
if (queue_length_ms == 0) {
|
||||||
|
encoding_rate_ratio_ = 1.0;
|
||||||
|
} else if (queue_length_ms > 50) {
|
||||||
|
double encoding_ratio = 1.0 - queue_length_ms / 1000.0;
|
||||||
|
encoding_rate_ratio_ = std::min(encoding_rate_ratio_, encoding_ratio);
|
||||||
|
encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
target_bitrate_bps *= encoding_rate_ratio_;
|
||||||
|
target_bitrate_bps = target_bitrate_bps < 50000 ? 0 : target_bitrate_bps;
|
||||||
|
}
|
||||||
|
if (HasNetworkParametersToReportChanged(target_bitrate_bps, fraction_loss,
|
||||||
|
rtt_ms)) {
|
||||||
|
observer_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt_ms,
|
||||||
|
probing_interval_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool CongestionControlHandler::HasNetworkParametersToReportChanged(
|
||||||
|
int64_t target_bitrate_bps,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt_ms) {
|
||||||
|
bool changed = last_reported_target_bitrate_bps_ != target_bitrate_bps ||
|
||||||
|
(target_bitrate_bps > 0 &&
|
||||||
|
(last_reported_fraction_loss_ != fraction_loss ||
|
||||||
|
last_reported_rtt_ms_ != rtt_ms));
|
||||||
|
if (changed &&
|
||||||
|
(last_reported_target_bitrate_bps_ == 0 || target_bitrate_bps == 0)) {
|
||||||
|
RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: "
|
||||||
|
<< target_bitrate_bps << " bps.";
|
||||||
|
}
|
||||||
|
last_reported_target_bitrate_bps_ = target_bitrate_bps;
|
||||||
|
last_reported_fraction_loss_ = fraction_loss;
|
||||||
|
last_reported_rtt_ms_ = rtt_ms;
|
||||||
|
return changed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CongestionControlHandler::IsSendQueueFull() const {
|
||||||
|
return pacer_expected_queue_ms_ > PacedSender::kMaxQueueLengthMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
absl::optional<TargetTransferRate>
|
||||||
|
CongestionControlHandler::last_transfer_rate() {
|
||||||
|
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
||||||
|
return current_target_rate_msg_;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace webrtc
|
71
modules/congestion_controller/rtp/control_handler.h
Normal file
71
modules/congestion_controller/rtp/control_handler.h
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* 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 MODULES_CONGESTION_CONTROLLER_RTP_CONTROL_HANDLER_H_
|
||||||
|
#define MODULES_CONGESTION_CONTROLLER_RTP_CONTROL_HANDLER_H_
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include "api/transport/network_control.h"
|
||||||
|
#include "modules/congestion_controller/include/network_changed_observer.h"
|
||||||
|
#include "modules/pacing/paced_sender.h"
|
||||||
|
#include "rtc_base/sequenced_task_checker.h"
|
||||||
|
|
||||||
|
namespace webrtc {
|
||||||
|
// This is used to observe the network controller state and route calls to
|
||||||
|
// the proper handler. It also keeps cached values for safe asynchronous use.
|
||||||
|
// This makes sure that things running on the worker queue can't access state
|
||||||
|
// in SendSideCongestionController, which would risk causing data race on
|
||||||
|
// destruction unless members are properly ordered.
|
||||||
|
class CongestionControlHandler {
|
||||||
|
public:
|
||||||
|
CongestionControlHandler(NetworkChangedObserver* observer,
|
||||||
|
PacedSender* pacer);
|
||||||
|
~CongestionControlHandler();
|
||||||
|
|
||||||
|
void PostUpdates(NetworkControlUpdate update);
|
||||||
|
|
||||||
|
void OnNetworkAvailability(NetworkAvailability msg);
|
||||||
|
void OnOutstandingData(DataSize in_flight_data);
|
||||||
|
void OnPacerQueueUpdate(TimeDelta expected_queue_time);
|
||||||
|
|
||||||
|
absl::optional<TargetTransferRate> last_transfer_rate();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetPacerState(bool paused);
|
||||||
|
void OnNetworkInvalidation();
|
||||||
|
bool IsSendQueueFull() const;
|
||||||
|
bool HasNetworkParametersToReportChanged(int64_t bitrate_bps,
|
||||||
|
float loss_rate_ratio,
|
||||||
|
TimeDelta rtt);
|
||||||
|
|
||||||
|
bool HasNetworkParametersToReportChanged(int64_t bitrate_bps,
|
||||||
|
uint8_t fraction_loss,
|
||||||
|
int64_t rtt);
|
||||||
|
NetworkChangedObserver* observer_ = nullptr;
|
||||||
|
PacedSender* const pacer_;
|
||||||
|
|
||||||
|
absl::optional<TargetTransferRate> current_target_rate_msg_;
|
||||||
|
bool network_available_ = true;
|
||||||
|
bool pacer_paused_ = false;
|
||||||
|
int64_t last_reported_target_bitrate_bps_ = 0;
|
||||||
|
uint8_t last_reported_fraction_loss_ = 0;
|
||||||
|
int64_t last_reported_rtt_ms_ = 0;
|
||||||
|
const bool pacer_pushback_experiment_ = false;
|
||||||
|
uint32_t min_pushback_target_bitrate_bps_;
|
||||||
|
int64_t pacer_expected_queue_ms_ = 0;
|
||||||
|
double encoding_rate_ratio_ = 1.0;
|
||||||
|
|
||||||
|
rtc::SequencedTaskChecker sequenced_checker_;
|
||||||
|
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(CongestionControlHandler);
|
||||||
|
};
|
||||||
|
} // namespace webrtc
|
||||||
|
#endif // MODULES_CONGESTION_CONTROLLER_RTP_CONTROL_HANDLER_H_
|
@ -21,7 +21,7 @@
|
|||||||
#include "api/transport/network_types.h"
|
#include "api/transport/network_types.h"
|
||||||
#include "common_types.h" // NOLINT(build/include)
|
#include "common_types.h" // NOLINT(build/include)
|
||||||
#include "modules/congestion_controller/include/send_side_congestion_controller_interface.h"
|
#include "modules/congestion_controller/include/send_side_congestion_controller_interface.h"
|
||||||
#include "modules/congestion_controller/rtp/pacer_controller.h"
|
#include "modules/congestion_controller/rtp/control_handler.h"
|
||||||
#include "modules/congestion_controller/rtp/transport_feedback_adapter.h"
|
#include "modules/congestion_controller/rtp/transport_feedback_adapter.h"
|
||||||
#include "modules/include/module.h"
|
#include "modules/include/module.h"
|
||||||
#include "modules/include/module_common_types.h"
|
#include "modules/include/module_common_types.h"
|
||||||
@ -40,18 +40,11 @@ struct SentPacket;
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
class Clock;
|
class Clock;
|
||||||
class RateLimiter;
|
|
||||||
class RtcEventLog;
|
class RtcEventLog;
|
||||||
|
|
||||||
namespace webrtc_cc {
|
namespace webrtc_cc {
|
||||||
|
|
||||||
namespace send_side_cc_internal {
|
namespace send_side_cc_internal {
|
||||||
// This is used to observe the network controller state and route calls to
|
|
||||||
// the proper handler. It also keeps cached values for safe asynchronous use.
|
|
||||||
// This makes sure that things running on the worker queue can't access state
|
|
||||||
// in SendSideCongestionController, which would risk causing data race on
|
|
||||||
// destruction unless members are properly ordered.
|
|
||||||
class ControlHandler;
|
|
||||||
|
|
||||||
// TODO(srte): Make sure the PeriodicTask implementation is reusable and move it
|
// TODO(srte): Make sure the PeriodicTask implementation is reusable and move it
|
||||||
// to task_queue.h.
|
// to task_queue.h.
|
||||||
@ -182,10 +175,7 @@ class SendSideCongestionController
|
|||||||
const std::unique_ptr<NetworkControllerFactoryInterface>
|
const std::unique_ptr<NetworkControllerFactoryInterface>
|
||||||
controller_factory_fallback_ RTC_GUARDED_BY(task_queue_);
|
controller_factory_fallback_ RTC_GUARDED_BY(task_queue_);
|
||||||
|
|
||||||
const std::unique_ptr<PacerController> pacer_controller_
|
std::unique_ptr<CongestionControlHandler> control_handler_
|
||||||
RTC_GUARDED_BY(task_queue_);
|
|
||||||
|
|
||||||
std::unique_ptr<send_side_cc_internal::ControlHandler> control_handler_
|
|
||||||
RTC_GUARDED_BY(task_queue_);
|
RTC_GUARDED_BY(task_queue_);
|
||||||
|
|
||||||
std::unique_ptr<NetworkControllerInterface> controller_
|
std::unique_ptr<NetworkControllerInterface> controller_
|
||||||
|
@ -1,70 +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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "modules/congestion_controller/rtp/pacer_controller.h"
|
|
||||||
|
|
||||||
#include "rtc_base/checks.h"
|
|
||||||
#include "rtc_base/logging.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
|
|
||||||
PacerController::PacerController(PacedSender* pacer) : pacer_(pacer) {
|
|
||||||
sequenced_checker_.Detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
PacerController::~PacerController() = default;
|
|
||||||
|
|
||||||
void PacerController::OnCongestionWindow(DataSize congestion_window) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
if (congestion_window.IsFinite())
|
|
||||||
pacer_->SetCongestionWindow(congestion_window.bytes());
|
|
||||||
else
|
|
||||||
pacer_->SetCongestionWindow(PacedSender::kNoCongestionWindow);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacerController::OnNetworkAvailability(NetworkAvailability msg) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
network_available_ = msg.network_available;
|
|
||||||
pacer_->UpdateOutstandingData(0);
|
|
||||||
SetPacerState(!msg.network_available);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacerController::OnNetworkRouteChange(NetworkRouteChange) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
pacer_->UpdateOutstandingData(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacerController::OnPacerConfig(PacerConfig msg) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
DataRate pacing_rate = msg.data_window / msg.time_window;
|
|
||||||
DataRate padding_rate = msg.pad_window / msg.time_window;
|
|
||||||
pacer_->SetPacingRates(pacing_rate.bps(), padding_rate.bps());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacerController::OnProbeClusterConfig(ProbeClusterConfig config) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
int64_t bitrate_bps = config.target_data_rate.bps();
|
|
||||||
pacer_->CreateProbeCluster(bitrate_bps);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacerController::OnOutstandingData(DataSize in_flight_data) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
pacer_->UpdateOutstandingData(in_flight_data.bytes());
|
|
||||||
}
|
|
||||||
|
|
||||||
void PacerController::SetPacerState(bool paused) {
|
|
||||||
if (paused && !pacer_paused_)
|
|
||||||
pacer_->Pause();
|
|
||||||
else if (!paused && pacer_paused_)
|
|
||||||
pacer_->Resume();
|
|
||||||
pacer_paused_ = paused;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace webrtc
|
|
@ -1,50 +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 MODULES_CONGESTION_CONTROLLER_RTP_PACER_CONTROLLER_H_
|
|
||||||
#define MODULES_CONGESTION_CONTROLLER_RTP_PACER_CONTROLLER_H_
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "api/transport/network_types.h"
|
|
||||||
#include "modules/pacing/paced_sender.h"
|
|
||||||
#include "rtc_base/sequenced_task_checker.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
|
||||||
class Clock;
|
|
||||||
|
|
||||||
// Wrapper class to control pacer using task queues. Note that this class is
|
|
||||||
// only designed to be used from a single task queue and has no built in
|
|
||||||
// concurrency safety.
|
|
||||||
// TODO(srte): Integrate this interface directly into PacedSender.
|
|
||||||
class PacerController {
|
|
||||||
public:
|
|
||||||
explicit PacerController(PacedSender* pacer);
|
|
||||||
~PacerController();
|
|
||||||
void OnCongestionWindow(DataSize msg);
|
|
||||||
void OnNetworkAvailability(NetworkAvailability msg);
|
|
||||||
void OnNetworkRouteChange(NetworkRouteChange msg);
|
|
||||||
void OnOutstandingData(DataSize in_flight_data);
|
|
||||||
void OnPacerConfig(PacerConfig msg);
|
|
||||||
void OnProbeClusterConfig(ProbeClusterConfig msg);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void SetPacerState(bool paused);
|
|
||||||
PacedSender* const pacer_;
|
|
||||||
|
|
||||||
absl::optional<PacerConfig> current_pacer_config_;
|
|
||||||
bool pacer_paused_ = false;
|
|
||||||
bool network_available_ = true;
|
|
||||||
|
|
||||||
rtc::SequencedTaskChecker sequenced_checker_;
|
|
||||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(PacerController);
|
|
||||||
};
|
|
||||||
} // namespace webrtc
|
|
||||||
#endif // MODULES_CONGESTION_CONTROLLER_RTP_PACER_CONTROLLER_H_
|
|
@ -37,17 +37,8 @@ namespace webrtc {
|
|||||||
namespace webrtc_cc {
|
namespace webrtc_cc {
|
||||||
namespace {
|
namespace {
|
||||||
using send_side_cc_internal::PeriodicTask;
|
using send_side_cc_internal::PeriodicTask;
|
||||||
|
|
||||||
// When PacerPushbackExperiment is enabled, build-up in the pacer due to
|
|
||||||
// the congestion window and/or data spikes reduces encoder allocations.
|
|
||||||
const char kPacerPushbackExperiment[] = "WebRTC-PacerPushbackExperiment";
|
|
||||||
const int64_t PacerQueueUpdateIntervalMs = 25;
|
const int64_t PacerQueueUpdateIntervalMs = 25;
|
||||||
|
|
||||||
bool IsPacerPushbackExperimentEnabled() {
|
|
||||||
return webrtc::field_trial::IsEnabled(kPacerPushbackExperiment);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
TargetRateConstraints ConvertConstraints(int min_bitrate_bps,
|
TargetRateConstraints ConvertConstraints(int min_bitrate_bps,
|
||||||
int max_bitrate_bps,
|
int max_bitrate_bps,
|
||||||
int start_bitrate_bps,
|
int start_bitrate_bps,
|
||||||
@ -113,160 +104,6 @@ static PeriodicTask* StartPeriodicTask(rtc::TaskQueue* task_queue,
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
namespace send_side_cc_internal {
|
|
||||||
class ControlHandler {
|
|
||||||
public:
|
|
||||||
ControlHandler(NetworkChangedObserver* observer,
|
|
||||||
PacerController* pacer_controller,
|
|
||||||
const Clock* clock);
|
|
||||||
|
|
||||||
void PostUpdates(NetworkControlUpdate update);
|
|
||||||
|
|
||||||
void OnNetworkAvailability(NetworkAvailability msg);
|
|
||||||
void OnOutstandingData(DataSize in_flight_data);
|
|
||||||
void OnPacerQueueUpdate(TimeDelta expected_queue_time);
|
|
||||||
|
|
||||||
absl::optional<TargetTransferRate> last_transfer_rate();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OnNetworkInvalidation();
|
|
||||||
bool GetNetworkParameters(int32_t* estimated_bitrate_bps,
|
|
||||||
uint8_t* fraction_loss,
|
|
||||||
int64_t* rtt_ms);
|
|
||||||
bool IsSendQueueFull() const;
|
|
||||||
bool HasNetworkParametersToReportChanged(int64_t bitrate_bps,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt);
|
|
||||||
NetworkChangedObserver* observer_ = nullptr;
|
|
||||||
PacerController* pacer_controller_;
|
|
||||||
|
|
||||||
absl::optional<TargetTransferRate> current_target_rate_msg_;
|
|
||||||
bool network_available_ = true;
|
|
||||||
int64_t last_reported_target_bitrate_bps_ = 0;
|
|
||||||
uint8_t last_reported_fraction_loss_ = 0;
|
|
||||||
int64_t last_reported_rtt_ms_ = 0;
|
|
||||||
const bool pacer_pushback_experiment_ = false;
|
|
||||||
uint32_t min_pushback_target_bitrate_bps_;
|
|
||||||
int64_t pacer_expected_queue_ms_ = 0;
|
|
||||||
double encoding_rate_ratio_ = 1.0;
|
|
||||||
|
|
||||||
rtc::SequencedTaskChecker sequenced_checker_;
|
|
||||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(ControlHandler);
|
|
||||||
};
|
|
||||||
|
|
||||||
ControlHandler::ControlHandler(NetworkChangedObserver* observer,
|
|
||||||
PacerController* pacer_controller,
|
|
||||||
const Clock* clock)
|
|
||||||
: observer_(observer),
|
|
||||||
pacer_controller_(pacer_controller),
|
|
||||||
pacer_pushback_experiment_(IsPacerPushbackExperimentEnabled()) {
|
|
||||||
sequenced_checker_.Detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControlHandler::PostUpdates(NetworkControlUpdate update) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
if (update.congestion_window) {
|
|
||||||
pacer_controller_->OnCongestionWindow(*update.congestion_window);
|
|
||||||
}
|
|
||||||
if (update.pacer_config) {
|
|
||||||
pacer_controller_->OnPacerConfig(*update.pacer_config);
|
|
||||||
}
|
|
||||||
for (const auto& probe : update.probe_cluster_configs) {
|
|
||||||
pacer_controller_->OnProbeClusterConfig(probe);
|
|
||||||
}
|
|
||||||
if (update.target_rate) {
|
|
||||||
current_target_rate_msg_ = *update.target_rate;
|
|
||||||
OnNetworkInvalidation();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControlHandler::OnNetworkAvailability(NetworkAvailability msg) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
network_available_ = msg.network_available;
|
|
||||||
OnNetworkInvalidation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControlHandler::OnOutstandingData(DataSize in_flight_data) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
OnNetworkInvalidation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControlHandler::OnPacerQueueUpdate(TimeDelta expected_queue_time) {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
pacer_expected_queue_ms_ = expected_queue_time.ms();
|
|
||||||
OnNetworkInvalidation();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ControlHandler::OnNetworkInvalidation() {
|
|
||||||
if (!current_target_rate_msg_.has_value())
|
|
||||||
return;
|
|
||||||
|
|
||||||
uint32_t target_bitrate_bps = current_target_rate_msg_->target_rate.bps();
|
|
||||||
int64_t rtt_ms =
|
|
||||||
current_target_rate_msg_->network_estimate.round_trip_time.ms();
|
|
||||||
float loss_rate_ratio =
|
|
||||||
current_target_rate_msg_->network_estimate.loss_rate_ratio;
|
|
||||||
|
|
||||||
int loss_ratio_255 = loss_rate_ratio * 255;
|
|
||||||
uint8_t fraction_loss =
|
|
||||||
rtc::dchecked_cast<uint8_t>(rtc::SafeClamp(loss_ratio_255, 0, 255));
|
|
||||||
|
|
||||||
int64_t probing_interval_ms =
|
|
||||||
current_target_rate_msg_->network_estimate.bwe_period.ms();
|
|
||||||
|
|
||||||
if (!network_available_) {
|
|
||||||
target_bitrate_bps = 0;
|
|
||||||
} else if (!pacer_pushback_experiment_) {
|
|
||||||
target_bitrate_bps = IsSendQueueFull() ? 0 : target_bitrate_bps;
|
|
||||||
} else {
|
|
||||||
int64_t queue_length_ms = pacer_expected_queue_ms_;
|
|
||||||
|
|
||||||
if (queue_length_ms == 0) {
|
|
||||||
encoding_rate_ratio_ = 1.0;
|
|
||||||
} else if (queue_length_ms > 50) {
|
|
||||||
double encoding_ratio = 1.0 - queue_length_ms / 1000.0;
|
|
||||||
encoding_rate_ratio_ = std::min(encoding_rate_ratio_, encoding_ratio);
|
|
||||||
encoding_rate_ratio_ = std::max(encoding_rate_ratio_, 0.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
target_bitrate_bps *= encoding_rate_ratio_;
|
|
||||||
target_bitrate_bps = target_bitrate_bps < 50000 ? 0 : target_bitrate_bps;
|
|
||||||
}
|
|
||||||
if (HasNetworkParametersToReportChanged(target_bitrate_bps, fraction_loss,
|
|
||||||
rtt_ms)) {
|
|
||||||
observer_->OnNetworkChanged(target_bitrate_bps, fraction_loss, rtt_ms,
|
|
||||||
probing_interval_ms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bool ControlHandler::HasNetworkParametersToReportChanged(
|
|
||||||
int64_t target_bitrate_bps,
|
|
||||||
uint8_t fraction_loss,
|
|
||||||
int64_t rtt_ms) {
|
|
||||||
bool changed = last_reported_target_bitrate_bps_ != target_bitrate_bps ||
|
|
||||||
(target_bitrate_bps > 0 &&
|
|
||||||
(last_reported_fraction_loss_ != fraction_loss ||
|
|
||||||
last_reported_rtt_ms_ != rtt_ms));
|
|
||||||
if (changed &&
|
|
||||||
(last_reported_target_bitrate_bps_ == 0 || target_bitrate_bps == 0)) {
|
|
||||||
RTC_LOG(LS_INFO) << "Bitrate estimate state changed, BWE: "
|
|
||||||
<< target_bitrate_bps << " bps.";
|
|
||||||
}
|
|
||||||
last_reported_target_bitrate_bps_ = target_bitrate_bps;
|
|
||||||
last_reported_fraction_loss_ = fraction_loss;
|
|
||||||
last_reported_rtt_ms_ = rtt_ms;
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ControlHandler::IsSendQueueFull() const {
|
|
||||||
return pacer_expected_queue_ms_ > PacedSender::kMaxQueueLengthMs;
|
|
||||||
}
|
|
||||||
|
|
||||||
absl::optional<TargetTransferRate> ControlHandler::last_transfer_rate() {
|
|
||||||
RTC_DCHECK_CALLED_SEQUENTIALLY(&sequenced_checker_);
|
|
||||||
return current_target_rate_msg_;
|
|
||||||
}
|
|
||||||
} // namespace send_side_cc_internal
|
|
||||||
|
|
||||||
SendSideCongestionController::SendSideCongestionController(
|
SendSideCongestionController::SendSideCongestionController(
|
||||||
const Clock* clock,
|
const Clock* clock,
|
||||||
rtc::TaskQueue* task_queue,
|
rtc::TaskQueue* task_queue,
|
||||||
@ -282,7 +119,6 @@ SendSideCongestionController::SendSideCongestionController(
|
|||||||
controller_factory_with_feedback_(controller_factory),
|
controller_factory_with_feedback_(controller_factory),
|
||||||
controller_factory_fallback_(
|
controller_factory_fallback_(
|
||||||
absl::make_unique<GoogCcNetworkControllerFactory>(event_log)),
|
absl::make_unique<GoogCcNetworkControllerFactory>(event_log)),
|
||||||
pacer_controller_(absl::make_unique<PacerController>(pacer_)),
|
|
||||||
process_interval_(controller_factory_fallback_->GetProcessInterval()),
|
process_interval_(controller_factory_fallback_->GetProcessInterval()),
|
||||||
last_report_block_time_(Timestamp::ms(clock_->TimeInMilliseconds())),
|
last_report_block_time_(Timestamp::ms(clock_->TimeInMilliseconds())),
|
||||||
observer_(nullptr),
|
observer_(nullptr),
|
||||||
@ -328,8 +164,8 @@ void SendSideCongestionController::MaybeRecreateControllers() {
|
|||||||
if (!network_available_ || !observer_)
|
if (!network_available_ || !observer_)
|
||||||
return;
|
return;
|
||||||
if (!control_handler_) {
|
if (!control_handler_) {
|
||||||
control_handler_ = absl::make_unique<send_side_cc_internal::ControlHandler>(
|
control_handler_ =
|
||||||
observer_, pacer_controller_.get(), clock_);
|
absl::make_unique<CongestionControlHandler>(observer_, pacer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
initial_config_.constraints.at_time =
|
initial_config_.constraints.at_time =
|
||||||
@ -435,7 +271,7 @@ void SendSideCongestionController::OnNetworkRouteChanged(
|
|||||||
} else {
|
} else {
|
||||||
UpdateInitialConstraints(msg.constraints);
|
UpdateInitialConstraints(msg.constraints);
|
||||||
}
|
}
|
||||||
pacer_controller_->OnNetworkRouteChange(msg);
|
pacer_->UpdateOutstandingData(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -502,7 +338,6 @@ void SendSideCongestionController::SignalNetworkState(NetworkState state) {
|
|||||||
network_available_ = msg.network_available;
|
network_available_ = msg.network_available;
|
||||||
if (controller_) {
|
if (controller_) {
|
||||||
control_handler_->PostUpdates(controller_->OnNetworkAvailability(msg));
|
control_handler_->PostUpdates(controller_->OnNetworkAvailability(msg));
|
||||||
pacer_controller_->OnNetworkAvailability(msg);
|
|
||||||
control_handler_->OnNetworkAvailability(msg);
|
control_handler_->OnNetworkAvailability(msg);
|
||||||
} else {
|
} else {
|
||||||
MaybeCreateControllers();
|
MaybeCreateControllers();
|
||||||
@ -624,7 +459,6 @@ void SendSideCongestionController::MaybeUpdateOutstandingData() {
|
|||||||
DataSize in_flight_data = transport_feedback_adapter_.GetOutstandingData();
|
DataSize in_flight_data = transport_feedback_adapter_.GetOutstandingData();
|
||||||
task_queue_->PostTask([this, in_flight_data]() {
|
task_queue_->PostTask([this, in_flight_data]() {
|
||||||
RTC_DCHECK_RUN_ON(task_queue_);
|
RTC_DCHECK_RUN_ON(task_queue_);
|
||||||
pacer_controller_->OnOutstandingData(in_flight_data);
|
|
||||||
if (control_handler_)
|
if (control_handler_)
|
||||||
control_handler_->OnOutstandingData(in_flight_data);
|
control_handler_->OnOutstandingData(in_flight_data);
|
||||||
});
|
});
|
||||||
|
Reference in New Issue
Block a user