1use crate::{Result, codec};
8
9pub struct Bridge {
11 catalog: moq_mux::catalog::Producer,
12 track: moq_mux::container::Producer<moq_mux::catalog::hang::Container>,
13 announced: bool,
14}
15
16impl Bridge {
17 pub fn new(mut broadcast: moq_net::BroadcastProducer, catalog: moq_mux::catalog::Producer) -> Result<Self> {
19 let track = broadcast.unique_track(".vp8")?;
20 let producer = catalog.media_producer(track, moq_mux::catalog::hang::Container::Legacy);
21 Ok(Self {
22 catalog,
23 track: producer,
24 announced: false,
25 })
26 }
27
28 fn announce(&mut self) {
29 if self.announced {
30 return;
31 }
32 let name = self.track.track().name.clone();
33 let mut config = hang::catalog::VideoConfig::new(hang::catalog::VideoCodec::VP8);
34 config.container = hang::catalog::Container::Legacy;
35 config.timeline = Some(self.catalog.timeline_section(&name));
36 self.catalog.lock().video.renditions.insert(name, config);
37 self.announced = true;
38 }
39}
40
41impl codec::Bridge for Bridge {
42 fn push(&mut self, frame: codec::Frame) -> Result<()> {
43 self.announce();
44 let pts = moq_mux::container::Timestamp::from_micros(frame.timestamp_us)
45 .map_err(|err| crate::Error::Other(anyhow::anyhow!("invalid timestamp: {err}")))?;
46 let keyframe = frame.payload.first().map(|b| b & 0x01 == 0).unwrap_or(false);
48 self.track
49 .write(moq_mux::container::Frame {
50 timestamp: pts,
51 payload: frame.payload,
52 keyframe,
53 duration: None,
54 })
55 .map_err(|err| crate::Error::Other(anyhow::anyhow!("vp8 track write failed: {err}")))?;
56 Ok(())
57 }
58}
59
60impl Drop for Bridge {
61 fn drop(&mut self) {
62 self.catalog.lock().video.renditions.remove(&self.track.track().name);
63 }
64}