Skip to main content

moq_rtc/codec/
av1.rs

1//! AV1 bridge.
2//!
3//! str0m hands us complete AV1 temporal units (OBU-framed, with inline sequence
4//! headers). This feeds the moq-mux AV1 splitter/importer so catalog config and
5//! keyframe detection stay shared with the other ingest paths.
6
7use crate::{Result, codec};
8
9/// Bridges str0m AV1 temporal units into a MoQ AV1 track.
10pub struct Bridge {
11	split: moq_mux::codec::av1::Split,
12	import: moq_mux::codec::av1::Import,
13}
14
15impl Bridge {
16	/// Publish an `.av1` track on `broadcast`, adding the catalog rendition once config is known.
17	pub fn new(mut broadcast: moq_net::BroadcastProducer, catalog: moq_mux::catalog::Producer) -> Result<Self> {
18		let track = moq_mux::import::unique_track(&mut broadcast, ".av1")?;
19		let import = moq_mux::codec::av1::Import::new(track, catalog);
20		let split = moq_mux::codec::av1::Split::new();
21		Ok(Self { split, import })
22	}
23}
24
25impl codec::Bridge for Bridge {
26	fn push(&mut self, frame: codec::Frame) -> Result<()> {
27		let pts = moq_mux::container::Timestamp::from_micros(frame.timestamp_us)
28			.map_err(|err| crate::Error::Other(anyhow::anyhow!("invalid timestamp: {err}")))?;
29		// str0m hands over one whole temporal unit per frame, so flush to emit it.
30		let mut frames = self.split.decode(&frame.payload, Some(pts))?;
31		frames.extend(self.split.flush(Some(pts))?);
32		self.import.decode(frames)?;
33		Ok(())
34	}
35}