use super::decoder::FlexFec03Decoder;
use crate::stream_info::StreamInfo;
use crate::{Interceptor, Packet, TaggedPacket, interceptor};
use shared::error::Error;
use std::collections::HashMap;
use std::marker::PhantomData;
pub struct FlexFec03ReceiveBuilder<P> {
_phantom: PhantomData<P>,
}
impl<P> Default for FlexFec03ReceiveBuilder<P> {
fn default() -> Self {
Self {
_phantom: PhantomData,
}
}
}
impl<P> FlexFec03ReceiveBuilder<P> {
pub fn new() -> Self {
Self::default()
}
pub fn build(self) -> impl FnOnce(P) -> FlexFec03ReceiveInterceptor<P> {
move |inner| FlexFec03ReceiveInterceptor::new(inner)
}
}
#[derive(Interceptor)]
pub struct FlexFec03ReceiveInterceptor<P> {
#[next]
inner: P,
decoders: HashMap<u32, FlexFec03Decoder>,
repair_to_media: HashMap<u32, u32>,
}
impl<P> FlexFec03ReceiveInterceptor<P> {
fn new(inner: P) -> Self {
Self {
inner,
decoders: HashMap::new(),
repair_to_media: HashMap::new(),
}
}
pub fn protected_streams(&self) -> impl Iterator<Item = u32> + '_ {
self.decoders.keys().copied()
}
}
#[interceptor]
impl<P: Interceptor> FlexFec03ReceiveInterceptor<P> {
#[overrides]
fn bind_remote_stream(&mut self, info: &StreamInfo) {
if let (Some(ssrc_fec), Some(_)) = (info.ssrc_fec, info.payload_type_fec) {
self.decoders
.insert(info.ssrc, FlexFec03Decoder::new(ssrc_fec, info.ssrc));
self.repair_to_media.insert(ssrc_fec, info.ssrc);
}
self.inner.bind_remote_stream(info);
}
#[overrides]
fn unbind_remote_stream(&mut self, info: &StreamInfo) {
self.decoders.remove(&info.ssrc);
self.repair_to_media.retain(|_, media| *media != info.ssrc);
self.inner.unbind_remote_stream(info);
}
#[overrides]
fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
let Packet::Rtp(rtp_packet) = &msg.message else {
return self.inner.handle_read(msg);
};
let ssrc = rtp_packet.header.ssrc;
let now = msg.now;
let transport = msg.transport;
if let Some(&media_ssrc) = self.repair_to_media.get(&ssrc) {
let recovered = match self.decoders.get_mut(&media_ssrc) {
Some(decoder) => decoder.decode(rtp_packet.clone()),
None => Vec::new(),
};
return self.forward_recovered(now, transport, recovered);
}
let recovered = match self.decoders.get_mut(&ssrc) {
Some(decoder) => decoder.decode(rtp_packet.clone()),
None => return self.inner.handle_read(msg),
};
self.inner.handle_read(msg)?;
self.forward_recovered(now, transport, recovered)
}
}
impl<P: Interceptor> FlexFec03ReceiveInterceptor<P> {
fn forward_recovered(
&mut self,
now: std::time::Instant,
transport: shared::TransportContext,
recovered: Vec<rtp::Packet>,
) -> Result<(), Error> {
for packet in recovered {
self.inner.handle_read(TaggedPacket {
now,
transport,
message: Packet::Rtp(packet),
})?;
}
Ok(())
}
}