blob: fbcc224780cbe951a85a78885c1a9ee65ba41a96 [file] [log] [blame]
// Copyright 2024 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "quiche/quic/moqt/moqt_bitrate_adjuster.h"
#include <cstdint>
#include <cstdlib>
#include <optional>
#include "quiche/quic/core/quic_bandwidth.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/common/platform/api/quiche_bug_tracker.h"
#include "quiche/common/platform/api/quiche_logging.h"
#include "quiche/web_transport/web_transport.h"
namespace moqt {
namespace {
using ::quic::QuicBandwidth;
using ::quic::QuicTime;
using ::quic::QuicTimeDelta;
} // namespace
void MoqtBitrateAdjuster::Start() {
if (start_time_.IsInitialized()) {
QUICHE_BUG(MoqtBitrateAdjuster_double_init)
<< "MoqtBitrateAdjuster::Start() called more than once.";
return;
}
start_time_ = clock_->Now();
}
void MoqtBitrateAdjuster::OnObjectAckReceived(
uint64_t /*group_id*/, uint64_t /*object_id*/,
QuicTimeDelta delta_from_deadline) {
if (!start_time_.IsInitialized()) {
return;
}
const QuicTime earliest_action_time = start_time_ + parameters_.initial_delay;
if (clock_->Now() < earliest_action_time) {
return;
}
if (delta_from_deadline < QuicTimeDelta::Zero()) {
// While adjusting down upon the first sign of packets getting late might
// seem aggressive, note that:
// - By the time user occurs, this is already a user-visible issue (so, in
// some sense, this isn't aggressive enough).
// - The adjustment won't happen if we're already bellow `k * max_bw`, so
// if the delays are due to other factors like bufferbloat, the measured
// bandwidth will likely not result in a downwards adjustment.
AttemptAdjustingDown();
}
}
void MoqtBitrateAdjuster::AttemptAdjustingDown() {
webtransport::SessionStats stats = session_->GetSessionStats();
QuicBandwidth target_bandwidth =
parameters_.target_bitrate_multiplier_down *
QuicBandwidth::FromBitsPerSecond(stats.estimated_send_rate_bps);
QUICHE_DLOG(INFO) << "Adjusting the bitrate down to " << target_bandwidth;
adjustable_->ConsiderAdjustingBitrate(target_bandwidth,
BitrateAdjustmentType::kDown);
}
void MoqtBitrateAdjuster::OnObjectAckSupportKnown(
std::optional<quic::QuicTimeDelta> time_window) {
if (!time_window.has_value() || *time_window <= QuicTimeDelta::Zero()) {
QUICHE_DLOG(WARNING)
<< "OBJECT_ACK not supported; bitrate adjustments will not work.";
return;
}
time_window_ = *time_window;
Start();
}
bool ShouldIgnoreBitrateAdjustment(quic::QuicBandwidth new_bitrate,
BitrateAdjustmentType type,
quic::QuicBandwidth old_bitrate,
float min_change) {
const float min_change_bps = old_bitrate.ToBitsPerSecond() * min_change;
const float change_bps =
new_bitrate.ToBitsPerSecond() - old_bitrate.ToBitsPerSecond();
if (std::abs(change_bps) < min_change_bps) {
return true;
}
switch (type) {
case moqt::BitrateAdjustmentType::kDown:
if (new_bitrate >= old_bitrate) {
return true;
}
break;
case moqt::BitrateAdjustmentType::kUp:
if (old_bitrate >= new_bitrate) {
return true;
}
break;
}
return false;
}
} // namespace moqt