use crate::{Result, codec};
pub struct Bridge {
rendition: codec::VideoRendition,
track: moq_mux::container::Producer<moq_mux::catalog::hang::Container>,
announced: bool,
}
impl Bridge {
pub fn new(mut broadcast: moq_net::broadcast::Producer, catalog: moq_mux::catalog::Producer) -> Result<Self> {
let track = broadcast.create_track(broadcast.unique_name(".vp8"), hang::container::track_info())?;
let name = track.name().to_string();
let producer = catalog.media_producer(track, moq_mux::catalog::hang::Container::Legacy)?;
Ok(Self {
rendition: codec::VideoRendition { catalog, name },
track: producer,
announced: false,
})
}
fn announce(&mut self) -> Result<()> {
if self.announced {
return Ok(());
}
let name = self.rendition.name.clone();
let mut config = hang::catalog::VideoConfig::new(hang::catalog::VideoCodec::VP8);
config.container = hang::catalog::Container::Legacy;
config.timeline = Some(self.rendition.catalog.timeline(&name)?.section());
let mut guard = self.rendition.catalog.lock();
guard.video.renditions.insert(name, config);
guard.commit()?;
self.announced = true;
Ok(())
}
}
impl codec::Bridge for Bridge {
fn push(&mut self, frame: codec::Frame) -> Result<()> {
self.announce()?;
let pts = moq_net::Timestamp::from_micros(frame.timestamp_us)
.map_err(|err| crate::Error::Other(anyhow::anyhow!("invalid timestamp: {err}")))?;
let keyframe = frame.payload.first().map(|b| b & 0x01 == 0).unwrap_or(false);
self.track
.write(moq_mux::container::Frame {
timestamp: pts,
payload: frame.payload,
keyframe,
duration: None,
})
.map_err(|err| crate::Error::Other(anyhow::anyhow!("vp8 track write failed: {err}")))?;
Ok(())
}
fn abort(self: Box<Self>, err: moq_net::Error) {
self.track.abort(err);
}
}