use std::{fmt, str::FromStr};
use bytes::Buf;
use hang::Error;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[non_exhaustive]
pub enum StreamFormat {
Avc3,
Fmp4,
Hev1,
Av01,
}
impl FromStr for StreamFormat {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"avc3" => Ok(StreamFormat::Avc3),
"h264" | "annex-b" => {
tracing::warn!("format '{s}' is deprecated, use 'avc3' instead");
Ok(StreamFormat::Avc3)
}
"hev1" => Ok(StreamFormat::Hev1),
"fmp4" | "cmaf" => Ok(StreamFormat::Fmp4),
"av01" | "av1" | "av1C" => Ok(StreamFormat::Av01),
_ => Err(Error::UnknownFormat(s.to_string())),
}
}
}
impl fmt::Display for StreamFormat {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match *self {
StreamFormat::Avc3 => write!(f, "avc3"),
StreamFormat::Fmp4 => write!(f, "fmp4"),
StreamFormat::Hev1 => write!(f, "hev1"),
StreamFormat::Av01 => write!(f, "av01"),
}
}
}
#[derive(derive_more::From)]
enum StreamKind {
Avc3(super::Avc3),
Fmp4(Box<super::Fmp4>),
Hev1(super::Hev1),
Av01(super::Av01),
}
pub struct Stream {
decoder: StreamKind,
}
impl Stream {
pub fn new(
broadcast: moq_lite::BroadcastProducer,
catalog: crate::catalog::Producer,
format: StreamFormat,
) -> Self {
let decoder = match format {
StreamFormat::Avc3 => super::Avc3::new(broadcast, catalog).into(),
StreamFormat::Fmp4 => Box::new(super::Fmp4::new(broadcast, catalog)).into(),
StreamFormat::Hev1 => super::Hev1::new(broadcast, catalog).into(),
StreamFormat::Av01 => super::Av01::new(broadcast, catalog).into(),
};
Self { decoder }
}
pub fn initialize<T: Buf + AsRef<[u8]>>(&mut self, buf: &mut T) -> anyhow::Result<()> {
match self.decoder {
StreamKind::Avc3(ref mut decoder) => decoder.initialize(buf)?,
StreamKind::Fmp4(ref mut decoder) => decoder.decode(buf)?,
StreamKind::Hev1(ref mut decoder) => decoder.initialize(buf)?,
StreamKind::Av01(ref mut decoder) => decoder.initialize(buf)?,
}
anyhow::ensure!(!buf.has_remaining(), "buffer was not fully consumed");
Ok(())
}
pub fn decode_stream<T: Buf + AsRef<[u8]>>(&mut self, buf: &mut T) -> anyhow::Result<()> {
match self.decoder {
StreamKind::Avc3(ref mut decoder) => decoder.decode_stream(buf, None),
StreamKind::Fmp4(ref mut decoder) => decoder.decode(buf),
StreamKind::Hev1(ref mut decoder) => decoder.decode_stream(buf, None),
StreamKind::Av01(ref mut decoder) => decoder.decode_stream(buf, None),
}
}
pub fn finish(&mut self) -> anyhow::Result<()> {
match self.decoder {
StreamKind::Avc3(ref mut decoder) => decoder.finish(),
StreamKind::Fmp4(ref mut decoder) => decoder.finish(),
StreamKind::Hev1(ref mut decoder) => decoder.finish(),
StreamKind::Av01(ref mut decoder) => decoder.finish(),
}
}
pub fn is_initialized(&self) -> bool {
match self.decoder {
StreamKind::Avc3(ref decoder) => decoder.is_initialized(),
StreamKind::Fmp4(ref decoder) => decoder.is_initialized(),
StreamKind::Hev1(ref decoder) => decoder.is_initialized(),
StreamKind::Av01(ref decoder) => decoder.is_initialized(),
}
}
}