use super::encoder::FlexFec03Encoder;
use crate::Interceptor;
use crate::stream_info::StreamInfo;
use crate::{AttributedPacket, Packet, TaggedPacket};
use sansio::Protocol;
use shared::error::Error;
use std::collections::{HashMap, VecDeque};
use std::time::Instant;
pub const DEFAULT_NUM_MEDIA_PACKETS: u32 = 5;
pub const DEFAULT_NUM_FEC_PACKETS: u32 = 2;
pub struct FlexFec03SendBuilder {
num_media_packets: u32,
num_fec_packets: u32,
}
impl Default for FlexFec03SendBuilder {
fn default() -> Self {
Self {
num_media_packets: DEFAULT_NUM_MEDIA_PACKETS,
num_fec_packets: DEFAULT_NUM_FEC_PACKETS,
}
}
}
impl FlexFec03SendBuilder {
pub fn new() -> Self {
Self::default()
}
pub fn with_num_media_packets(mut self, num_media_packets: u32) -> Self {
self.num_media_packets = num_media_packets;
self
}
pub fn with_num_fec_packets(mut self, num_fec_packets: u32) -> Self {
self.num_fec_packets = num_fec_packets;
self
}
pub fn build(self) -> FlexFec03SendInterceptor {
FlexFec03SendInterceptor::new(self.num_media_packets, self.num_fec_packets)
}
}
struct ProtectedStream {
encoder: FlexFec03Encoder,
block: Vec<rtp::Packet>,
}
pub struct FlexFec03SendInterceptor {
num_media_packets: u32,
num_fec_packets: u32,
streams: HashMap<u32, ProtectedStream>,
read_queue: VecDeque<TaggedPacket>,
write_queue: VecDeque<TaggedPacket>,
}
impl FlexFec03SendInterceptor {
fn new(num_media_packets: u32, num_fec_packets: u32) -> Self {
Self {
read_queue: VecDeque::new(),
write_queue: VecDeque::new(),
num_media_packets: num_media_packets.max(1),
num_fec_packets,
streams: HashMap::new(),
}
}
pub fn protected_streams(&self) -> impl Iterator<Item = u32> + '_ {
self.streams.keys().copied()
}
}
impl Protocol<TaggedPacket, TaggedPacket, ()> for FlexFec03SendInterceptor {
type Rout = TaggedPacket;
type Wout = TaggedPacket;
type Eout = ();
type Error = Error;
type Time = Instant;
fn handle_read(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
self.read_queue.push_back(msg);
Ok(())
}
fn poll_read(&mut self) -> Option<Self::Rout> {
self.read_queue.pop_front()
}
fn handle_write(&mut self, msg: TaggedPacket) -> Result<(), Self::Error> {
let Packet::Rtp(rtp_packet) = &msg.message.packet else {
self.write_queue.push_back(msg);
return Ok(());
};
let ssrc = rtp_packet.header.ssrc;
let now = msg.now;
let transport = msg.transport;
let Some(stream) = self.streams.get_mut(&ssrc) else {
self.write_queue.push_back(msg);
return Ok(());
};
stream.block.push(rtp_packet.clone());
let repair_packets = if stream.block.len() as u32 >= self.num_media_packets {
let repair = stream.encoder.encode(&stream.block, self.num_fec_packets);
stream.block.clear();
repair
} else {
Vec::new()
};
self.write_queue.push_back(msg);
for packet in repair_packets {
self.write_queue.push_back(TaggedPacket {
now,
transport,
message: AttributedPacket::new(Packet::Rtp(packet)),
});
}
Ok(())
}
fn poll_write(&mut self) -> Option<TaggedPacket> {
self.write_queue.pop_front()
}
fn handle_timeout(&mut self, _now: Instant) -> Result<(), Self::Error> {
Ok(())
}
fn poll_timeout(&mut self) -> Option<Self::Time> {
None
}
}
impl Interceptor for FlexFec03SendInterceptor {
fn bind_local_stream(&mut self, info: &StreamInfo) {
if let (Some(ssrc_fec), Some(payload_type_fec)) = (info.ssrc_fec, info.payload_type_fec) {
self.streams.insert(
info.ssrc,
ProtectedStream {
encoder: FlexFec03Encoder::new(payload_type_fec, ssrc_fec),
block: Vec::new(),
},
);
}
}
fn unbind_local_stream(&mut self, info: &StreamInfo) {
self.streams.remove(&info.ssrc);
}
fn bind_remote_stream(&mut self, _info: &StreamInfo) {}
fn unbind_remote_stream(&mut self, _info: &StreamInfo) {}
}