mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-27 04:35:34 +08:00
[feat] add pacing controller module
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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;
|
||||
|
||||
118
src/transport/packet_sender.cpp
Normal file
118
src/transport/packet_sender.cpp
Normal 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_; }
|
||||
116
src/transport/packet_sender.h
Normal file
116
src/transport/packet_sender.h
Normal 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
|
||||
Reference in New Issue
Block a user