blob: f1afad3ea9b6a50f7e6f3f01d00aef53e4a55149 [file] [log] [blame]
/*
* Copyright 2025 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_SCREAM_DELAY_BASED_CONGESTION_CONTROL_H_
#define MODULES_CONGESTION_CONTROLLER_SCREAM_DELAY_BASED_CONGESTION_CONTROL_H_
#include <algorithm>
#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/congestion_controller/scream/scream_v2_parameters.h"
#include "rtc_base/numerics/windowed_min_filter.h"
namespace webrtc {
// Implements logic necessary for backing off if queue delay increase as
// proposed in
// https://datatracker.ietf.org/doc/draft-johansson-ccwg-rfc8298bis-screamv2/.
// The functionality is split out into a separate class since it may be possible
// to replace this logic with the trend line filter from Goog CC or a ML model.
class DelayBasedCongestionControl {
public:
explicit DelayBasedCongestionControl(ScreamV2Parameters params);
void OnTransportPacketsFeedback(const TransportPacketsFeedback& msg);
// Set a limit on how much the reference window can be reduced due to
// increased delay.
void SetMinDelayBasedBwe(DataRate min_delay_based_bwe) {
min_delay_based_bwe_ = min_delay_based_bwe;
}
// Returns true if queue delay is detected, but it may be low and does not
// necessarily mean reference window should be reduced. From 4.2.2.1.
// (queue_qdelay >= queue_delay_target * 0.25)
bool IsQueueDelayDetected() const;
// Returns true if queue delay is detected and reference window should be
// reduced. From 4.2.2.1. (queue_qdelay >= queue_delay_target*0.5)
bool ShouldReduceReferenceWindow() const;
DataSize UpdateReferenceWindow(DataSize rew_window,
double ref_window_mss_ratio) const;
// Returns false if the minimum queue delay has been above the drain threshold
// for a prolonged time. This can happen if minimum possible latency has
// increased, or queues has been filled for a longer period of time without
// being drained.
bool IsQueueDrainedInTime(Timestamp now) const {
return min_queue_delay_above_threshold_start_.IsInfinite() ||
(now - min_queue_delay_above_threshold_start_ <
params_.queue_delay_drain_period.Get());
}
// Resets queue delay estimates to start values.
void ResetQueueDelay();
double scale_increase() const {
return std::clamp(1 - queue_delay_avg_ / (params_.queue_delay_target.Get() *
params_.queue_delay_threshold),
0.1, 1.0);
}
TimeDelta queue_delay() const { return queue_delay_avg_; }
double queue_delay_dev_norm() const { return queue_delay_dev_norm_; }
TimeDelta rtt() const { return last_smoothed_rtt_; }
double l4s_alpha_v() const;
private:
TimeDelta min_base_delay() const {
return std::min(next_base_delay_, base_delay_history_.GetMin());
}
void UpdateSmoothedRtt(TimeDelta rtt_sample);
void UpdateQueueDelayAverage(TimeDelta one_way_delay);
const ScreamV2Parameters params_;
DataRate min_delay_based_bwe_;
// For computing min one way delay and compensate for clock drift.
// Based on https://datatracker.ietf.org/doc/html/rfc6817
Timestamp last_base_delay_update_ = Timestamp::MinusInfinity();
TimeDelta next_base_delay_ = TimeDelta::PlusInfinity();
WindowedMinFilter<TimeDelta> base_delay_history_;
Timestamp min_queue_delay_above_threshold_start_ = Timestamp::MinusInfinity();
TimeDelta last_smoothed_rtt_ = TimeDelta::Zero();
Timestamp last_update_qdelay_avg_time_ = Timestamp::MinusInfinity();
TimeDelta queue_delay_avg_ = TimeDelta::PlusInfinity();
double queue_delay_dev_norm_ = 0.0;
};
} // namespace webrtc
#endif // MODULES_CONGESTION_CONTROLLER_SCREAM_DELAY_BASED_CONGESTION_CONTROL_H_