use std::sync::Arc;
use tokio::sync::RwLock;
use tracing::debug;
use crate::api::common::error::MediaTransportError;
use crate::api::common::frame::MediaFrame;
use crate::buffer::{
BufferPool, GlobalBufferManager, PacketPriority, TransmitBuffer, TransmitBufferConfig,
};
use crate::transport::RtpTransport;
pub async fn init_transmit_buffer(
buffer_manager: &Option<Arc<GlobalBufferManager>>,
packet_pool: &Option<Arc<BufferPool>>,
transmit_buffer: &Arc<RwLock<Option<TransmitBuffer>>>,
ssrc: u32,
buffer_config: TransmitBufferConfig,
) -> Result<(), MediaTransportError> {
if let Some(buffer_manager) = buffer_manager {
if let Some(packet_pool) = packet_pool {
let tx_buffer = TransmitBuffer::with_buffer_manager(
ssrc,
buffer_config,
buffer_manager.clone(),
packet_pool.clone(),
);
let mut tx_buffer_guard = transmit_buffer.write().await;
*tx_buffer_guard = Some(tx_buffer);
debug!(
"Initialized high-performance transmit buffer for SSRC {:#x}",
ssrc
);
}
}
Ok(())
}
pub async fn send_frame_with_priority(
frame: MediaFrame,
priority: PacketPriority,
high_performance_buffers_enabled: bool,
transmit_buffer: &Arc<RwLock<Option<TransmitBuffer>>>,
transport: &Arc<tokio::sync::Mutex<Option<Arc<dyn RtpTransport>>>>,
remote_address: std::net::SocketAddr,
fallback_send_frame: impl Fn(MediaFrame) -> Result<(), MediaTransportError>,
) -> Result<(), MediaTransportError> {
if high_performance_buffers_enabled {
let mut tx_buffer_guard = transmit_buffer.write().await;
if let Some(tx_buffer) = tx_buffer_guard.as_mut() {
let mut header = crate::packet::RtpHeader::new(
frame.payload_type,
frame.sequence,
frame.timestamp,
frame.ssrc,
);
if frame.marker {
header.marker = true;
}
if !frame.csrcs.is_empty() {
header.add_csrcs(&frame.csrcs);
}
let packet = crate::packet::RtpPacket::new(header, frame.data);
debug!(
"Queuing packet with priority {:?}: PT={}, SEQ={}, TS={}",
priority,
packet.header.payload_type,
packet.header.sequence_number,
packet.header.timestamp
);
if tx_buffer.queue_packet(packet, priority).await {
if let Some(packet) = tx_buffer.get_next_packet().await {
let transport_guard = transport.lock().await;
if let Some(transport) = transport_guard.as_ref() {
transport
.send_rtp(&packet, remote_address)
.await
.map_err(|e| {
MediaTransportError::SendError(format!(
"Failed to send RTP packet: {}",
e
))
})?;
tx_buffer.acknowledge_packet(packet.header.sequence_number);
return Ok(());
} else {
return Err(MediaTransportError::Transport(
"Transport not connected".to_string(),
));
}
}
}
return Err(MediaTransportError::BufferFull(
"Transmit buffer is full".to_string(),
));
}
}
debug!("Falling back to regular send_frame");
fallback_send_frame(frame)
}
pub async fn update_transmit_buffer_config(
high_performance_buffers_enabled: bool,
transmit_buffer: &Arc<RwLock<Option<TransmitBuffer>>>,
config: TransmitBufferConfig,
) -> Result<(), MediaTransportError> {
if high_performance_buffers_enabled {
let mut tx_buffer_guard = transmit_buffer.write().await;
if let Some(tx_buffer) = tx_buffer_guard.as_mut() {
tx_buffer.update_config(config);
debug!("Updated transmit buffer configuration");
return Ok(());
}
}
Err(MediaTransportError::ConfigError(
"High-performance buffers not enabled".to_string(),
))
}
pub async fn set_priority_threshold(
high_performance_buffers_enabled: bool,
transmit_buffer: &Arc<RwLock<Option<TransmitBuffer>>>,
buffer_fullness: f32,
priority: PacketPriority,
) -> Result<(), MediaTransportError> {
if high_performance_buffers_enabled {
let mut tx_buffer_guard = transmit_buffer.write().await;
if let Some(tx_buffer) = tx_buffer_guard.as_mut() {
tx_buffer.set_priority_threshold(buffer_fullness, priority);
debug!(
"Set priority threshold: {}% fullness -> {:?} priority",
buffer_fullness * 100.0,
priority
);
return Ok(());
}
}
Err(MediaTransportError::ConfigError(
"High-performance buffers not enabled".to_string(),
))
}