#[cfg(test)]
mod track_local_static_test;
pub mod track_local_static_rtp;
pub mod track_local_static_sample;
use std::any::Any;
use std::fmt;
use std::sync::atomic::Ordering;
use std::sync::Arc;
use async_trait::async_trait;
use interceptor::{Attributes, RTPWriter};
use portable_atomic::AtomicBool;
use tokio::sync::Mutex;
use util::Unmarshal;
use crate::error::{Error, Result};
use crate::rtp_transceiver::rtp_codec::*;
use crate::rtp_transceiver::*;
#[async_trait]
pub trait TrackLocalWriter: fmt::Debug {
async fn write_rtp(&self, p: &rtp::packet::Packet) -> Result<usize>;
async fn write(&self, b: &[u8]) -> Result<usize>;
}
#[derive(Default, Debug, Clone)]
pub struct TrackLocalContext {
pub(crate) id: String,
pub(crate) params: RTCRtpParameters,
pub(crate) ssrc: SSRC,
pub(crate) write_stream: Option<Arc<dyn TrackLocalWriter + Send + Sync>>,
pub(crate) paused: Arc<AtomicBool>,
}
impl TrackLocalContext {
pub fn codec_parameters(&self) -> &[RTCRtpCodecParameters] {
&self.params.codecs
}
pub fn header_extensions(&self) -> &[RTCRtpHeaderExtensionParameters] {
&self.params.header_extensions
}
pub fn ssrc(&self) -> SSRC {
self.ssrc
}
pub fn write_stream(&self) -> Option<Arc<dyn TrackLocalWriter + Send + Sync>> {
self.write_stream.clone()
}
pub fn id(&self) -> String {
self.id.clone()
}
}
#[async_trait]
pub trait TrackLocal {
async fn bind(&self, t: &TrackLocalContext) -> Result<RTCRtpCodecParameters>;
async fn unbind(&self, t: &TrackLocalContext) -> Result<()>;
fn id(&self) -> &str;
fn stream_id(&self) -> &str;
fn kind(&self) -> RTPCodecType;
fn as_any(&self) -> &dyn Any;
}
#[derive(Default, Debug)]
pub(crate) struct TrackBinding {
id: String,
ssrc: SSRC,
payload_type: PayloadType,
params: RTCRtpParameters,
write_stream: Option<Arc<dyn TrackLocalWriter + Send + Sync>>,
sender_paused: Arc<AtomicBool>,
}
impl TrackBinding {
pub fn is_sender_paused(&self) -> bool {
self.sender_paused.load(Ordering::SeqCst)
}
}
pub(crate) struct InterceptorToTrackLocalWriter {
pub(crate) interceptor_rtp_writer: Mutex<Option<Arc<dyn RTPWriter + Send + Sync>>>,
sender_paused: Arc<AtomicBool>,
}
impl InterceptorToTrackLocalWriter {
pub(crate) fn new(paused: Arc<AtomicBool>) -> Self {
InterceptorToTrackLocalWriter {
interceptor_rtp_writer: Mutex::new(None),
sender_paused: paused,
}
}
fn is_sender_paused(&self) -> bool {
self.sender_paused.load(Ordering::SeqCst)
}
}
impl std::fmt::Debug for InterceptorToTrackLocalWriter {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("InterceptorToTrackLocalWriter").finish()
}
}
#[async_trait]
impl TrackLocalWriter for InterceptorToTrackLocalWriter {
async fn write_rtp(&self, pkt: &rtp::packet::Packet) -> Result<usize> {
if self.is_sender_paused() {
return Ok(0);
}
let interceptor_rtp_writer = self.interceptor_rtp_writer.lock().await;
if let Some(writer) = &*interceptor_rtp_writer {
let a = Attributes::new();
Ok(writer.write(pkt, &a).await?)
} else {
Ok(0)
}
}
async fn write(&self, mut b: &[u8]) -> Result<usize> {
let pkt = rtp::packet::Packet::unmarshal(&mut b)?;
self.write_rtp(&pkt).await
}
}