mirror of
https://github.com/kunkundi/crossdesk.git
synced 2025-10-26 20:25:34 +08:00
[feat] enable congestion controller set target bitrate to video encoder
This commit is contained in:
@@ -9,14 +9,15 @@ VideoChannelSend::~VideoChannelSend() {}
|
|||||||
|
|
||||||
VideoChannelSend::VideoChannelSend(
|
VideoChannelSend::VideoChannelSend(
|
||||||
std::shared_ptr<webrtc::Clock> clock, std::shared_ptr<IceAgent> ice_agent,
|
std::shared_ptr<webrtc::Clock> clock, std::shared_ptr<IceAgent> ice_agent,
|
||||||
std::shared_ptr<IOStatistics> ice_io_statistics)
|
std::shared_ptr<IOStatistics> ice_io_statistics,
|
||||||
|
std::function<void(const webrtc::RtpPacketToSend& packet)>
|
||||||
|
on_sent_packet_func)
|
||||||
: ice_agent_(ice_agent),
|
: ice_agent_(ice_agent),
|
||||||
ice_io_statistics_(ice_io_statistics),
|
ice_io_statistics_(ice_io_statistics),
|
||||||
|
on_sent_packet_func_(on_sent_packet_func),
|
||||||
clock_(clock){};
|
clock_(clock){};
|
||||||
|
|
||||||
void VideoChannelSend::Initialize(rtp::PAYLOAD_TYPE payload_type) {
|
void VideoChannelSend::Initialize(rtp::PAYLOAD_TYPE payload_type) {
|
||||||
controller_ = std::make_unique<CongestionControl>();
|
|
||||||
|
|
||||||
rtp_video_sender_ = std::make_unique<RtpVideoSender>(ice_io_statistics_);
|
rtp_video_sender_ = std::make_unique<RtpVideoSender>(ice_io_statistics_);
|
||||||
rtp_packetizer_ =
|
rtp_packetizer_ =
|
||||||
RtpPacketizer::Create(payload_type, rtp_video_sender_->GetSsrc());
|
RtpPacketizer::Create(payload_type, rtp_video_sender_->GetSsrc());
|
||||||
@@ -43,23 +44,7 @@ void VideoChannelSend::Initialize(rtp::PAYLOAD_TYPE payload_type) {
|
|||||||
|
|
||||||
rtp_video_sender_->SetOnSentPacketFunc(
|
rtp_video_sender_->SetOnSentPacketFunc(
|
||||||
[this](const webrtc::RtpPacketToSend& packet) -> void {
|
[this](const webrtc::RtpPacketToSend& packet) -> void {
|
||||||
webrtc::PacedPacketInfo pacing_info;
|
on_sent_packet_func_(packet);
|
||||||
size_t transport_overhead_bytes_per_packet_ = 0;
|
|
||||||
webrtc::Timestamp creation_time =
|
|
||||||
webrtc::Timestamp::Millis(clock_->TimeInMilliseconds());
|
|
||||||
transport_feedback_adapter_.AddPacket(
|
|
||||||
packet, pacing_info, transport_overhead_bytes_per_packet_,
|
|
||||||
creation_time);
|
|
||||||
|
|
||||||
rtc::SentPacket sent_packet;
|
|
||||||
sent_packet.packet_id = packet.transport_sequence_number().value();
|
|
||||||
sent_packet.send_time_ms = clock_->TimeInMilliseconds();
|
|
||||||
sent_packet.info.included_in_feedback = true;
|
|
||||||
sent_packet.info.included_in_allocation = true;
|
|
||||||
sent_packet.info.packet_size_bytes = packet.size();
|
|
||||||
sent_packet.info.packet_type = rtc::PacketType::kData;
|
|
||||||
|
|
||||||
transport_feedback_adapter_.ProcessSentPacket(sent_packet);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
rtp_video_sender_->Start();
|
rtp_video_sender_->Start();
|
||||||
@@ -80,66 +65,3 @@ int VideoChannelSend::SendVideo(char* data, size_t size) {
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VideoChannelSend::OnCongestionControlFeedback(
|
|
||||||
Timestamp recv_ts,
|
|
||||||
const webrtc::rtcp::CongestionControlFeedback& feedback) {
|
|
||||||
++feedback_count_;
|
|
||||||
std::optional<webrtc::TransportPacketsFeedback> feedback_msg =
|
|
||||||
transport_feedback_adapter_.ProcessCongestionControlFeedback(feedback,
|
|
||||||
recv_ts);
|
|
||||||
if (feedback_msg) {
|
|
||||||
HandleTransportPacketsFeedback(*feedback_msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoChannelSend::HandleTransportPacketsFeedback(
|
|
||||||
const webrtc::TransportPacketsFeedback& feedback) {
|
|
||||||
// if (transport_is_ecn_capable_) {
|
|
||||||
// // If transport does not support ECN, packets should not be sent as
|
|
||||||
// ECT(1).
|
|
||||||
// // TODO: bugs.webrtc.org/42225697 - adapt to ECN feedback and
|
|
||||||
// continue to
|
|
||||||
// // send packets as ECT(1) if transport is ECN capable.
|
|
||||||
// transport_is_ecn_capable_ = false;
|
|
||||||
// LOG_INFO("Transport is {} ECN capable. Stop sending ECT(1)",
|
|
||||||
// (feedback.transport_supports_ecn ? "" : " not "));
|
|
||||||
// }
|
|
||||||
if (controller_)
|
|
||||||
PostUpdates(controller_->OnTransportPacketsFeedback(feedback));
|
|
||||||
|
|
||||||
// Only update outstanding data if any packet is first time acked.
|
|
||||||
UpdateCongestedState();
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoChannelSend::PostUpdates(webrtc::NetworkControlUpdate update) {
|
|
||||||
// if (update.congestion_window) {
|
|
||||||
// congestion_window_size_ = *update.congestion_window;
|
|
||||||
// UpdateCongestedState();
|
|
||||||
// }
|
|
||||||
// if (update.pacer_config) {
|
|
||||||
// pacer_.SetPacingRates(update.pacer_config->data_rate(),
|
|
||||||
// update.pacer_config->pad_rate());
|
|
||||||
// }
|
|
||||||
// if (!update.probe_cluster_configs.empty()) {
|
|
||||||
// pacer_.CreateProbeClusters(std::move(update.probe_cluster_configs));
|
|
||||||
// }
|
|
||||||
// if (update.target_rate) {
|
|
||||||
// control_handler_->SetTargetRate(*update.target_rate);
|
|
||||||
// UpdateControlState();
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoChannelSend::UpdateControlState() {
|
|
||||||
// std::optional<TargetTransferRate> update =
|
|
||||||
// control_handler_->GetUpdate(); if (!update) return;
|
|
||||||
// retransmission_rate_limiter_.SetMaxRate(update->target_rate.bps());
|
|
||||||
// observer_->OnTargetTransferRate(*update);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VideoChannelSend::UpdateCongestedState() {
|
|
||||||
// if (auto update = GetCongestedStateUpdate()) {
|
|
||||||
// is_congested_ = update.value();
|
|
||||||
// pacer_.SetCongested(update.value());
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
@@ -23,7 +23,9 @@ class VideoChannelSend {
|
|||||||
VideoChannelSend();
|
VideoChannelSend();
|
||||||
VideoChannelSend(std::shared_ptr<webrtc::Clock> clock,
|
VideoChannelSend(std::shared_ptr<webrtc::Clock> clock,
|
||||||
std::shared_ptr<IceAgent> ice_agent,
|
std::shared_ptr<IceAgent> ice_agent,
|
||||||
std::shared_ptr<IOStatistics> ice_io_statistics);
|
std::shared_ptr<IOStatistics> ice_io_statistics,
|
||||||
|
std::function<void(const webrtc::RtpPacketToSend& packet)>
|
||||||
|
on_sent_packet_func_);
|
||||||
~VideoChannelSend();
|
~VideoChannelSend();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -50,15 +52,11 @@ class VideoChannelSend {
|
|||||||
std::unique_ptr<RtpPacketizer> rtp_packetizer_ = nullptr;
|
std::unique_ptr<RtpPacketizer> rtp_packetizer_ = nullptr;
|
||||||
std::unique_ptr<RtpVideoSender> rtp_video_sender_ = nullptr;
|
std::unique_ptr<RtpVideoSender> rtp_video_sender_ = nullptr;
|
||||||
|
|
||||||
|
std::function<void(const webrtc::RtpPacketToSend& packet)>
|
||||||
|
on_sent_packet_func_ = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<Clock> clock_;
|
std::shared_ptr<Clock> clock_;
|
||||||
int64_t current_offset_ = std::numeric_limits<int64_t>::min();
|
|
||||||
// Used by RFC 8888 congestion control feedback to track base time.
|
|
||||||
std::optional<uint32_t> last_feedback_compact_ntp_time_;
|
|
||||||
int feedback_count_ = 0;
|
|
||||||
|
|
||||||
webrtc::TransportFeedbackAdapter transport_feedback_adapter_;
|
|
||||||
std::unique_ptr<CongestionControl> controller_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -359,6 +359,11 @@ int AomAv1Encoder::ForceIdr() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AomAv1Encoder::SetTargetBitrate(int bitrate) {
|
||||||
|
target_bitrate_ = bitrate;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int AomAv1Encoder::Release() {
|
int AomAv1Encoder::Release() {
|
||||||
if (frame_for_encode_ != nullptr) {
|
if (frame_for_encode_ != nullptr) {
|
||||||
aom_img_free(frame_for_encode_);
|
aom_img_free(frame_for_encode_);
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ class AomAv1Encoder : public VideoEncoder {
|
|||||||
|
|
||||||
int ForceIdr();
|
int ForceIdr();
|
||||||
|
|
||||||
|
int SetTargetBitrate(int bitrate);
|
||||||
|
|
||||||
std::string GetEncoderName() { return "AomAV1"; }
|
std::string GetEncoderName() { return "AomAV1"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -221,6 +221,25 @@ int NvidiaVideoEncoder::ForceIdr() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int NvidiaVideoEncoder::SetTargetBitrate(int bitrate) {
|
||||||
|
if (!encoder_) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
NV_ENC_RECONFIGURE_PARAMS reconfig_params;
|
||||||
|
reconfig_params.version = NV_ENC_RECONFIGURE_PARAMS_VER;
|
||||||
|
NV_ENC_INITIALIZE_PARAMS init_params;
|
||||||
|
NV_ENC_CONFIG encode_config = {NV_ENC_CONFIG_VER};
|
||||||
|
init_params.encodeConfig = &encode_config;
|
||||||
|
encoder_->GetInitializeParams(&init_params);
|
||||||
|
init_params.frameRateDen = 1;
|
||||||
|
init_params.frameRateNum = init_params.frameRateDen * fps_;
|
||||||
|
init_params.encodeConfig->rcParams.averageBitRate = average_bitrate_;
|
||||||
|
init_params.encodeConfig->rcParams.maxBitRate = bitrate;
|
||||||
|
reconfig_params.reInitEncodeParams = init_params;
|
||||||
|
return encoder_->Reconfigure(&reconfig_params) ? 0 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
int NvidiaVideoEncoder::ResetEncodeResolution(unsigned int width,
|
int NvidiaVideoEncoder::ResetEncodeResolution(unsigned int width,
|
||||||
unsigned int height) {
|
unsigned int height) {
|
||||||
if (!encoder_) {
|
if (!encoder_) {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ class NvidiaVideoEncoder : public VideoEncoder {
|
|||||||
|
|
||||||
int ForceIdr();
|
int ForceIdr();
|
||||||
|
|
||||||
|
int SetTargetBitrate(int bitrate);
|
||||||
|
|
||||||
std::string GetEncoderName() { return "NvidiaH264"; }
|
std::string GetEncoderName() { return "NvidiaH264"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -50,6 +52,7 @@ class NvidiaVideoEncoder : public VideoEncoder {
|
|||||||
uint32_t key_frame_interval_ = 3000;
|
uint32_t key_frame_interval_ = 3000;
|
||||||
uint32_t average_bitrate_ = 2000000;
|
uint32_t average_bitrate_ = 2000000;
|
||||||
uint32_t max_bitrate_ = 10000000;
|
uint32_t max_bitrate_ = 10000000;
|
||||||
|
uint32_t fps_ = 30;
|
||||||
int max_payload_size_ = 3000;
|
int max_payload_size_ = 3000;
|
||||||
NvEncoder* encoder_ = nullptr;
|
NvEncoder* encoder_ = nullptr;
|
||||||
CUcontext cuda_context_ = nullptr;
|
CUcontext cuda_context_ = nullptr;
|
||||||
|
|||||||
@@ -359,6 +359,13 @@ int OpenH264Encoder::ForceIdr() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int OpenH264Encoder::SetTargetBitrate(int bitrate) {
|
||||||
|
target_bitrate_ = bitrate;
|
||||||
|
encoder_params_.iTargetBitrate = target_bitrate_;
|
||||||
|
|
||||||
|
return openh264_encoder_->SetOption(ENCODER_OPTION_BITRATE, &target_bitrate_);
|
||||||
|
}
|
||||||
|
|
||||||
int OpenH264Encoder::Release() {
|
int OpenH264Encoder::Release() {
|
||||||
if (openh264_encoder_) {
|
if (openh264_encoder_) {
|
||||||
openh264_encoder_->Uninitialize();
|
openh264_encoder_->Uninitialize();
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ class OpenH264Encoder : public VideoEncoder {
|
|||||||
|
|
||||||
int ForceIdr();
|
int ForceIdr();
|
||||||
|
|
||||||
|
int SetTargetBitrate(int bitrate);
|
||||||
|
|
||||||
std::string GetEncoderName() { return "OpenH264"; }
|
std::string GetEncoderName() { return "OpenH264"; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ class VideoEncoder {
|
|||||||
|
|
||||||
virtual int ForceIdr() = 0;
|
virtual int ForceIdr() = 0;
|
||||||
|
|
||||||
|
virtual int SetTargetBitrate(int bitrate) = 0;
|
||||||
|
|
||||||
virtual std::string GetEncoderName() = 0;
|
virtual std::string GetEncoderName() = 0;
|
||||||
|
|
||||||
VideoEncoder() = default;
|
VideoEncoder() = default;
|
||||||
|
|||||||
@@ -602,11 +602,8 @@ void PeerConnection::ProcessIceWorkMsg(const IceWorkMsg &msg) {
|
|||||||
hardware_acceleration_, trickle_ice_, reliable_ice_, enable_turn_,
|
hardware_acceleration_, trickle_ice_, reliable_ice_, enable_turn_,
|
||||||
false, video_payload_types_, audio_payload_types_);
|
false, video_payload_types_, audio_payload_types_);
|
||||||
|
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveVideoFunc(
|
ice_transport_list_[remote_user_id]->SetOnReceiveFunc(
|
||||||
on_receive_video_frame_);
|
on_receive_video_frame_, on_receive_audio_buffer_,
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveAudioFunc(
|
|
||||||
on_receive_audio_buffer_);
|
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveDataFunc(
|
|
||||||
on_receive_data_buffer_);
|
on_receive_data_buffer_);
|
||||||
|
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveNetStatusReportFunc(
|
ice_transport_list_[remote_user_id]->SetOnReceiveNetStatusReportFunc(
|
||||||
@@ -649,11 +646,8 @@ void PeerConnection::ProcessIceWorkMsg(const IceWorkMsg &msg) {
|
|||||||
hardware_acceleration_, trickle_ice_, reliable_ice_, enable_turn_,
|
hardware_acceleration_, trickle_ice_, reliable_ice_, enable_turn_,
|
||||||
false, video_payload_types_, audio_payload_types_);
|
false, video_payload_types_, audio_payload_types_);
|
||||||
|
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveVideoFunc(
|
ice_transport_list_[remote_user_id]->SetOnReceiveFunc(
|
||||||
on_receive_video_frame_);
|
on_receive_video_frame_, on_receive_audio_buffer_,
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveAudioFunc(
|
|
||||||
on_receive_audio_buffer_);
|
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveDataFunc(
|
|
||||||
on_receive_data_buffer_);
|
on_receive_data_buffer_);
|
||||||
|
|
||||||
ice_transport_list_[remote_user_id]->SetOnReceiveNetStatusReportFunc(
|
ice_transport_list_[remote_user_id]->SetOnReceiveNetStatusReportFunc(
|
||||||
|
|||||||
@@ -21,6 +21,32 @@ constexpr float kDefaultPaceMultiplier = 2.5f;
|
|||||||
// below the current throughput estimate to drain the network queues.
|
// below the current throughput estimate to drain the network queues.
|
||||||
constexpr double kProbeDropThroughputFraction = 0.85;
|
constexpr double kProbeDropThroughputFraction = 0.85;
|
||||||
|
|
||||||
|
BandwidthLimitedCause GetBandwidthLimitedCause(LossBasedState loss_based_state,
|
||||||
|
bool is_rtt_above_limit,
|
||||||
|
BandwidthUsage bandwidth_usage) {
|
||||||
|
if (bandwidth_usage == BandwidthUsage::kBwOverusing ||
|
||||||
|
bandwidth_usage == BandwidthUsage::kBwUnderusing) {
|
||||||
|
return BandwidthLimitedCause::kDelayBasedLimitedDelayIncreased;
|
||||||
|
} else if (is_rtt_above_limit) {
|
||||||
|
return BandwidthLimitedCause::kRttBasedBackOffHighRtt;
|
||||||
|
}
|
||||||
|
switch (loss_based_state) {
|
||||||
|
case LossBasedState::kDecreasing:
|
||||||
|
// Probes may not be sent in this state.
|
||||||
|
return BandwidthLimitedCause::kLossLimitedBwe;
|
||||||
|
case webrtc::LossBasedState::kIncreaseUsingPadding:
|
||||||
|
// Probes may not be sent in this state.
|
||||||
|
return BandwidthLimitedCause::kLossLimitedBwe;
|
||||||
|
case LossBasedState::kIncreasing:
|
||||||
|
// Probes may be sent in this state.
|
||||||
|
return BandwidthLimitedCause::kLossLimitedBweIncreasing;
|
||||||
|
case LossBasedState::kDelayBasedEstimate:
|
||||||
|
return BandwidthLimitedCause::kDelayBasedLimited;
|
||||||
|
default:
|
||||||
|
return BandwidthLimitedCause::kLossLimitedBwe;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
CongestionControl::CongestionControl()
|
CongestionControl::CongestionControl()
|
||||||
: packet_feedback_only_(true),
|
: packet_feedback_only_(true),
|
||||||
use_min_allocatable_as_lower_bound_(false),
|
use_min_allocatable_as_lower_bound_(false),
|
||||||
@@ -179,13 +205,13 @@ NetworkControlUpdate CongestionControl::OnTransportPacketsFeedback(
|
|||||||
bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time,
|
bandwidth_estimation_->UpdateDelayBasedEstimate(report.feedback_time,
|
||||||
result.target_bitrate);
|
result.target_bitrate);
|
||||||
}
|
}
|
||||||
// bandwidth_estimation_->UpdateLossBasedEstimator(
|
bandwidth_estimation_->UpdateLossBasedEstimator(
|
||||||
// report, result.delay_detector_state, probe_bitrate,
|
report, result.delay_detector_state, probe_bitrate,
|
||||||
// alr_start_time.has_value());
|
alr_start_time.has_value());
|
||||||
// if (result.updated) {
|
if (result.updated) {
|
||||||
// // Update the estimate in the ProbeController, in case we want to probe.
|
// Update the estimate in the ProbeController, in case we want to probe.
|
||||||
// MaybeTriggerOnNetworkChanged(&update, report.feedback_time);
|
MaybeTriggerOnNetworkChanged(&update, report.feedback_time);
|
||||||
// }
|
}
|
||||||
|
|
||||||
recovered_from_overuse = result.recovered_from_overuse;
|
recovered_from_overuse = result.recovered_from_overuse;
|
||||||
|
|
||||||
@@ -214,14 +240,13 @@ NetworkControlUpdate CongestionControl::OnTransportPacketsFeedback(
|
|||||||
|
|
||||||
void CongestionControl::MaybeTriggerOnNetworkChanged(
|
void CongestionControl::MaybeTriggerOnNetworkChanged(
|
||||||
NetworkControlUpdate* update, Timestamp at_time) {
|
NetworkControlUpdate* update, Timestamp at_time) {
|
||||||
// uint8_t fraction_loss = bandwidth_estimation_->fraction_loss();
|
uint8_t fraction_loss = bandwidth_estimation_->fraction_loss();
|
||||||
// TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time();
|
TimeDelta round_trip_time = bandwidth_estimation_->round_trip_time();
|
||||||
// DataRate loss_based_target_rate = bandwidth_estimation_->target_rate();
|
DataRate loss_based_target_rate = bandwidth_estimation_->target_rate();
|
||||||
// LossBasedState loss_based_state =
|
LossBasedState loss_based_state = bandwidth_estimation_->loss_based_state();
|
||||||
// bandwidth_estimation_->loss_based_state(); DataRate pushback_target_rate =
|
DataRate pushback_target_rate = loss_based_target_rate;
|
||||||
// loss_based_target_rate;
|
|
||||||
|
|
||||||
// double cwnd_reduce_ratio = 0.0;
|
double cwnd_reduce_ratio = 0.0;
|
||||||
// if (congestion_window_pushback_controller_) {
|
// if (congestion_window_pushback_controller_) {
|
||||||
// int64_t pushback_rate =
|
// int64_t pushback_rate =
|
||||||
// congestion_window_pushback_controller_->UpdateTargetBitrate(
|
// congestion_window_pushback_controller_->UpdateTargetBitrate(
|
||||||
@@ -235,53 +260,88 @@ void CongestionControl::MaybeTriggerOnNetworkChanged(
|
|||||||
// loss_based_target_rate.bps();
|
// loss_based_target_rate.bps();
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
// DataRate stable_target_rate =
|
DataRate stable_target_rate =
|
||||||
// bandwidth_estimation_->GetEstimatedLinkCapacity();
|
bandwidth_estimation_->GetEstimatedLinkCapacity();
|
||||||
// stable_target_rate = std::min(stable_target_rate, pushback_target_rate);
|
stable_target_rate = std::min(stable_target_rate, pushback_target_rate);
|
||||||
|
|
||||||
// if ((loss_based_target_rate != last_loss_based_target_rate_) ||
|
if ((loss_based_target_rate != last_loss_based_target_rate_) ||
|
||||||
// (loss_based_state != last_loss_base_state_) ||
|
(loss_based_state != last_loss_base_state_) ||
|
||||||
// (fraction_loss != last_estimated_fraction_loss_) ||
|
(fraction_loss != last_estimated_fraction_loss_) ||
|
||||||
// (round_trip_time != last_estimated_round_trip_time_) ||
|
(round_trip_time != last_estimated_round_trip_time_) ||
|
||||||
// (pushback_target_rate != last_pushback_target_rate_) ||
|
(pushback_target_rate != last_pushback_target_rate_) ||
|
||||||
// (stable_target_rate != last_stable_target_rate_)) {
|
(stable_target_rate != last_stable_target_rate_)) {
|
||||||
// last_loss_based_target_rate_ = loss_based_target_rate;
|
last_loss_based_target_rate_ = loss_based_target_rate;
|
||||||
// last_pushback_target_rate_ = pushback_target_rate;
|
last_pushback_target_rate_ = pushback_target_rate;
|
||||||
// last_estimated_fraction_loss_ = fraction_loss;
|
last_estimated_fraction_loss_ = fraction_loss;
|
||||||
// last_estimated_round_trip_time_ = round_trip_time;
|
last_estimated_round_trip_time_ = round_trip_time;
|
||||||
// last_stable_target_rate_ = stable_target_rate;
|
last_stable_target_rate_ = stable_target_rate;
|
||||||
// last_loss_base_state_ = loss_based_state;
|
last_loss_base_state_ = loss_based_state;
|
||||||
|
|
||||||
// alr_detector_->SetEstimatedBitrate(loss_based_target_rate.bps());
|
alr_detector_->SetEstimatedBitrate(loss_based_target_rate.bps());
|
||||||
|
|
||||||
// TimeDelta bwe_period = delay_based_bwe_->GetExpectedBwePeriod();
|
TimeDelta bwe_period = delay_based_bwe_->GetExpectedBwePeriod();
|
||||||
|
|
||||||
// TargetTransferRate target_rate_msg;
|
TargetTransferRate target_rate_msg;
|
||||||
// target_rate_msg.at_time = at_time;
|
target_rate_msg.at_time = at_time;
|
||||||
// if (rate_control_settings_.UseCongestionWindowDropFrameOnly()) {
|
// if (rate_control_settings_.UseCongestionWindowDropFrameOnly()) {
|
||||||
// target_rate_msg.target_rate = loss_based_target_rate;
|
// target_rate_msg.target_rate = loss_based_target_rate;
|
||||||
// target_rate_msg.cwnd_reduce_ratio = cwnd_reduce_ratio;
|
// target_rate_msg.cwnd_reduce_ratio = cwnd_reduce_ratio;
|
||||||
// } else {
|
// } else
|
||||||
// target_rate_msg.target_rate = pushback_target_rate;
|
{ target_rate_msg.target_rate = pushback_target_rate; }
|
||||||
// }
|
target_rate_msg.stable_target_rate = stable_target_rate;
|
||||||
// target_rate_msg.stable_target_rate = stable_target_rate;
|
target_rate_msg.network_estimate.at_time = at_time;
|
||||||
// target_rate_msg.network_estimate.at_time = at_time;
|
target_rate_msg.network_estimate.round_trip_time = round_trip_time;
|
||||||
// target_rate_msg.network_estimate.round_trip_time = round_trip_time;
|
target_rate_msg.network_estimate.loss_rate_ratio = fraction_loss / 255.0f;
|
||||||
// target_rate_msg.network_estimate.loss_rate_ratio = fraction_loss /
|
target_rate_msg.network_estimate.bwe_period = bwe_period;
|
||||||
// 255.0f; target_rate_msg.network_estimate.bwe_period = bwe_period;
|
|
||||||
|
|
||||||
// update->target_rate = target_rate_msg;
|
update->target_rate = target_rate_msg;
|
||||||
|
|
||||||
// auto probes = probe_controller_->SetEstimatedBitrate(
|
auto probes = probe_controller_->SetEstimatedBitrate(
|
||||||
// loss_based_target_rate,
|
loss_based_target_rate,
|
||||||
// GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state(),
|
GetBandwidthLimitedCause(bandwidth_estimation_->loss_based_state(),
|
||||||
// bandwidth_estimation_->IsRttAboveLimit(),
|
bandwidth_estimation_->IsRttAboveLimit(),
|
||||||
// delay_based_bwe_->last_state()),
|
delay_based_bwe_->last_state()),
|
||||||
// at_time);
|
at_time);
|
||||||
// update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
|
update->probe_cluster_configs.insert(update->probe_cluster_configs.end(),
|
||||||
// probes.begin(), probes.end());
|
probes.begin(), probes.end());
|
||||||
// update->pacer_config = GetPacingRates(at_time);
|
update->pacer_config = GetPacingRates(at_time);
|
||||||
// LOG_INFO("bwe {} pushback_target_bps={} estimate_bps={}", at_time.ms(),
|
// LOG_INFO("bwe {} pushback_target_bps={} estimate_bps={}", at_time.ms(),
|
||||||
// last_pushback_target_rate_.bps(), loss_based_target_rate.bps());
|
// last_pushback_target_rate_.bps(), loss_based_target_rate.bps());
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PacerConfig CongestionControl::GetPacingRates(Timestamp at_time) const {
|
||||||
|
// Pacing rate is based on target rate before congestion window pushback,
|
||||||
|
// because we don't want to build queues in the pacer when pushback occurs.
|
||||||
|
DataRate pacing_rate = DataRate::Zero();
|
||||||
|
if (pace_at_max_of_bwe_and_lower_link_capacity_ && estimate_ &&
|
||||||
|
!bandwidth_estimation_->PaceAtLossBasedEstimate()) {
|
||||||
|
pacing_rate =
|
||||||
|
std::max({min_total_allocated_bitrate_, estimate_->link_capacity_lower,
|
||||||
|
last_loss_based_target_rate_}) *
|
||||||
|
pacing_factor_;
|
||||||
|
} else {
|
||||||
|
pacing_rate =
|
||||||
|
std::max(min_total_allocated_bitrate_, last_loss_based_target_rate_) *
|
||||||
|
pacing_factor_;
|
||||||
|
}
|
||||||
|
if (limit_pacingfactor_by_upper_link_capacity_estimate_ && estimate_ &&
|
||||||
|
estimate_->link_capacity_upper.IsFinite() &&
|
||||||
|
pacing_rate > estimate_->link_capacity_upper) {
|
||||||
|
pacing_rate =
|
||||||
|
std::max({estimate_->link_capacity_upper, min_total_allocated_bitrate_,
|
||||||
|
last_loss_based_target_rate_});
|
||||||
|
}
|
||||||
|
|
||||||
|
DataRate padding_rate =
|
||||||
|
(last_loss_base_state_ == LossBasedState::kIncreaseUsingPadding)
|
||||||
|
? std::max(max_padding_rate_, last_loss_based_target_rate_)
|
||||||
|
: max_padding_rate_;
|
||||||
|
padding_rate = std::min(padding_rate, last_pushback_target_rate_);
|
||||||
|
PacerConfig msg;
|
||||||
|
msg.at_time = at_time;
|
||||||
|
msg.time_window = TimeDelta::Seconds(1);
|
||||||
|
msg.data_window = pacing_rate * msg.time_window;
|
||||||
|
msg.pad_window = padding_rate * msg.time_window;
|
||||||
|
return msg;
|
||||||
}
|
}
|
||||||
@@ -28,6 +28,9 @@ class CongestionControl {
|
|||||||
void MaybeTriggerOnNetworkChanged(NetworkControlUpdate* update,
|
void MaybeTriggerOnNetworkChanged(NetworkControlUpdate* update,
|
||||||
Timestamp at_time);
|
Timestamp at_time);
|
||||||
|
|
||||||
|
private:
|
||||||
|
PacerConfig GetPacingRates(Timestamp at_time) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const bool packet_feedback_only_;
|
const bool packet_feedback_only_;
|
||||||
const bool use_min_allocatable_as_lower_bound_;
|
const bool use_min_allocatable_as_lower_bound_;
|
||||||
@@ -54,12 +57,19 @@ class CongestionControl {
|
|||||||
|
|
||||||
bool first_packet_sent_ = false;
|
bool first_packet_sent_ = false;
|
||||||
|
|
||||||
|
std::optional<NetworkStateEstimate> estimate_;
|
||||||
|
|
||||||
Timestamp next_loss_update_ = Timestamp::MinusInfinity();
|
Timestamp next_loss_update_ = Timestamp::MinusInfinity();
|
||||||
int lost_packets_since_last_loss_update_ = 0;
|
int lost_packets_since_last_loss_update_ = 0;
|
||||||
int expected_packets_since_last_loss_update_ = 0;
|
int expected_packets_since_last_loss_update_ = 0;
|
||||||
|
|
||||||
std::deque<int64_t> feedback_max_rtts_;
|
std::deque<int64_t> feedback_max_rtts_;
|
||||||
|
|
||||||
|
DataRate last_loss_based_target_rate_;
|
||||||
|
DataRate last_pushback_target_rate_;
|
||||||
|
DataRate last_stable_target_rate_;
|
||||||
|
LossBasedState last_loss_base_state_;
|
||||||
|
|
||||||
std::optional<uint8_t> last_estimated_fraction_loss_ = 0;
|
std::optional<uint8_t> last_estimated_fraction_loss_ = 0;
|
||||||
TimeDelta last_estimated_round_trip_time_ = TimeDelta::PlusInfinity();
|
TimeDelta last_estimated_round_trip_time_ = TimeDelta::PlusInfinity();
|
||||||
|
|
||||||
|
|||||||
@@ -206,6 +206,7 @@ DelayBasedBwe::Result DelayBasedBwe::MaybeUpdateEstimate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.delay_detector_state = detector_state;
|
result.delay_detector_state = detector_state;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -234,6 +234,10 @@ DataRate SendSideBandwidthEstimation::target_rate() const {
|
|||||||
return std::max(min_bitrate_configured_, target);
|
return std::max(min_bitrate_configured_, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LossBasedState SendSideBandwidthEstimation::loss_based_state() const {
|
||||||
|
return loss_based_state_;
|
||||||
|
}
|
||||||
|
|
||||||
bool SendSideBandwidthEstimation::IsRttAboveLimit() const {
|
bool SendSideBandwidthEstimation::IsRttAboveLimit() const {
|
||||||
return rtt_backoff_.IsRttAboveLimit();
|
return rtt_backoff_.IsRttAboveLimit();
|
||||||
}
|
}
|
||||||
@@ -511,4 +515,10 @@ void SendSideBandwidthEstimation::ApplyTargetLimits(Timestamp at_time) {
|
|||||||
UpdateTargetBitrate(current_target_, at_time);
|
UpdateTargetBitrate(current_target_, at_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SendSideBandwidthEstimation::PaceAtLossBasedEstimate() const {
|
||||||
|
// return LossBasedBandwidthEstimatorV2ReadyForUse() &&
|
||||||
|
// loss_based_bandwidth_estimator_v2_->PaceAtLossBasedEstimate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
|||||||
@@ -29,6 +29,16 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
enum class LossBasedState {
|
||||||
|
kIncreasing = 0,
|
||||||
|
// TODO(bugs.webrtc.org/12707): Remove one of the increasing states once we
|
||||||
|
// have decided if padding is usefull for ramping up when BWE is loss
|
||||||
|
// limited.
|
||||||
|
kIncreaseUsingPadding = 1,
|
||||||
|
kDecreasing = 2,
|
||||||
|
kDelayBasedEstimate = 3
|
||||||
|
};
|
||||||
|
|
||||||
class LinkCapacityTracker {
|
class LinkCapacityTracker {
|
||||||
public:
|
public:
|
||||||
LinkCapacityTracker() = default;
|
LinkCapacityTracker() = default;
|
||||||
@@ -79,6 +89,7 @@ class SendSideBandwidthEstimation {
|
|||||||
void OnRouteChange();
|
void OnRouteChange();
|
||||||
|
|
||||||
DataRate target_rate() const;
|
DataRate target_rate() const;
|
||||||
|
LossBasedState loss_based_state() const;
|
||||||
// Return whether the current rtt is higher than the rtt limited configured in
|
// Return whether the current rtt is higher than the rtt limited configured in
|
||||||
// RttBasedBackoff.
|
// RttBasedBackoff.
|
||||||
bool IsRttAboveLimit() const;
|
bool IsRttAboveLimit() const;
|
||||||
@@ -115,6 +126,7 @@ class SendSideBandwidthEstimation {
|
|||||||
BandwidthUsage delay_detector_state,
|
BandwidthUsage delay_detector_state,
|
||||||
std::optional<DataRate> probe_bitrate,
|
std::optional<DataRate> probe_bitrate,
|
||||||
bool in_alr);
|
bool in_alr);
|
||||||
|
bool PaceAtLossBasedEstimate() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class GoogCcStatePrinter;
|
friend class GoogCcStatePrinter;
|
||||||
@@ -184,6 +196,7 @@ class SendSideBandwidthEstimation {
|
|||||||
float high_loss_threshold_;
|
float high_loss_threshold_;
|
||||||
DataRate bitrate_threshold_;
|
DataRate bitrate_threshold_;
|
||||||
bool disable_receiver_limit_caps_only_;
|
bool disable_receiver_limit_caps_only_;
|
||||||
|
LossBasedState loss_based_state_;
|
||||||
};
|
};
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
#endif // MODULES_CONGESTION_CONTROLLER_GOOG_CC_SEND_SIDE_BANDWIDTH_ESTIMATION_H_
|
||||||
|
|||||||
@@ -7,10 +7,6 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#if __APPLE__
|
|
||||||
#else
|
|
||||||
#include "nvcodec_api.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
@@ -25,22 +21,9 @@ IceTransport::IceTransport(
|
|||||||
remote_user_id_(remote_user_id),
|
remote_user_id_(remote_user_id),
|
||||||
ice_ws_transport_(ice_ws_transmission),
|
ice_ws_transport_(ice_ws_transmission),
|
||||||
on_ice_status_change_(on_ice_status_change),
|
on_ice_status_change_(on_ice_status_change),
|
||||||
user_data_(user_data),
|
user_data_(user_data) {}
|
||||||
clock_(webrtc::Clock::GetRealTimeClockShared()) {}
|
|
||||||
|
|
||||||
IceTransport::~IceTransport() {
|
IceTransport::~IceTransport() {}
|
||||||
user_data_ = nullptr;
|
|
||||||
video_codec_inited_ = false;
|
|
||||||
audio_codec_inited_ = false;
|
|
||||||
load_nvcodec_dll_success_ = false;
|
|
||||||
|
|
||||||
#ifdef __APPLE__
|
|
||||||
#else
|
|
||||||
if (hardware_acceleration_ && load_nvcodec_dll_success_) {
|
|
||||||
ReleaseNvCodecDll();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
int IceTransport::SetLocalCapabilities(bool hardware_acceleration,
|
int IceTransport::SetLocalCapabilities(bool hardware_acceleration,
|
||||||
bool use_trickle_ice,
|
bool use_trickle_ice,
|
||||||
@@ -63,12 +46,24 @@ int IceTransport::InitIceTransmission(
|
|||||||
std::string &stun_ip, int stun_port, std::string &turn_ip, int turn_port,
|
std::string &stun_ip, int stun_port, std::string &turn_ip, int turn_port,
|
||||||
std::string &turn_username, std::string &turn_password,
|
std::string &turn_username, std::string &turn_password,
|
||||||
rtp::PAYLOAD_TYPE video_codec_payload_type) {
|
rtp::PAYLOAD_TYPE video_codec_payload_type) {
|
||||||
|
ice_transport_controller_ = std::make_shared<IceTransportController>();
|
||||||
ice_agent_ = std::make_unique<IceAgent>(
|
ice_agent_ = std::make_unique<IceAgent>(
|
||||||
offer_peer_, use_trickle_ice_, use_reliable_ice_, enable_turn_,
|
offer_peer_, use_trickle_ice_, use_reliable_ice_, enable_turn_,
|
||||||
force_turn_, stun_ip, stun_port, turn_ip, turn_port, turn_username,
|
force_turn_, stun_ip, stun_port, turn_ip, turn_port, turn_username,
|
||||||
turn_password);
|
turn_password);
|
||||||
|
|
||||||
InitializeIOStatistics();
|
ice_io_statistics_ = std::make_unique<IOStatistics>(
|
||||||
|
[this](const IOStatistics::NetTrafficStats &net_traffic_stats) {
|
||||||
|
if (on_receive_net_status_report_) {
|
||||||
|
XNetTrafficStats xnet_traffic_stats;
|
||||||
|
memcpy(&xnet_traffic_stats, &net_traffic_stats,
|
||||||
|
sizeof(XNetTrafficStats));
|
||||||
|
on_receive_net_status_report_(
|
||||||
|
user_id_.data(), user_id_.size(), TraversalMode(traversal_type_),
|
||||||
|
&xnet_traffic_stats, remote_user_id_.data(),
|
||||||
|
remote_user_id_.size(), user_data_);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ice_agent_->CreateIceAgent(
|
ice_agent_->CreateIceAgent(
|
||||||
[](NiceAgent *agent, guint stream_id, guint component_id,
|
[](NiceAgent *agent, guint stream_id, guint component_id,
|
||||||
@@ -100,66 +95,6 @@ int IceTransport::InitIceTransmission(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IceTransport::InitializeIOStatistics() {
|
|
||||||
ice_io_statistics_ = std::make_unique<IOStatistics>(
|
|
||||||
[this](const IOStatistics::NetTrafficStats &net_traffic_stats) {
|
|
||||||
if (on_receive_net_status_report_) {
|
|
||||||
XNetTrafficStats xnet_traffic_stats;
|
|
||||||
memcpy(&xnet_traffic_stats, &net_traffic_stats,
|
|
||||||
sizeof(XNetTrafficStats));
|
|
||||||
on_receive_net_status_report_(
|
|
||||||
user_id_.data(), user_id_.size(), TraversalMode(traversal_type_),
|
|
||||||
&xnet_traffic_stats, remote_user_id_.data(),
|
|
||||||
remote_user_id_.size(), user_data_);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IceTransport::InitializeChannels(
|
|
||||||
rtp::PAYLOAD_TYPE video_codec_payload_type) {
|
|
||||||
video_codec_payload_type_ = video_codec_payload_type;
|
|
||||||
|
|
||||||
video_channel_send_ = std::make_unique<VideoChannelSend>(clock_, ice_agent_,
|
|
||||||
ice_io_statistics_);
|
|
||||||
audio_channel_send_ =
|
|
||||||
std::make_unique<AudioChannelSend>(ice_agent_, ice_io_statistics_);
|
|
||||||
data_channel_send_ =
|
|
||||||
std::make_unique<DataChannelSend>(ice_agent_, ice_io_statistics_);
|
|
||||||
|
|
||||||
video_channel_send_->Initialize(video_codec_payload_type_);
|
|
||||||
audio_channel_send_->Initialize(rtp::PAYLOAD_TYPE::OPUS);
|
|
||||||
data_channel_send_->Initialize(rtp::PAYLOAD_TYPE::DATA);
|
|
||||||
|
|
||||||
std::weak_ptr<IceTransport> weak_self = shared_from_this();
|
|
||||||
video_channel_receive_ = std::make_unique<VideoChannelReceive>(
|
|
||||||
clock_, ice_agent_, ice_io_statistics_,
|
|
||||||
[this, weak_self](VideoFrame &video_frame) {
|
|
||||||
if (auto self = weak_self.lock()) {
|
|
||||||
OnReceiveCompleteFrame(video_frame);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
audio_channel_receive_ = std::make_unique<AudioChannelReceive>(
|
|
||||||
ice_agent_, ice_io_statistics_,
|
|
||||||
[this, weak_self](const char *data, size_t size) {
|
|
||||||
if (auto self = weak_self.lock()) {
|
|
||||||
OnReceiveCompleteAudio(data, size);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
data_channel_receive_ = std::make_unique<DataChannelReceive>(
|
|
||||||
ice_agent_, ice_io_statistics_,
|
|
||||||
[this, weak_self](const char *data, size_t size) {
|
|
||||||
if (auto self = weak_self.lock()) {
|
|
||||||
OnReceiveCompleteData(data, size);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
video_channel_receive_->Initialize(video_codec_payload_type_);
|
|
||||||
audio_channel_receive_->Initialize(rtp::PAYLOAD_TYPE::OPUS);
|
|
||||||
data_channel_receive_->Initialize(rtp::PAYLOAD_TYPE::DATA);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IceTransport::OnIceStateChange(NiceAgent *agent, guint stream_id,
|
void IceTransport::OnIceStateChange(NiceAgent *agent, guint stream_id,
|
||||||
guint component_id,
|
guint component_id,
|
||||||
NiceComponentState state,
|
NiceComponentState state,
|
||||||
@@ -252,12 +187,13 @@ void IceTransport::OnReceiveBuffer(NiceAgent *agent, guint stream_id,
|
|||||||
gchar *buffer, gpointer user_ptr) {
|
gchar *buffer, gpointer user_ptr) {
|
||||||
if (!is_closed_) {
|
if (!is_closed_) {
|
||||||
if (CheckIsRtpPacket(buffer, size)) {
|
if (CheckIsRtpPacket(buffer, size)) {
|
||||||
if (CheckIsVideoPacket(buffer, size)) {
|
if (CheckIsVideoPacket(buffer, size) && ice_transport_controller_) {
|
||||||
video_channel_receive_->OnReceiveRtpPacket(buffer, size);
|
ice_transport_controller_->OnReceiveVideoRtpPacket(buffer, size);
|
||||||
} else if (CheckIsAudioPacket(buffer, size)) {
|
} else if (CheckIsAudioPacket(buffer, size) &&
|
||||||
audio_channel_receive_->OnReceiveRtpPacket(buffer, size);
|
ice_transport_controller_) {
|
||||||
} else if (CheckIsDataPacket(buffer, size)) {
|
ice_transport_controller_->OnReceiveAudioRtpPacket(buffer, size);
|
||||||
data_channel_receive_->OnReceiveRtpPacket(buffer, size);
|
} else if (CheckIsDataPacket(buffer, size) && ice_transport_controller_) {
|
||||||
|
ice_transport_controller_->OnReceiveDataRtpPacket(buffer, size);
|
||||||
}
|
}
|
||||||
} else if (CheckIsRtcpPacket(buffer, size)) {
|
} else if (CheckIsRtcpPacket(buffer, size)) {
|
||||||
// LOG_ERROR("Rtcp packet [{}]", (uint8_t)(buffer[1]));
|
// LOG_ERROR("Rtcp packet [{}]", (uint8_t)(buffer[1]));
|
||||||
@@ -372,44 +308,12 @@ bool IceTransport::HandleCongestionControlFeedback(
|
|||||||
// rtcp_packet_info->congestion_control_feedback.emplace(std::move(feedback));
|
// rtcp_packet_info->congestion_control_feedback.emplace(std::move(feedback));
|
||||||
// }
|
// }
|
||||||
|
|
||||||
video_channel_send_->OnCongestionControlFeedback(clock_->CurrentTime(),
|
if (ice_transport_controller_) {
|
||||||
feedback);
|
ice_transport_controller_->OnCongestionControlFeedback(feedback);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IceTransport::OnReceiveCompleteFrame(VideoFrame &video_frame) {
|
|
||||||
int num_frame_returned = video_decoder_->Decode(
|
|
||||||
(uint8_t *)video_frame.Buffer(), video_frame.Size(),
|
|
||||||
[this](VideoFrame video_frame) {
|
|
||||||
if (on_receive_video_) {
|
|
||||||
XVideoFrame x_video_frame;
|
|
||||||
x_video_frame.data = (const char *)video_frame.Buffer();
|
|
||||||
x_video_frame.width = video_frame.Width();
|
|
||||||
x_video_frame.height = video_frame.Height();
|
|
||||||
x_video_frame.size = video_frame.Size();
|
|
||||||
on_receive_video_(&x_video_frame, remote_user_id_.data(),
|
|
||||||
remote_user_id_.size(), user_data_);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IceTransport::OnReceiveCompleteAudio(const char *data, size_t size) {
|
|
||||||
int num_frame_returned = audio_decoder_->Decode(
|
|
||||||
(uint8_t *)data, size, [this](uint8_t *data, int size) {
|
|
||||||
if (on_receive_audio_) {
|
|
||||||
on_receive_audio_((const char *)data, size, remote_user_id_.data(),
|
|
||||||
remote_user_id_.size(), user_data_);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void IceTransport::OnReceiveCompleteData(const char *data, size_t size) {
|
|
||||||
if (on_receive_data_) {
|
|
||||||
on_receive_data_(data, size, remote_user_id_.data(), remote_user_id_.size(),
|
|
||||||
user_data_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int IceTransport::DestroyIceTransmission() {
|
int IceTransport::DestroyIceTransmission() {
|
||||||
LOG_INFO("[{}->{}] Destroy ice transmission", user_id_, remote_user_id_);
|
LOG_INFO("[{}->{}] Destroy ice transmission", user_id_, remote_user_id_);
|
||||||
is_closed_ = true;
|
is_closed_ = true;
|
||||||
@@ -422,130 +326,9 @@ int IceTransport::DestroyIceTransmission() {
|
|||||||
ice_io_statistics_->Stop();
|
ice_io_statistics_->Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video_channel_send_) {
|
|
||||||
video_channel_send_->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio_channel_send_) {
|
|
||||||
audio_channel_send_->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_channel_send_) {
|
|
||||||
data_channel_send_->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (video_channel_receive_) {
|
|
||||||
video_channel_receive_->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (audio_channel_receive_) {
|
|
||||||
audio_channel_receive_->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data_channel_receive_) {
|
|
||||||
data_channel_receive_->Destroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ice_agent_->DestroyIceAgent();
|
return ice_agent_->DestroyIceAgent();
|
||||||
}
|
}
|
||||||
|
|
||||||
int IceTransport::CreateVideoCodec(rtp::PAYLOAD_TYPE video_pt,
|
|
||||||
bool hardware_acceleration) {
|
|
||||||
if (video_codec_inited_) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
hardware_acceleration_ = hardware_acceleration;
|
|
||||||
|
|
||||||
if (rtp::PAYLOAD_TYPE::AV1 == video_pt) {
|
|
||||||
if (hardware_acceleration_) {
|
|
||||||
hardware_acceleration_ = false;
|
|
||||||
LOG_WARN("Only support software codec for AV1");
|
|
||||||
}
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, true);
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, true);
|
|
||||||
} else if (rtp::PAYLOAD_TYPE::H264 == video_pt) {
|
|
||||||
#ifdef __APPLE__
|
|
||||||
if (hardware_acceleration_) {
|
|
||||||
hardware_acceleration_ = false;
|
|
||||||
LOG_WARN(
|
|
||||||
"MacOS not support hardware acceleration, use default software "
|
|
||||||
"codec");
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
|
||||||
} else {
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (hardware_acceleration_) {
|
|
||||||
if (0 == LoadNvCodecDll()) {
|
|
||||||
load_nvcodec_dll_success_ = true;
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(true, false);
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(true, false);
|
|
||||||
} else {
|
|
||||||
LOG_WARN(
|
|
||||||
"Hardware accelerated codec not available, use default software "
|
|
||||||
"codec");
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!video_encoder_) {
|
|
||||||
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
|
||||||
LOG_ERROR("Create encoder failed, try to use software H.264 encoder");
|
|
||||||
}
|
|
||||||
if (!video_encoder_ || 0 != video_encoder_->Init()) {
|
|
||||||
LOG_ERROR("Encoder init failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!video_decoder_) {
|
|
||||||
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
|
||||||
LOG_ERROR("Create decoder failed, try to use software H.264 decoder");
|
|
||||||
}
|
|
||||||
if (!video_decoder_ || video_decoder_->Init()) {
|
|
||||||
LOG_ERROR("Decoder init failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
video_codec_inited_ = true;
|
|
||||||
LOG_INFO("Create video codec [{}|{}] finish",
|
|
||||||
video_encoder_->GetEncoderName(), video_decoder_->GetDecoderName());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IceTransport::CreateAudioCodec() {
|
|
||||||
if (audio_codec_inited_) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_encoder_ = std::make_unique<AudioEncoder>(AudioEncoder(48000, 1, 480));
|
|
||||||
if (!audio_encoder_ || 0 != audio_encoder_->Init()) {
|
|
||||||
LOG_ERROR("Audio encoder init failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_decoder_ = std::make_unique<AudioDecoder>(AudioDecoder(48000, 1, 480));
|
|
||||||
if (!audio_decoder_ || 0 != audio_decoder_->Init()) {
|
|
||||||
LOG_ERROR("Audio decoder init failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
audio_codec_inited_ = true;
|
|
||||||
LOG_INFO("Create audio codec [{}|{}] finish",
|
|
||||||
audio_encoder_->GetEncoderName(), audio_decoder_->GetDecoderName());
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IceTransport::SetTransmissionId(const std::string &transmission_id) {
|
int IceTransport::SetTransmissionId(const std::string &transmission_id) {
|
||||||
transmission_id_ = transmission_id;
|
transmission_id_ = transmission_id;
|
||||||
|
|
||||||
@@ -742,10 +525,12 @@ std::string IceTransport::GetRemoteCapabilities(const std::string &remote_sdp) {
|
|||||||
return std::string();
|
return std::string();
|
||||||
}
|
}
|
||||||
|
|
||||||
InitializeChannels(negotiated_video_pt_);
|
if (ice_transport_controller_) {
|
||||||
|
ice_transport_controller_->Create(
|
||||||
CreateVideoCodec(negotiated_video_pt_, hardware_acceleration_);
|
remote_user_id_, negotiated_video_pt_, hardware_acceleration_,
|
||||||
CreateAudioCodec();
|
ice_agent_, ice_io_statistics_, on_receive_video_, on_receive_audio_,
|
||||||
|
on_receive_data_, user_data_);
|
||||||
|
}
|
||||||
|
|
||||||
remote_capabilities_got_ = true;
|
remote_capabilities_got_ = true;
|
||||||
}
|
}
|
||||||
@@ -978,31 +763,13 @@ int IceTransport::SendVideoFrame(const XVideoFrame *video_frame) {
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (b_force_i_frame_) {
|
if (ice_transport_controller_) {
|
||||||
video_encoder_->ForceIdr();
|
return ice_transport_controller_->SendVideo(video_frame);
|
||||||
LOG_INFO("Force I frame");
|
|
||||||
b_force_i_frame_ = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = video_encoder_->Encode(
|
|
||||||
video_frame,
|
|
||||||
[this](char *encoded_frame, size_t size,
|
|
||||||
VideoEncoder::VideoFrameType frame_type) -> int {
|
|
||||||
if (video_channel_send_) {
|
|
||||||
video_channel_send_->SendVideo(encoded_frame, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (0 != ret) {
|
|
||||||
LOG_ERROR("Encode failed");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int IceTransport::SendAudioFrame(const char *data, size_t size) {
|
int IceTransport::SendAudioFrame(const char *data, size_t size) {
|
||||||
if (state_ != NICE_COMPONENT_STATE_CONNECTED &&
|
if (state_ != NICE_COMPONENT_STATE_CONNECTED &&
|
||||||
state_ != NICE_COMPONENT_STATE_READY) {
|
state_ != NICE_COMPONENT_STATE_READY) {
|
||||||
@@ -1011,17 +778,11 @@ int IceTransport::SendAudioFrame(const char *data, size_t size) {
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ret = audio_encoder_->Encode(
|
if (ice_transport_controller_) {
|
||||||
(uint8_t *)data, size,
|
return ice_transport_controller_->SendAudio(data, size);
|
||||||
[this](char *encoded_audio_buffer, size_t size) -> int {
|
|
||||||
if (audio_channel_send_) {
|
|
||||||
audio_channel_send_->SendAudio(encoded_audio_buffer, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -1;
|
||||||
});
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int IceTransport::SendDataFrame(const char *data, size_t size) {
|
int IceTransport::SendDataFrame(const char *data, size_t size) {
|
||||||
@@ -1032,11 +793,11 @@ int IceTransport::SendDataFrame(const char *data, size_t size) {
|
|||||||
return -2;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data_channel_send_) {
|
if (ice_transport_controller_) {
|
||||||
data_channel_send_->SendData(data, size);
|
return ice_transport_controller_->SendData(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t IceTransport::CheckIsRtpPacket(const char *buffer, size_t size) {
|
uint8_t IceTransport::CheckIsRtpPacket(const char *buffer, size_t size) {
|
||||||
|
|||||||
@@ -9,32 +9,15 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "audio_decoder.h"
|
|
||||||
#include "audio_encoder.h"
|
|
||||||
// #include "congestion_control.h"
|
|
||||||
#include "audio_channel_receive.h"
|
|
||||||
#include "audio_channel_send.h"
|
|
||||||
#include "clock.h"
|
|
||||||
#include "data_channel_receive.h"
|
|
||||||
#include "data_channel_send.h"
|
|
||||||
#include "ice_agent.h"
|
#include "ice_agent.h"
|
||||||
|
#include "ice_transport_controller.h"
|
||||||
#include "io_statistics.h"
|
#include "io_statistics.h"
|
||||||
#include "ringbuffer.h"
|
#include "ringbuffer.h"
|
||||||
#include "rtcp_packet_info.h"
|
#include "rtcp_packet_info.h"
|
||||||
#include "rtp_audio_receiver.h"
|
|
||||||
#include "rtp_audio_sender.h"
|
|
||||||
#include "rtp_data_receiver.h"
|
|
||||||
#include "rtp_data_sender.h"
|
|
||||||
#include "rtp_packet.h"
|
#include "rtp_packet.h"
|
||||||
#include "rtp_video_receiver.h"
|
|
||||||
#include "rtp_video_sender.h"
|
|
||||||
#include "video_channel_receive.h"
|
|
||||||
#include "video_channel_send.h"
|
|
||||||
#include "video_decoder_factory.h"
|
|
||||||
#include "video_encoder_factory.h"
|
|
||||||
#include "ws_client.h"
|
#include "ws_client.h"
|
||||||
|
|
||||||
class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
class IceTransport {
|
||||||
public:
|
public:
|
||||||
typedef enum { VIDEO = 96, AUDIO = 97, DATA = 127 } DATA_TYPE;
|
typedef enum { VIDEO = 96, AUDIO = 97, DATA = 127 } DATA_TYPE;
|
||||||
typedef enum { H264 = 96, AV1 = 99 } VIDEO_TYPE;
|
typedef enum { H264 = 96, AV1 = 99 } VIDEO_TYPE;
|
||||||
@@ -70,24 +53,11 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
|
|
||||||
int DestroyIceTransmission();
|
int DestroyIceTransmission();
|
||||||
|
|
||||||
void SetOnReceiveVideoFunc(
|
void SetOnReceiveFunc(OnReceiveVideo on_receive_video,
|
||||||
std::function<void(const XVideoFrame *, const char *, const size_t,
|
OnReceiveAudio on_receive_audio,
|
||||||
void *)>
|
OnReceiveData on_receive_data) {
|
||||||
on_receive_video) {
|
|
||||||
on_receive_video_ = on_receive_video;
|
on_receive_video_ = on_receive_video;
|
||||||
}
|
|
||||||
|
|
||||||
void SetOnReceiveAudioFunc(
|
|
||||||
std::function<void(const char *, size_t, const char *, const size_t,
|
|
||||||
void *)>
|
|
||||||
on_receive_audio) {
|
|
||||||
on_receive_audio_ = on_receive_audio;
|
on_receive_audio_ = on_receive_audio;
|
||||||
}
|
|
||||||
|
|
||||||
void SetOnReceiveDataFunc(
|
|
||||||
std::function<void(const char *, size_t, const char *, const size_t,
|
|
||||||
void *)>
|
|
||||||
on_receive_data) {
|
|
||||||
on_receive_data_ = on_receive_data;
|
on_receive_data_ = on_receive_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,9 +101,6 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
bool NegotiateAudioPayloadType(const std::string &remote_sdp);
|
bool NegotiateAudioPayloadType(const std::string &remote_sdp);
|
||||||
bool NegotiateDataPayloadType(const std::string &remote_sdp);
|
bool NegotiateDataPayloadType(const std::string &remote_sdp);
|
||||||
|
|
||||||
int CreateVideoCodec(rtp::PAYLOAD_TYPE video_pt, bool hardware_acceleration);
|
|
||||||
int CreateAudioCodec();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint8_t CheckIsRtpPacket(const char *buffer, size_t size);
|
uint8_t CheckIsRtpPacket(const char *buffer, size_t size);
|
||||||
uint8_t CheckIsRtcpPacket(const char *buffer, size_t size);
|
uint8_t CheckIsRtcpPacket(const char *buffer, size_t size);
|
||||||
@@ -142,10 +109,6 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
uint8_t CheckIsDataPacket(const char *buffer, size_t size);
|
uint8_t CheckIsDataPacket(const char *buffer, size_t size);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitializeIOStatistics();
|
|
||||||
|
|
||||||
void InitializeChannels(rtp::PAYLOAD_TYPE video_codec_payload_type);
|
|
||||||
|
|
||||||
void OnIceStateChange(NiceAgent *agent, guint stream_id, guint component_id,
|
void OnIceStateChange(NiceAgent *agent, guint stream_id, guint component_id,
|
||||||
NiceComponentState state, gpointer user_ptr);
|
NiceComponentState state, gpointer user_ptr);
|
||||||
|
|
||||||
@@ -162,12 +125,6 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
void OnReceiveBuffer(NiceAgent *agent, guint stream_id, guint component_id,
|
void OnReceiveBuffer(NiceAgent *agent, guint stream_id, guint component_id,
|
||||||
guint size, gchar *buffer, gpointer user_ptr);
|
guint size, gchar *buffer, gpointer user_ptr);
|
||||||
|
|
||||||
void OnReceiveCompleteFrame(VideoFrame &video_frame);
|
|
||||||
|
|
||||||
void OnReceiveCompleteAudio(const char *data, size_t size);
|
|
||||||
|
|
||||||
void OnReceiveCompleteData(const char *data, size_t size);
|
|
||||||
|
|
||||||
bool ParseRtcpPacket(const uint8_t *buffer, size_t size,
|
bool ParseRtcpPacket(const uint8_t *buffer, size_t size,
|
||||||
RtcpPacketInfo *rtcp_packet_info);
|
RtcpPacketInfo *rtcp_packet_info);
|
||||||
|
|
||||||
@@ -176,6 +133,7 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
RtcpPacketInfo *rtcp_packet_info);
|
RtcpPacketInfo *rtcp_packet_info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool hardware_acceleration_ = false;
|
||||||
bool use_trickle_ice_ = true;
|
bool use_trickle_ice_ = true;
|
||||||
bool enable_turn_ = false;
|
bool enable_turn_ = false;
|
||||||
bool use_reliable_ice_ = false;
|
bool use_reliable_ice_ = false;
|
||||||
@@ -203,13 +161,10 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
|
std::shared_ptr<IceAgent> ice_agent_ = nullptr;
|
||||||
bool is_closed_ = false;
|
bool is_closed_ = false;
|
||||||
std::shared_ptr<WsClient> ice_ws_transport_ = nullptr;
|
std::shared_ptr<WsClient> ice_ws_transport_ = nullptr;
|
||||||
// CongestionControl *congestion_control_ = nullptr;
|
|
||||||
std::function<void(const XVideoFrame *, const char *, const size_t, void *)>
|
OnReceiveVideo on_receive_video_ = nullptr;
|
||||||
on_receive_video_ = nullptr;
|
OnReceiveAudio on_receive_audio_ = nullptr;
|
||||||
std::function<void(const char *, size_t, const char *, const size_t, void *)>
|
OnReceiveData on_receive_data_ = nullptr;
|
||||||
on_receive_audio_ = nullptr;
|
|
||||||
std::function<void(const char *, size_t, const char *, const size_t, void *)>
|
|
||||||
on_receive_data_ = nullptr;
|
|
||||||
|
|
||||||
std::function<void(std::string, const std::string &)> on_ice_status_change_ =
|
std::function<void(std::string, const std::string &)> on_ice_status_change_ =
|
||||||
nullptr;
|
nullptr;
|
||||||
@@ -220,23 +175,7 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
on_receive_net_status_report_ = nullptr;
|
on_receive_net_status_report_ = nullptr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<webrtc::Clock> clock_;
|
std::shared_ptr<IceTransportController> ice_transport_controller_ = nullptr;
|
||||||
std::unique_ptr<VideoChannelSend> video_channel_send_ = nullptr;
|
|
||||||
std::unique_ptr<VideoChannelReceive> video_channel_receive_ = nullptr;
|
|
||||||
std::unique_ptr<AudioChannelSend> audio_channel_send_ = nullptr;
|
|
||||||
std::unique_ptr<AudioChannelReceive> audio_channel_receive_ = nullptr;
|
|
||||||
std::unique_ptr<DataChannelSend> data_channel_send_ = nullptr;
|
|
||||||
std::unique_ptr<DataChannelReceive> data_channel_receive_ = nullptr;
|
|
||||||
|
|
||||||
std::unique_ptr<RtpVideoReceiver> rtp_video_receiver_ = nullptr;
|
|
||||||
std::unique_ptr<RtpVideoSender> rtp_video_sender_ = nullptr;
|
|
||||||
std::unique_ptr<RtpAudioReceiver> rtp_audio_receiver_ = nullptr;
|
|
||||||
std::unique_ptr<RtpAudioSender> rtp_audio_sender_ = nullptr;
|
|
||||||
std::unique_ptr<RtpDataReceiver> rtp_data_receiver_ = nullptr;
|
|
||||||
std::unique_ptr<RtpDataSender> rtp_data_sender_ = nullptr;
|
|
||||||
bool start_send_packet_ = false;
|
|
||||||
|
|
||||||
uint32_t last_complete_frame_ts_ = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<IOStatistics> ice_io_statistics_ = nullptr;
|
std::shared_ptr<IOStatistics> ice_io_statistics_ = nullptr;
|
||||||
@@ -250,19 +189,6 @@ class IceTransport : public std::enable_shared_from_this<IceTransport> {
|
|||||||
rtp::PAYLOAD_TYPE negotiated_video_pt_ = rtp::PAYLOAD_TYPE::UNDEFINED;
|
rtp::PAYLOAD_TYPE negotiated_video_pt_ = rtp::PAYLOAD_TYPE::UNDEFINED;
|
||||||
rtp::PAYLOAD_TYPE negotiated_audio_pt_ = rtp::PAYLOAD_TYPE::UNDEFINED;
|
rtp::PAYLOAD_TYPE negotiated_audio_pt_ = rtp::PAYLOAD_TYPE::UNDEFINED;
|
||||||
rtp::PAYLOAD_TYPE negotiated_data_pt_ = rtp::PAYLOAD_TYPE::UNDEFINED;
|
rtp::PAYLOAD_TYPE negotiated_data_pt_ = rtp::PAYLOAD_TYPE::UNDEFINED;
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<VideoEncoder> video_encoder_ = nullptr;
|
|
||||||
std::unique_ptr<VideoDecoder> video_decoder_ = nullptr;
|
|
||||||
bool b_force_i_frame_ = false;
|
|
||||||
bool video_codec_inited_ = false;
|
|
||||||
bool load_nvcodec_dll_success_ = false;
|
|
||||||
bool hardware_acceleration_ = false;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::unique_ptr<AudioEncoder> audio_encoder_ = nullptr;
|
|
||||||
std::unique_ptr<AudioDecoder> audio_decoder_ = nullptr;
|
|
||||||
bool audio_codec_inited_ = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
389
src/transport/ice_transport_controller.cpp
Normal file
389
src/transport/ice_transport_controller.cpp
Normal file
@@ -0,0 +1,389 @@
|
|||||||
|
#include "ice_transport_controller.h"
|
||||||
|
#if __APPLE__
|
||||||
|
#else
|
||||||
|
#include "nvcodec_api.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
IceTransportController::IceTransportController()
|
||||||
|
: b_force_i_frame_(true),
|
||||||
|
video_codec_inited_(false),
|
||||||
|
audio_codec_inited_(false),
|
||||||
|
load_nvcodec_dll_success_(false),
|
||||||
|
hardware_acceleration_(false),
|
||||||
|
clock_(webrtc::Clock::GetRealTimeClockShared()) {}
|
||||||
|
|
||||||
|
IceTransportController::~IceTransportController() {
|
||||||
|
user_data_ = nullptr;
|
||||||
|
video_codec_inited_ = false;
|
||||||
|
audio_codec_inited_ = false;
|
||||||
|
load_nvcodec_dll_success_ = false;
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#else
|
||||||
|
if (hardware_acceleration_ && load_nvcodec_dll_success_) {
|
||||||
|
ReleaseNvCodecDll();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::Create(
|
||||||
|
std::string remote_user_id, rtp::PAYLOAD_TYPE video_codec_payload_type,
|
||||||
|
bool hardware_acceleration, std::shared_ptr<IceAgent> ice_agent,
|
||||||
|
std::shared_ptr<IOStatistics> ice_io_statistics,
|
||||||
|
OnReceiveVideo on_receive_video, OnReceiveAudio on_receive_audio,
|
||||||
|
OnReceiveData on_receive_data, void* user_data) {
|
||||||
|
remote_user_id_ = remote_user_id;
|
||||||
|
on_receive_video_ = on_receive_video;
|
||||||
|
on_receive_audio_ = on_receive_audio;
|
||||||
|
on_receive_data_ = on_receive_data;
|
||||||
|
user_data_ = user_data;
|
||||||
|
|
||||||
|
CreateVideoCodec(video_codec_payload_type, hardware_acceleration);
|
||||||
|
CreateAudioCodec();
|
||||||
|
|
||||||
|
controller_ = std::make_unique<CongestionControl>();
|
||||||
|
|
||||||
|
video_channel_send_ = std::make_unique<VideoChannelSend>(
|
||||||
|
clock_, ice_agent, ice_io_statistics,
|
||||||
|
[this](const webrtc::RtpPacketToSend& packet) {
|
||||||
|
OnSentRtpPacket(packet);
|
||||||
|
});
|
||||||
|
audio_channel_send_ =
|
||||||
|
std::make_unique<AudioChannelSend>(ice_agent, ice_io_statistics);
|
||||||
|
data_channel_send_ =
|
||||||
|
std::make_unique<DataChannelSend>(ice_agent, ice_io_statistics);
|
||||||
|
|
||||||
|
video_channel_send_->Initialize(video_codec_payload_type);
|
||||||
|
audio_channel_send_->Initialize(rtp::PAYLOAD_TYPE::OPUS);
|
||||||
|
data_channel_send_->Initialize(rtp::PAYLOAD_TYPE::DATA);
|
||||||
|
|
||||||
|
std::weak_ptr<IceTransportController> weak_self = shared_from_this();
|
||||||
|
video_channel_receive_ = std::make_unique<VideoChannelReceive>(
|
||||||
|
clock_, ice_agent, ice_io_statistics,
|
||||||
|
[this, weak_self](VideoFrame& video_frame) {
|
||||||
|
if (auto self = weak_self.lock()) {
|
||||||
|
OnReceiveCompleteFrame(video_frame);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
audio_channel_receive_ = std::make_unique<AudioChannelReceive>(
|
||||||
|
ice_agent, ice_io_statistics,
|
||||||
|
[this, weak_self](const char* data, size_t size) {
|
||||||
|
if (auto self = weak_self.lock()) {
|
||||||
|
OnReceiveCompleteAudio(data, size);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
data_channel_receive_ = std::make_unique<DataChannelReceive>(
|
||||||
|
ice_agent, ice_io_statistics,
|
||||||
|
[this, weak_self](const char* data, size_t size) {
|
||||||
|
if (auto self = weak_self.lock()) {
|
||||||
|
OnReceiveCompleteData(data, size);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
video_channel_receive_->Initialize(video_codec_payload_type);
|
||||||
|
audio_channel_receive_->Initialize(rtp::PAYLOAD_TYPE::OPUS);
|
||||||
|
data_channel_receive_->Initialize(rtp::PAYLOAD_TYPE::DATA);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::Destroy() {
|
||||||
|
if (video_channel_send_) {
|
||||||
|
video_channel_send_->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audio_channel_send_) {
|
||||||
|
audio_channel_send_->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_channel_send_) {
|
||||||
|
data_channel_send_->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (video_channel_receive_) {
|
||||||
|
video_channel_receive_->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audio_channel_receive_) {
|
||||||
|
audio_channel_receive_->Destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data_channel_receive_) {
|
||||||
|
data_channel_receive_->Destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::SendVideo(const XVideoFrame* video_frame) {
|
||||||
|
if (!video_encoder_) {
|
||||||
|
LOG_ERROR("Video Encoder not created");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (b_force_i_frame_) {
|
||||||
|
video_encoder_->ForceIdr();
|
||||||
|
LOG_INFO("Force I frame");
|
||||||
|
b_force_i_frame_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = video_encoder_->Encode(
|
||||||
|
video_frame,
|
||||||
|
[this](char* encoded_frame, size_t size,
|
||||||
|
VideoEncoder::VideoFrameType frame_type) -> int {
|
||||||
|
if (video_channel_send_) {
|
||||||
|
video_channel_send_->SendVideo(encoded_frame, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (0 != ret) {
|
||||||
|
LOG_ERROR("Encode failed");
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::SendAudio(const char* data, size_t size) {
|
||||||
|
if (!audio_encoder_) {
|
||||||
|
LOG_ERROR("Audio Encoder not created");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = audio_encoder_->Encode(
|
||||||
|
(uint8_t*)data, size,
|
||||||
|
[this](char* encoded_audio_buffer, size_t size) -> int {
|
||||||
|
if (audio_channel_send_) {
|
||||||
|
audio_channel_send_->SendAudio(encoded_audio_buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::SendData(const char* data, size_t size) {
|
||||||
|
if (data_channel_send_) {
|
||||||
|
data_channel_send_->SendData(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::OnReceiveVideoRtpPacket(const char* data,
|
||||||
|
size_t size) {
|
||||||
|
if (video_channel_receive_) {
|
||||||
|
return video_channel_receive_->OnReceiveRtpPacket(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::OnReceiveAudioRtpPacket(const char* data,
|
||||||
|
size_t size) {
|
||||||
|
if (audio_channel_receive_) {
|
||||||
|
return audio_channel_receive_->OnReceiveRtpPacket(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::OnReceiveDataRtpPacket(const char* data,
|
||||||
|
size_t size) {
|
||||||
|
if (data_channel_receive_) {
|
||||||
|
return data_channel_receive_->OnReceiveRtpPacket(data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::OnReceiveCompleteFrame(VideoFrame& video_frame) {
|
||||||
|
int num_frame_returned = video_decoder_->Decode(
|
||||||
|
(uint8_t*)video_frame.Buffer(), video_frame.Size(),
|
||||||
|
[this](VideoFrame video_frame) {
|
||||||
|
if (on_receive_video_) {
|
||||||
|
XVideoFrame x_video_frame;
|
||||||
|
x_video_frame.data = (const char*)video_frame.Buffer();
|
||||||
|
x_video_frame.width = video_frame.Width();
|
||||||
|
x_video_frame.height = video_frame.Height();
|
||||||
|
x_video_frame.size = video_frame.Size();
|
||||||
|
on_receive_video_(&x_video_frame, remote_user_id_.data(),
|
||||||
|
remote_user_id_.size(), user_data_);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::OnReceiveCompleteAudio(const char* data,
|
||||||
|
size_t size) {
|
||||||
|
int num_frame_returned = audio_decoder_->Decode(
|
||||||
|
(uint8_t*)data, size, [this](uint8_t* data, int size) {
|
||||||
|
if (on_receive_audio_) {
|
||||||
|
on_receive_audio_((const char*)data, size, remote_user_id_.data(),
|
||||||
|
remote_user_id_.size(), user_data_);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::OnReceiveCompleteData(const char* data,
|
||||||
|
size_t size) {
|
||||||
|
if (on_receive_data_) {
|
||||||
|
on_receive_data_(data, size, remote_user_id_.data(), remote_user_id_.size(),
|
||||||
|
user_data_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::CreateVideoCodec(rtp::PAYLOAD_TYPE video_pt,
|
||||||
|
bool hardware_acceleration) {
|
||||||
|
if (video_codec_inited_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hardware_acceleration_ = hardware_acceleration;
|
||||||
|
|
||||||
|
if (rtp::PAYLOAD_TYPE::AV1 == video_pt) {
|
||||||
|
if (hardware_acceleration_) {
|
||||||
|
hardware_acceleration_ = false;
|
||||||
|
LOG_WARN("Only support software codec for AV1");
|
||||||
|
}
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, true);
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, true);
|
||||||
|
} else if (rtp::PAYLOAD_TYPE::H264 == video_pt) {
|
||||||
|
#ifdef __APPLE__
|
||||||
|
if (hardware_acceleration_) {
|
||||||
|
hardware_acceleration_ = false;
|
||||||
|
LOG_WARN(
|
||||||
|
"MacOS not support hardware acceleration, use default software "
|
||||||
|
"codec");
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
||||||
|
} else {
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
if (hardware_acceleration_) {
|
||||||
|
if (0 == LoadNvCodecDll()) {
|
||||||
|
load_nvcodec_dll_success_ = true;
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(true, false);
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(true, false);
|
||||||
|
} else {
|
||||||
|
LOG_WARN(
|
||||||
|
"Hardware accelerated codec not available, use default software "
|
||||||
|
"codec");
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!video_encoder_) {
|
||||||
|
video_encoder_ = VideoEncoderFactory::CreateVideoEncoder(false, false);
|
||||||
|
LOG_ERROR("Create encoder failed, try to use software H.264 encoder");
|
||||||
|
}
|
||||||
|
if (!video_encoder_ || 0 != video_encoder_->Init()) {
|
||||||
|
LOG_ERROR("Encoder init failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!video_decoder_) {
|
||||||
|
video_decoder_ = VideoDecoderFactory::CreateVideoDecoder(false, false);
|
||||||
|
LOG_ERROR("Create decoder failed, try to use software H.264 decoder");
|
||||||
|
}
|
||||||
|
if (!video_decoder_ || video_decoder_->Init()) {
|
||||||
|
LOG_ERROR("Decoder init failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
video_codec_inited_ = true;
|
||||||
|
LOG_INFO("Create video codec [{}|{}] finish",
|
||||||
|
video_encoder_->GetEncoderName(), video_decoder_->GetDecoderName());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int IceTransportController::CreateAudioCodec() {
|
||||||
|
if (audio_codec_inited_) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_encoder_ = std::make_unique<AudioEncoder>(AudioEncoder(48000, 1, 480));
|
||||||
|
if (!audio_encoder_ || 0 != audio_encoder_->Init()) {
|
||||||
|
LOG_ERROR("Audio encoder init failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_decoder_ = std::make_unique<AudioDecoder>(AudioDecoder(48000, 1, 480));
|
||||||
|
if (!audio_decoder_ || 0 != audio_decoder_->Init()) {
|
||||||
|
LOG_ERROR("Audio decoder init failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_codec_inited_ = true;
|
||||||
|
LOG_INFO("Create audio codec [{}|{}] finish",
|
||||||
|
audio_encoder_->GetEncoderName(), audio_decoder_->GetDecoderName());
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::OnCongestionControlFeedback(
|
||||||
|
const webrtc::rtcp::CongestionControlFeedback& feedback) {
|
||||||
|
std::optional<webrtc::TransportPacketsFeedback> feedback_msg =
|
||||||
|
transport_feedback_adapter_.ProcessCongestionControlFeedback(
|
||||||
|
feedback, clock_->CurrentTime());
|
||||||
|
if (feedback_msg) {
|
||||||
|
HandleTransportPacketsFeedback(*feedback_msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::HandleTransportPacketsFeedback(
|
||||||
|
const webrtc::TransportPacketsFeedback& feedback) {
|
||||||
|
if (controller_)
|
||||||
|
PostUpdates(controller_->OnTransportPacketsFeedback(feedback));
|
||||||
|
|
||||||
|
UpdateCongestedState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::OnSentRtpPacket(
|
||||||
|
const webrtc::RtpPacketToSend& packet) {
|
||||||
|
webrtc::PacedPacketInfo pacing_info;
|
||||||
|
size_t transport_overhead_bytes_per_packet_ = 0;
|
||||||
|
webrtc::Timestamp creation_time =
|
||||||
|
webrtc::Timestamp::Millis(clock_->TimeInMilliseconds());
|
||||||
|
transport_feedback_adapter_.AddPacket(
|
||||||
|
packet, pacing_info, transport_overhead_bytes_per_packet_, creation_time);
|
||||||
|
|
||||||
|
rtc::SentPacket sent_packet;
|
||||||
|
sent_packet.packet_id = packet.transport_sequence_number().value();
|
||||||
|
sent_packet.send_time_ms = clock_->TimeInMilliseconds();
|
||||||
|
sent_packet.info.included_in_feedback = true;
|
||||||
|
sent_packet.info.included_in_allocation = true;
|
||||||
|
sent_packet.info.packet_size_bytes = packet.size();
|
||||||
|
sent_packet.info.packet_type = rtc::PacketType::kData;
|
||||||
|
|
||||||
|
transport_feedback_adapter_.ProcessSentPacket(sent_packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::PostUpdates(webrtc::NetworkControlUpdate update) {
|
||||||
|
// UpdateControlState();
|
||||||
|
|
||||||
|
target_bitrate_ = update.target_rate.has_value()
|
||||||
|
? update.target_rate->target_rate.bps()
|
||||||
|
: 0;
|
||||||
|
// LOG_WARN("Target bitrate [{}]bps", target_bitrate_);
|
||||||
|
video_encoder_->SetTargetBitrate(target_bitrate_);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::UpdateControlState() {
|
||||||
|
if (controller_) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IceTransportController::UpdateCongestedState() {
|
||||||
|
if (controller_) {
|
||||||
|
}
|
||||||
|
}
|
||||||
121
src/transport/ice_transport_controller.h
Normal file
121
src/transport/ice_transport_controller.h
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
/*
|
||||||
|
* @Author: DI JUNKUN
|
||||||
|
* @Date: 2025-02-11
|
||||||
|
* Copyright (c) 2025 by DI JUNKUN, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ICE_TRANSPORT_CONTROLLER_H_
|
||||||
|
#define _ICE_TRANSPORT_CONTROLLER_H_
|
||||||
|
|
||||||
|
#include "api/transport/network_types.h"
|
||||||
|
#include "api/units/timestamp.h"
|
||||||
|
#include "audio_channel_receive.h"
|
||||||
|
#include "audio_channel_send.h"
|
||||||
|
#include "audio_decoder.h"
|
||||||
|
#include "audio_encoder.h"
|
||||||
|
#include "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 "transport_feedback_adapter.h"
|
||||||
|
#include "video_channel_receive.h"
|
||||||
|
#include "video_channel_send.h"
|
||||||
|
#include "video_decoder_factory.h"
|
||||||
|
#include "video_encoder_factory.h"
|
||||||
|
|
||||||
|
typedef void (*OnReceiveVideo)(const XVideoFrame *, const char *, const size_t,
|
||||||
|
void *);
|
||||||
|
typedef void (*OnReceiveAudio)(const char *, size_t, const char *, const size_t,
|
||||||
|
void *);
|
||||||
|
typedef void (*OnReceiveData)(const char *, size_t, const char *, const size_t,
|
||||||
|
void *);
|
||||||
|
|
||||||
|
class IceTransportController
|
||||||
|
: public std::enable_shared_from_this<IceTransportController> {
|
||||||
|
public:
|
||||||
|
IceTransportController();
|
||||||
|
~IceTransportController();
|
||||||
|
|
||||||
|
public:
|
||||||
|
void Create(std::string remote_user_id,
|
||||||
|
rtp::PAYLOAD_TYPE video_codec_payload_type,
|
||||||
|
bool hardware_acceleration, std::shared_ptr<IceAgent> ice_agent,
|
||||||
|
std::shared_ptr<IOStatistics> ice_io_statistics,
|
||||||
|
OnReceiveVideo on_receive_video, OnReceiveAudio on_receive_audio,
|
||||||
|
OnReceiveData on_receive_data, void *user_data);
|
||||||
|
void Destroy();
|
||||||
|
|
||||||
|
int SendVideo(const XVideoFrame *video_frame);
|
||||||
|
int SendAudio(const char *data, size_t size);
|
||||||
|
int SendData(const char *data, size_t size);
|
||||||
|
|
||||||
|
int OnReceiveVideoRtpPacket(const char *data, size_t size);
|
||||||
|
int OnReceiveAudioRtpPacket(const char *data, size_t size);
|
||||||
|
int OnReceiveDataRtpPacket(const char *data, size_t size);
|
||||||
|
|
||||||
|
void OnReceiveCompleteFrame(VideoFrame &video_frame);
|
||||||
|
void OnReceiveCompleteAudio(const char *data, size_t size);
|
||||||
|
void OnReceiveCompleteData(const char *data, size_t size);
|
||||||
|
|
||||||
|
public:
|
||||||
|
void OnCongestionControlFeedback(
|
||||||
|
const webrtc::rtcp::CongestionControlFeedback &feedback);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int CreateVideoCodec(rtp::PAYLOAD_TYPE video_pt, bool hardware_acceleration);
|
||||||
|
int CreateAudioCodec();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void OnSentRtpPacket(const webrtc::RtpPacketToSend &packet);
|
||||||
|
void HandleTransportPacketsFeedback(
|
||||||
|
const webrtc::TransportPacketsFeedback &feedback);
|
||||||
|
void PostUpdates(webrtc::NetworkControlUpdate update);
|
||||||
|
void UpdateControlState();
|
||||||
|
void UpdateCongestedState();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<VideoChannelSend> video_channel_send_ = nullptr;
|
||||||
|
std::unique_ptr<AudioChannelSend> audio_channel_send_ = nullptr;
|
||||||
|
std::unique_ptr<DataChannelSend> data_channel_send_ = nullptr;
|
||||||
|
|
||||||
|
std::unique_ptr<VideoChannelReceive> video_channel_receive_ = nullptr;
|
||||||
|
std::unique_ptr<AudioChannelReceive> audio_channel_receive_ = nullptr;
|
||||||
|
std::unique_ptr<DataChannelReceive> data_channel_receive_ = nullptr;
|
||||||
|
|
||||||
|
OnReceiveVideo on_receive_video_ = nullptr;
|
||||||
|
OnReceiveAudio on_receive_audio_ = nullptr;
|
||||||
|
OnReceiveData on_receive_data_ = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
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::string remote_user_id_;
|
||||||
|
void *user_data_ = nullptr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<Clock> clock_;
|
||||||
|
webrtc::TransportFeedbackAdapter transport_feedback_adapter_;
|
||||||
|
std::unique_ptr<CongestionControl> controller_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<VideoEncoder> video_encoder_ = nullptr;
|
||||||
|
std::unique_ptr<VideoDecoder> video_decoder_ = nullptr;
|
||||||
|
bool b_force_i_frame_;
|
||||||
|
bool video_codec_inited_;
|
||||||
|
bool load_nvcodec_dll_success_;
|
||||||
|
bool hardware_acceleration_;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<AudioEncoder> audio_encoder_ = nullptr;
|
||||||
|
std::unique_ptr<AudioDecoder> audio_decoder_ = nullptr;
|
||||||
|
bool audio_codec_inited_ = false;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint64_t target_bitrate_ = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user