[feat] add pacing controller module

This commit is contained in:
dijunkun
2025-03-12 18:18:19 +08:00
parent 2bf60a9c81
commit 23df1f3b60
15 changed files with 2320 additions and 9 deletions

View File

@@ -52,6 +52,7 @@ void IceTransportController::Create(
CreateAudioCodec();
controller_ = std::make_unique<CongestionControl>();
packet_sender_ = std::make_unique<PacketSender>(ice_agent, webrtc_clock_);
resolution_adapter_ = std::make_unique<ResolutionAdapter>();
video_channel_send_ = std::make_unique<VideoChannelSend>(
@@ -471,7 +472,6 @@ void IceTransportController::PostUpdates(webrtc::NetworkControlUpdate update) {
target_bitrate_ = target_bitrate;
int width, height, target_width, target_height;
video_encoder_->GetResolution(&width, &height);
if (0 == resolution_adapter_->GetResolution(target_bitrate_, width,
height, &target_width,
&target_height)) {
@@ -480,19 +480,20 @@ void IceTransportController::PostUpdates(webrtc::NetworkControlUpdate update) {
target_height_ = target_height;
b_force_i_frame_ = true;
// LOG_INFO("Set target resolution [{}x{}]", target_width_.value(),
// target_height_.value());
}
} else if (target_width_.has_value() && target_height_.has_value()) {
target_width_.reset();
target_height_.reset();
// LOG_INFO("Use original resolution [{}x{}]", source_width_,
// source_height_);
}
video_encoder_->SetTargetBitrate(target_bitrate_);
LOG_WARN("Set target bitrate [{}]bps", target_bitrate_);
}
}
if (!update.probe_cluster_configs.empty()) {
packet_sender_->CreateProbeClusters(
std::move(update.probe_cluster_configs));
}
}
void IceTransportController::UpdateControlState() {

View File

@@ -14,12 +14,14 @@
#include "audio_channel_send.h"
#include "audio_decoder.h"
#include "audio_encoder.h"
#include "bitrate_prober.h"
#include "clock/system_clock.h"
#include "congestion_control.h"
#include "congestion_control_feedback.h"
#include "data_channel_receive.h"
#include "data_channel_send.h"
#include "ice_agent.h"
#include "packet_sender.h"
#include "resolution_adapter.h"
#include "transport_feedback_adapter.h"
#include "video_channel_receive.h"
@@ -103,7 +105,7 @@ class IceTransportController
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
std::shared_ptr<IOStatistics> ice_io_statistics_ = nullptr;
std::unique_ptr<RtpPacketizer> rtp_packetizer_ = nullptr;
std::unique_ptr<RtpVideoSender> rtp_video_sender_ = nullptr;
std::unique_ptr<PacketSender> packet_sender_ = nullptr;
std::string remote_user_id_;
void *user_data_ = nullptr;
@@ -112,6 +114,7 @@ class IceTransportController
std::shared_ptr<webrtc::Clock> webrtc_clock_ = nullptr;
webrtc::TransportFeedbackAdapter transport_feedback_adapter_;
std::unique_ptr<CongestionControl> controller_;
BitrateProber prober_;
private:
std::unique_ptr<VideoEncoder> video_encoder_ = nullptr;

View File

@@ -0,0 +1,118 @@
#include "packet_sender.h"
#include "log.h"
PacketSender::PacketSender(std::shared_ptr<IceAgent> ice_agent,
std::shared_ptr<webrtc::Clock> clock)
: ice_agent_(ice_agent),
clock_(clock),
pacing_controller_(clock.get(), this) {}
PacketSender::~PacketSender() {}
// int PacketSender::SendPacket(const char *data, size_t size) {
// LOG_INFO("Send packet, size: %d", size);
// return ice_agent_->Send(data, size);
// }
// void PacketSender::CreateProbeClusters(
// std::vector<webrtc::ProbeClusterConfig> probe_cluster_configs) {
// pacing_controller_.CreateProbeClusters(probe_cluster_configs);
// MaybeScheduleProcessPackets();
// }
// void PacketSender::MaybeScheduleProcessPackets() {
// if (!processing_packets_)
// MaybeProcessPackets(webrtc::Timestamp::MinusInfinity());
// }
// void PacketSender::MaybeProcessPackets(
// webrtc::Timestamp scheduled_process_time) {
// if (is_shutdown_ || !is_started_) {
// return;
// }
// // Protects against re-entry from transport feedback calling into the task
// // queue pacer.
// processing_packets_ = true;
// auto cleanup = std::unique_ptr<void, std::function<void(void *)>>(
// nullptr, [this](void *) { processing_packets_ = false; });
// webrtc::Timestamp next_send_time = pacing_controller_.NextSendTime();
// const webrtc::Timestamp now = clock_->CurrentTime();
// webrtc::TimeDelta early_execute_margin =
// pacing_controller_.IsProbing()
// ? webrtc::PacingController::kMaxEarlyProbeProcessing
// : webrtc::TimeDelta::Zero();
// // Process packets and update stats.
// while (next_send_time <= now + early_execute_margin) {
// pacing_controller_.ProcessPackets();
// next_send_time = pacing_controller_.NextSendTime();
// // Probing state could change. Get margin after process packets.
// early_execute_margin =
// pacing_controller_.IsProbing()
// ? webrtc::PacingController::kMaxEarlyProbeProcessing
// : webrtc::TimeDelta::Zero();
// }
// UpdateStats();
// // Ignore retired scheduled task, otherwise reset `next_process_time_`.
// if (scheduled_process_time.IsFinite()) {
// if (scheduled_process_time != next_process_time_) {
// return;
// }
// next_process_time_ = webrtc::Timestamp::MinusInfinity();
// }
// // Do not hold back in probing.
// webrtc::TimeDelta hold_back_window = webrtc::TimeDelta::Zero();
// if (!pacing_controller_.IsProbing()) {
// hold_back_window = max_hold_back_window_;
// webrtc::DataRate pacing_rate = pacing_controller_.pacing_rate();
// if (max_hold_back_window_in_packets_ != kNoPacketHoldback &&
// !pacing_rate.IsZero() &&
// packet_size_.filtered() != rtc::ExpFilter::kValueUndefined) {
// webrtc::TimeDelta avg_packet_send_time =
// webrtc::DataSize::Bytes(packet_size_.filtered()) / pacing_rate;
// hold_back_window =
// std::min(hold_back_window,
// avg_packet_send_time * max_hold_back_window_in_packets_);
// }
// }
// // Calculate next process time.
// webrtc::TimeDelta time_to_next_process =
// std::max(hold_back_window, next_send_time - now -
// early_execute_margin);
// next_send_time = now + time_to_next_process;
// // If no in flight task or in flight task is later than `next_send_time`,
// // schedule a new one. Previous in flight task will be retired.
// if (next_process_time_.IsMinusInfinity() ||
// next_process_time_ > next_send_time) {
// // Prefer low precision if allowed and not probing.
// task_queue_->PostDelayedHighPrecisionTask(
// SafeTask(
// safety_.flag(),
// [this, next_send_time]() { MaybeProcessPackets(next_send_time);
// }),
// time_to_next_process.RoundUpTo(webrtc::TimeDelta::Millis(1)));
// next_process_time_ = next_send_time;
// }
// }
// void PacketSender::UpdateStats() {
// Stats new_stats;
// new_stats.expected_queue_time = pacing_controller_.ExpectedQueueTime();
// new_stats.first_sent_packet_time =
// pacing_controller_.FirstSentPacketTime();
// new_stats.oldest_packet_enqueue_time =
// pacing_controller_.OldestPacketEnqueueTime();
// new_stats.queue_size = pacing_controller_.QueueSizeData();
// OnStatsUpdated(new_stats);
// }
// PacketSender::Stats PacketSender::GetStats() const { return current_stats_; }

View File

@@ -0,0 +1,116 @@
/*
* @Author: DI JUNKUN
* @Date: 2025-03-12
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
*/
#ifndef _PACKET_SENDER_H_
#define _PACKET_SENDER_H_
#include <memory>
#include "api/array_view.h"
#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 "ice_agent.h"
#include "pacing_controller.h"
#include "rtc_base/numerics/exp_filter.h"
#include "rtp_packet_pacer.h"
#include "rtp_packet_to_send.h"
class PacketSender : public webrtc::RtpPacketPacer,
public webrtc::PacingController::PacketSender {
public:
PacketSender(std::shared_ptr<IceAgent> ice_agent,
std::shared_ptr<webrtc::Clock> clock);
~PacketSender();
int SendPacket(const char* data, size_t size);
public:
void CreateProbeClusters(
std::vector<webrtc::ProbeClusterConfig> probe_cluster_configs) override{};
// Temporarily pause all sending.
void Pause() override{};
// Resume sending packets.
void Resume() override{};
void SetCongested(bool congested) override{};
// Sets the pacing rates. Must be called once before packets can be sent.
void SetPacingRates(webrtc::DataRate pacing_rate,
webrtc::DataRate padding_rate) override{};
// Time since the oldest packet currently in the queue was added.
webrtc::TimeDelta OldestPacketWaitTime() const override {
return webrtc::TimeDelta::Zero();
};
// Sum of payload + padding bytes of all packets currently in the pacer queue.
webrtc::DataSize QueueSizeData() const override {
return webrtc::DataSize::Zero();
};
// Returns the time when the first packet was sent.
std::optional<webrtc::Timestamp> FirstSentPacketTime() const override {
return {};
}
// Returns the expected number of milliseconds it will take to send the
// current packets in the queue, given the current size and bitrate, ignoring
// priority.
webrtc::TimeDelta ExpectedQueueTime() const override {
return webrtc::TimeDelta::Zero();
};
// Set the average upper bound on pacer queuing delay. The pacer may send at
// a higher rate than what was configured via SetPacingRates() in order to
// keep ExpectedQueueTimeMs() below `limit_ms` on average.
void SetQueueTimeLimit(webrtc::TimeDelta limit) override{};
// Currently audio traffic is not accounted by pacer and passed through.
// With the introduction of audio BWE audio traffic will be accounted for
// the pacer budget calculation. The audio traffic still will be injected
// at high priority.
void SetAccountForAudioPackets(bool account_for_audio) override{};
void SetIncludeOverhead() override{};
void SetTransportOverhead(webrtc::DataSize overhead_per_packet) override{};
public:
void SendPacket(std::unique_ptr<webrtc::RtpPacketToSend> packet,
const webrtc::PacedPacketInfo& cluster_info) override {}
// Should be called after each call to SendPacket().
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> FetchFec() override {
return {};
}
std::vector<std::unique_ptr<webrtc::RtpPacketToSend>> GeneratePadding(
webrtc::DataSize size) override {
return {};
}
// TODO(bugs.webrtc.org/1439830): Make pure once subclasses adapt.
void OnBatchComplete() override {}
// TODO(bugs.webrtc.org/11340): Make pure once downstream projects
// have been updated.
void OnAbortedRetransmissions(
uint32_t /* ssrc */,
rtc::ArrayView<const uint16_t> /* sequence_numbers */) {}
std::optional<uint32_t> GetRtxSsrcForMedia(
uint32_t /* ssrc */) const override {
return std::nullopt;
}
private:
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
webrtc::PacingController pacing_controller_;
private:
std::shared_ptr<webrtc::Clock> clock_ = nullptr;
};
#endif