mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 05:40:42 +01:00

This reverts commit 2f4bc64166
.
Reason for revert: Breaks downstream test
Original change's description:
> Clean up last_packet_received_time_ as it's no longer used.
>
> Bug: webrtc:15377
> Change-Id: I5453b9fd572a04dbea3241a2eb1c8ad8bb8b1186
> Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/320560
> Reviewed-by: Erik Språng <sprang@webrtc.org>
> Reviewed-by: Björn Terelius <terelius@webrtc.org>
> Commit-Queue: Ying Wang <yinwa@webrtc.org>
> Cr-Commit-Position: refs/heads/main@{#40792}
Bug: webrtc:15377
Change-Id: Ifa57671cc479cdd86f543c4edc236221beb76f90
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/321340
Auto-Submit: Björn Terelius <terelius@webrtc.org>
Reviewed-by: Ying Wang <yinwa@webrtc.org>
Owners-Override: Björn Terelius <terelius@webrtc.org>
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
Commit-Queue: Björn Terelius <terelius@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#40797}
391 lines
15 KiB
C++
391 lines
15 KiB
C++
/*
|
|
* 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/pcc/pcc_network_controller.h"
|
|
|
|
#include <algorithm>
|
|
|
|
#include "absl/types/optional.h"
|
|
#include "api/units/data_size.h"
|
|
#include "rtc_base/checks.h"
|
|
|
|
namespace webrtc {
|
|
namespace pcc {
|
|
namespace {
|
|
constexpr int64_t kInitialRttMs = 200;
|
|
constexpr int64_t kInitialBandwidthKbps = 300;
|
|
constexpr double kMonitorIntervalDurationRatio = 1;
|
|
constexpr double kDefaultSamplingStep = 0.05;
|
|
constexpr double kTimeoutRatio = 2;
|
|
constexpr double kAlphaForRtt = 0.9;
|
|
constexpr double kSlowStartModeIncrease = 1.5;
|
|
|
|
constexpr double kAlphaForPacketInterval = 0.9;
|
|
constexpr int64_t kMinPacketsNumberPerInterval = 20;
|
|
const TimeDelta kMinDurationOfMonitorInterval = TimeDelta::Millis(50);
|
|
const TimeDelta kStartupDuration = TimeDelta::Millis(500);
|
|
constexpr double kMinRateChangeBps = 4000;
|
|
constexpr DataRate kMinRateHaveMultiplicativeRateChange = DataRate::BitsPerSec(
|
|
static_cast<int64_t>(kMinRateChangeBps / kDefaultSamplingStep));
|
|
|
|
// Bitrate controller constants.
|
|
constexpr double kInitialConversionFactor = 5;
|
|
constexpr double kInitialDynamicBoundary = 0.1;
|
|
constexpr double kDynamicBoundaryIncrement = 0.1;
|
|
// Utility function parameters.
|
|
constexpr double kRttGradientCoefficientBps = 0.005;
|
|
constexpr double kLossCoefficientBps = 10;
|
|
constexpr double kThroughputCoefficient = 0.001;
|
|
constexpr double kThroughputPower = 0.9;
|
|
constexpr double kRttGradientThreshold = 0.01;
|
|
constexpr double kDelayGradientNegativeBound = 0.1;
|
|
|
|
constexpr int64_t kNumberOfPacketsToKeep = 20;
|
|
const uint64_t kRandomSeed = 100;
|
|
} // namespace
|
|
|
|
PccNetworkController::PccNetworkController(NetworkControllerConfig config)
|
|
: start_time_(Timestamp::PlusInfinity()),
|
|
last_sent_packet_time_(Timestamp::PlusInfinity()),
|
|
smoothed_packets_sending_interval_(TimeDelta::Zero()),
|
|
mode_(Mode::kStartup),
|
|
default_bandwidth_(DataRate::KilobitsPerSec(kInitialBandwidthKbps)),
|
|
bandwidth_estimate_(default_bandwidth_),
|
|
rtt_tracker_(TimeDelta::Millis(kInitialRttMs), kAlphaForRtt),
|
|
monitor_interval_timeout_(TimeDelta::Millis(kInitialRttMs) *
|
|
kTimeoutRatio),
|
|
monitor_interval_length_strategy_(MonitorIntervalLengthStrategy::kFixed),
|
|
monitor_interval_duration_ratio_(kMonitorIntervalDurationRatio),
|
|
sampling_step_(kDefaultSamplingStep),
|
|
monitor_interval_timeout_ratio_(kTimeoutRatio),
|
|
min_packets_number_per_interval_(kMinPacketsNumberPerInterval),
|
|
bitrate_controller_(kInitialConversionFactor,
|
|
kInitialDynamicBoundary,
|
|
kDynamicBoundaryIncrement,
|
|
kRttGradientCoefficientBps,
|
|
kLossCoefficientBps,
|
|
kThroughputCoefficient,
|
|
kThroughputPower,
|
|
kRttGradientThreshold,
|
|
kDelayGradientNegativeBound),
|
|
monitor_intervals_duration_(TimeDelta::Zero()),
|
|
complete_feedback_monitor_interval_number_(0),
|
|
random_generator_(kRandomSeed) {
|
|
if (config.constraints.starting_rate) {
|
|
default_bandwidth_ = *config.constraints.starting_rate;
|
|
bandwidth_estimate_ = default_bandwidth_;
|
|
}
|
|
}
|
|
|
|
PccNetworkController::~PccNetworkController() {}
|
|
|
|
NetworkControlUpdate PccNetworkController::CreateRateUpdate(
|
|
Timestamp at_time) const {
|
|
DataRate sending_rate = DataRate::Zero();
|
|
if (monitor_intervals_.empty() ||
|
|
(monitor_intervals_.size() >= monitor_intervals_bitrates_.size() &&
|
|
at_time >= monitor_intervals_.back().GetEndTime())) {
|
|
sending_rate = bandwidth_estimate_;
|
|
} else {
|
|
sending_rate = monitor_intervals_.back().GetTargetSendingRate();
|
|
}
|
|
// Set up config when sending rate is computed.
|
|
NetworkControlUpdate update;
|
|
|
|
// Set up target rate to encoder.
|
|
TargetTransferRate target_rate_msg;
|
|
target_rate_msg.at_time = at_time;
|
|
target_rate_msg.network_estimate.at_time = at_time;
|
|
target_rate_msg.network_estimate.round_trip_time = rtt_tracker_.GetRtt();
|
|
// TODO(koloskova): Add correct estimate.
|
|
target_rate_msg.network_estimate.loss_rate_ratio = 0;
|
|
target_rate_msg.network_estimate.bwe_period =
|
|
monitor_interval_duration_ratio_ * rtt_tracker_.GetRtt();
|
|
|
|
target_rate_msg.target_rate = sending_rate;
|
|
update.target_rate = target_rate_msg;
|
|
|
|
// Set up pacing/padding target rate.
|
|
PacerConfig pacer_config;
|
|
pacer_config.at_time = at_time;
|
|
pacer_config.time_window = TimeDelta::Millis(1);
|
|
pacer_config.data_window = sending_rate * pacer_config.time_window;
|
|
pacer_config.pad_window = sending_rate * pacer_config.time_window;
|
|
|
|
update.pacer_config = pacer_config;
|
|
return update;
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnSentPacket(SentPacket msg) {
|
|
// Start new monitor interval if previous has finished.
|
|
// Monitor interval is initialized in OnProcessInterval function.
|
|
if (start_time_.IsInfinite()) {
|
|
start_time_ = msg.send_time;
|
|
monitor_intervals_duration_ = kStartupDuration;
|
|
monitor_intervals_bitrates_ = {bandwidth_estimate_};
|
|
monitor_intervals_.emplace_back(bandwidth_estimate_, msg.send_time,
|
|
monitor_intervals_duration_);
|
|
complete_feedback_monitor_interval_number_ = 0;
|
|
}
|
|
if (last_sent_packet_time_.IsFinite()) {
|
|
smoothed_packets_sending_interval_ =
|
|
(msg.send_time - last_sent_packet_time_) * kAlphaForPacketInterval +
|
|
(1 - kAlphaForPacketInterval) * smoothed_packets_sending_interval_;
|
|
}
|
|
last_sent_packet_time_ = msg.send_time;
|
|
if (!monitor_intervals_.empty() &&
|
|
msg.send_time >= monitor_intervals_.back().GetEndTime() &&
|
|
monitor_intervals_bitrates_.size() > monitor_intervals_.size()) {
|
|
// Start new monitor interval.
|
|
monitor_intervals_.emplace_back(
|
|
monitor_intervals_bitrates_[monitor_intervals_.size()], msg.send_time,
|
|
monitor_intervals_duration_);
|
|
}
|
|
if (IsTimeoutExpired(msg.send_time)) {
|
|
DataSize received_size = DataSize::Zero();
|
|
for (size_t i = 1; i < last_received_packets_.size(); ++i) {
|
|
received_size += last_received_packets_[i].sent_packet.size;
|
|
}
|
|
TimeDelta sending_time = TimeDelta::Zero();
|
|
if (last_received_packets_.size() > 0)
|
|
sending_time = last_received_packets_.back().receive_time -
|
|
last_received_packets_.front().receive_time;
|
|
DataRate receiving_rate = bandwidth_estimate_;
|
|
if (sending_time > TimeDelta::Zero())
|
|
receiving_rate = received_size / sending_time;
|
|
bandwidth_estimate_ =
|
|
std::min<DataRate>(bandwidth_estimate_ * 0.5, receiving_rate);
|
|
if (mode_ == Mode::kSlowStart)
|
|
mode_ = Mode::kOnlineLearning;
|
|
}
|
|
if (mode_ == Mode::kStartup &&
|
|
msg.send_time - start_time_ >= kStartupDuration) {
|
|
DataSize received_size = DataSize::Zero();
|
|
for (size_t i = 1; i < last_received_packets_.size(); ++i) {
|
|
received_size += last_received_packets_[i].sent_packet.size;
|
|
}
|
|
TimeDelta sending_time = TimeDelta::Zero();
|
|
if (last_received_packets_.size() > 0)
|
|
sending_time = last_received_packets_.back().receive_time -
|
|
last_received_packets_.front().receive_time;
|
|
DataRate receiving_rate = bandwidth_estimate_;
|
|
if (sending_time > TimeDelta::Zero())
|
|
receiving_rate = received_size / sending_time;
|
|
bandwidth_estimate_ = receiving_rate;
|
|
monitor_intervals_.clear();
|
|
mode_ = Mode::kSlowStart;
|
|
monitor_intervals_duration_ = ComputeMonitorIntervalsDuration();
|
|
monitor_intervals_bitrates_ = {bandwidth_estimate_};
|
|
monitor_intervals_.emplace_back(bandwidth_estimate_, msg.send_time,
|
|
monitor_intervals_duration_);
|
|
bandwidth_estimate_ = bandwidth_estimate_ * (1 / kSlowStartModeIncrease);
|
|
complete_feedback_monitor_interval_number_ = 0;
|
|
return CreateRateUpdate(msg.send_time);
|
|
}
|
|
if (IsFeedbackCollectionDone() || IsTimeoutExpired(msg.send_time)) {
|
|
// Creating new monitor intervals.
|
|
monitor_intervals_.clear();
|
|
monitor_interval_timeout_ =
|
|
rtt_tracker_.GetRtt() * monitor_interval_timeout_ratio_;
|
|
monitor_intervals_duration_ = ComputeMonitorIntervalsDuration();
|
|
complete_feedback_monitor_interval_number_ = 0;
|
|
// Compute bitrates and start first monitor interval.
|
|
if (mode_ == Mode::kSlowStart) {
|
|
monitor_intervals_bitrates_ = {kSlowStartModeIncrease *
|
|
bandwidth_estimate_};
|
|
monitor_intervals_.emplace_back(
|
|
kSlowStartModeIncrease * bandwidth_estimate_, msg.send_time,
|
|
monitor_intervals_duration_);
|
|
} else {
|
|
RTC_DCHECK(mode_ == Mode::kOnlineLearning || mode_ == Mode::kDoubleCheck);
|
|
monitor_intervals_.clear();
|
|
int64_t sign = 2 * (random_generator_.Rand(0, 1) % 2) - 1;
|
|
RTC_DCHECK_GE(sign, -1);
|
|
RTC_DCHECK_LE(sign, 1);
|
|
if (bandwidth_estimate_ >= kMinRateHaveMultiplicativeRateChange) {
|
|
monitor_intervals_bitrates_ = {
|
|
bandwidth_estimate_ * (1 + sign * sampling_step_),
|
|
bandwidth_estimate_ * (1 - sign * sampling_step_)};
|
|
} else {
|
|
monitor_intervals_bitrates_ = {
|
|
DataRate::BitsPerSec(std::max<double>(
|
|
bandwidth_estimate_.bps() + sign * kMinRateChangeBps, 0)),
|
|
DataRate::BitsPerSec(std::max<double>(
|
|
bandwidth_estimate_.bps() - sign * kMinRateChangeBps, 0))};
|
|
}
|
|
monitor_intervals_.emplace_back(monitor_intervals_bitrates_[0],
|
|
msg.send_time,
|
|
monitor_intervals_duration_);
|
|
}
|
|
}
|
|
return CreateRateUpdate(msg.send_time);
|
|
}
|
|
|
|
TimeDelta PccNetworkController::ComputeMonitorIntervalsDuration() const {
|
|
TimeDelta monitor_intervals_duration = TimeDelta::Zero();
|
|
if (monitor_interval_length_strategy_ ==
|
|
MonitorIntervalLengthStrategy::kAdaptive) {
|
|
monitor_intervals_duration = std::max(
|
|
rtt_tracker_.GetRtt() * monitor_interval_duration_ratio_,
|
|
smoothed_packets_sending_interval_ * min_packets_number_per_interval_);
|
|
} else {
|
|
RTC_DCHECK(monitor_interval_length_strategy_ ==
|
|
MonitorIntervalLengthStrategy::kFixed);
|
|
monitor_intervals_duration =
|
|
smoothed_packets_sending_interval_ * min_packets_number_per_interval_;
|
|
}
|
|
monitor_intervals_duration =
|
|
std::max(kMinDurationOfMonitorInterval, monitor_intervals_duration);
|
|
return monitor_intervals_duration;
|
|
}
|
|
|
|
bool PccNetworkController::IsTimeoutExpired(Timestamp current_time) const {
|
|
if (complete_feedback_monitor_interval_number_ >= monitor_intervals_.size()) {
|
|
return false;
|
|
}
|
|
return current_time -
|
|
monitor_intervals_[complete_feedback_monitor_interval_number_]
|
|
.GetEndTime() >=
|
|
monitor_interval_timeout_;
|
|
}
|
|
|
|
bool PccNetworkController::IsFeedbackCollectionDone() const {
|
|
return complete_feedback_monitor_interval_number_ >=
|
|
monitor_intervals_bitrates_.size();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnTransportPacketsFeedback(
|
|
TransportPacketsFeedback msg) {
|
|
if (msg.packet_feedbacks.empty())
|
|
return NetworkControlUpdate();
|
|
// Save packets to last_received_packets_ array.
|
|
for (const PacketResult& packet_result : msg.ReceivedWithSendInfo()) {
|
|
last_received_packets_.push_back(packet_result);
|
|
}
|
|
while (last_received_packets_.size() > kNumberOfPacketsToKeep) {
|
|
last_received_packets_.pop_front();
|
|
}
|
|
rtt_tracker_.OnPacketsFeedback(msg.PacketsWithFeedback(), msg.feedback_time);
|
|
// Skip rate update in case when online learning mode just started, but
|
|
// corresponding monitor intervals were not started yet.
|
|
if (mode_ == Mode::kOnlineLearning &&
|
|
monitor_intervals_bitrates_.size() < 2) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
if (!IsFeedbackCollectionDone() && !monitor_intervals_.empty()) {
|
|
while (complete_feedback_monitor_interval_number_ <
|
|
monitor_intervals_.size()) {
|
|
monitor_intervals_[complete_feedback_monitor_interval_number_]
|
|
.OnPacketsFeedback(msg.PacketsWithFeedback());
|
|
if (!monitor_intervals_[complete_feedback_monitor_interval_number_]
|
|
.IsFeedbackCollectionDone())
|
|
break;
|
|
++complete_feedback_monitor_interval_number_;
|
|
}
|
|
}
|
|
if (IsFeedbackCollectionDone()) {
|
|
if (mode_ == Mode::kDoubleCheck) {
|
|
mode_ = Mode::kOnlineLearning;
|
|
} else if (NeedDoubleCheckMeasurments()) {
|
|
mode_ = Mode::kDoubleCheck;
|
|
}
|
|
if (mode_ != Mode::kDoubleCheck)
|
|
UpdateSendingRateAndMode();
|
|
}
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
bool PccNetworkController::NeedDoubleCheckMeasurments() const {
|
|
if (mode_ == Mode::kSlowStart) {
|
|
return false;
|
|
}
|
|
double first_loss_rate = monitor_intervals_[0].GetLossRate();
|
|
double second_loss_rate = monitor_intervals_[1].GetLossRate();
|
|
DataRate first_bitrate = monitor_intervals_[0].GetTargetSendingRate();
|
|
DataRate second_bitrate = monitor_intervals_[1].GetTargetSendingRate();
|
|
if ((first_bitrate.bps() - second_bitrate.bps()) *
|
|
(first_loss_rate - second_loss_rate) <
|
|
0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void PccNetworkController::UpdateSendingRateAndMode() {
|
|
if (monitor_intervals_.empty() || !IsFeedbackCollectionDone()) {
|
|
return;
|
|
}
|
|
if (mode_ == Mode::kSlowStart) {
|
|
DataRate old_bandwidth_estimate = bandwidth_estimate_;
|
|
bandwidth_estimate_ =
|
|
bitrate_controller_
|
|
.ComputeRateUpdateForSlowStartMode(monitor_intervals_[0])
|
|
.value_or(bandwidth_estimate_);
|
|
if (bandwidth_estimate_ <= old_bandwidth_estimate)
|
|
mode_ = Mode::kOnlineLearning;
|
|
} else {
|
|
RTC_DCHECK(mode_ == Mode::kOnlineLearning);
|
|
bandwidth_estimate_ =
|
|
bitrate_controller_.ComputeRateUpdateForOnlineLearningMode(
|
|
monitor_intervals_, bandwidth_estimate_);
|
|
}
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnNetworkAvailability(
|
|
NetworkAvailability msg) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnNetworkRouteChange(
|
|
NetworkRouteChange msg) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnProcessInterval(
|
|
ProcessInterval msg) {
|
|
return CreateRateUpdate(msg.at_time);
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnTargetRateConstraints(
|
|
TargetRateConstraints msg) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnRemoteBitrateReport(
|
|
RemoteBitrateReport) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnRoundTripTimeUpdate(
|
|
RoundTripTimeUpdate) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnTransportLossReport(
|
|
TransportLossReport) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnStreamsConfig(StreamsConfig msg) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnReceivedPacket(
|
|
ReceivedPacket msg) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
NetworkControlUpdate PccNetworkController::OnNetworkStateEstimate(
|
|
NetworkStateEstimate msg) {
|
|
return NetworkControlUpdate();
|
|
}
|
|
|
|
} // namespace pcc
|
|
} // namespace webrtc
|