use std::collections::VecDeque;
use std::sync::{Arc, Mutex};
use crate::encoded::{EncodedVideoFrame, EncodedVideoTrack, EncoderRegistry};
use crate::media::Track;
use crate::{CustomVideoEncoder, PeerConnectionFactory, Result};
pub enum MixedVideoTrack {
Raw(Track),
Encoded(EncodedVideoTrack),
}
impl MixedVideoTrack {
pub fn track(&self) -> &Track {
match self {
Self::Raw(t) => t,
Self::Encoded(e) => e.track(),
}
}
pub fn as_encoded(&self) -> Option<&EncodedVideoTrack> {
match self {
Self::Encoded(e) => Some(e),
Self::Raw(_) => None,
}
}
pub fn as_raw(&self) -> Option<&Track> {
match self {
Self::Raw(t) => Some(t),
Self::Encoded(_) => None,
}
}
}
enum SlotConfig {
Raw {
id: String,
},
Encoded {
id: String,
width: u32,
height: u32,
queue: Arc<Mutex<VecDeque<EncodedVideoFrame>>>,
},
}
pub struct EncodedVideoBuilder {
registry: Arc<EncoderRegistry>,
slots: Vec<SlotConfig>,
}
impl EncodedVideoBuilder {
pub(crate) fn new() -> Self {
Self {
registry: EncoderRegistry::new(),
slots: Vec::new(),
}
}
pub fn add_raw_track(&mut self, id: &str) -> usize {
self.registry.add_raw_slot();
let idx = self.slots.len();
self.slots.push(SlotConfig::Raw { id: id.to_owned() });
idx
}
pub fn add_encoded_track(&mut self, id: &str, width: u32, height: u32) -> usize {
let queue = self.registry.add_encoded_slot();
let idx = self.slots.len();
self.slots.push(SlotConfig::Encoded {
id: id.to_owned(),
width,
height,
queue,
});
idx
}
pub fn add_track(&mut self, id: &str, width: u32, height: u32) -> usize {
self.add_encoded_track(id, width, height)
}
pub fn build(self) -> Result<(PeerConnectionFactory, Vec<MixedVideoTrack>)> {
let encoder = CustomVideoEncoder::from_registry(self.registry);
let factory = PeerConnectionFactory::with_custom_video_encoder(encoder)?;
let mut out = Vec::with_capacity(self.slots.len());
for slot in self.slots {
match slot {
SlotConfig::Raw { id } => {
let track = factory.create_video_track(&id)?;
out.push(MixedVideoTrack::Raw(track));
}
SlotConfig::Encoded {
id,
width,
height,
queue,
} => {
let track = factory.create_video_track(&id)?;
out.push(MixedVideoTrack::Encoded(EncodedVideoTrack::new(
track, queue, width, height,
)));
}
}
}
Ok((factory, out))
}
}