use crate::{Result, codec};
pub struct Bridge {
catalog: moq_mux::catalog::Producer,
track: moq_mux::container::Producer<moq_mux::catalog::hang::Container>,
announced: bool,
}
impl Bridge {
pub fn new(mut broadcast: moq_net::BroadcastProducer, catalog: moq_mux::catalog::Producer) -> Result<Self> {
let track = broadcast.unique_track(".vp9")?;
let producer = moq_mux::container::Producer::new(track, moq_mux::catalog::hang::Container::Legacy);
Ok(Self {
catalog,
track: producer,
announced: false,
})
}
fn announce(&mut self) {
if self.announced {
return;
}
let mut config = hang::catalog::VideoConfig::new(hang::catalog::VP9::default());
config.container = hang::catalog::Container::Legacy;
self.catalog
.lock()
.video
.renditions
.insert(self.track.track().name.clone(), config);
self.announced = true;
}
}
impl codec::Bridge for Bridge {
fn push(&mut self, frame: codec::Frame) -> Result<()> {
self.announce();
let pts = moq_mux::container::Timestamp::from_micros(frame.timestamp_us)
.map_err(|err| crate::Error::Other(anyhow::anyhow!("invalid timestamp: {err}")))?;
let keyframe = is_keyframe(&frame.payload);
self.track
.write(moq_mux::container::Frame {
timestamp: pts,
payload: frame.payload,
keyframe,
duration: None,
})
.map_err(|err| crate::Error::Other(anyhow::anyhow!("vp9 track write failed: {err}")))?;
Ok(())
}
}
fn is_keyframe(payload: &[u8]) -> bool {
let Some(&b) = payload.first() else {
return false;
};
let profile = (((b >> 4) & 1) << 1) | ((b >> 5) & 1); let mut pos = 4;
if profile == 3 {
pos += 1;
}
let show_existing_frame = (b >> (7 - pos)) & 1;
if show_existing_frame == 1 {
return false;
}
pos += 1;
let frame_type = (b >> (7 - pos)) & 1;
frame_type == 0
}
impl Drop for Bridge {
fn drop(&mut self) {
self.catalog.lock().video.renditions.remove(&self.track.track().name);
}
}
#[cfg(test)]
mod tests {
use super::is_keyframe;
#[test]
fn profile0_keyframe_and_interframe() {
assert!(is_keyframe(&[0b1000_0010]));
assert!(!is_keyframe(&[0b1000_0110]));
}
#[test]
fn profile0_show_existing_frame_is_not_keyframe() {
assert!(!is_keyframe(&[0b1000_1000]));
}
#[test]
fn profile3_keyframe_and_interframe() {
assert!(is_keyframe(&[0b1011_0000])); assert!(!is_keyframe(&[0b1011_0010])); }
#[test]
fn empty_payload_is_not_keyframe() {
assert!(!is_keyframe(&[]));
}
}