use super::{ContainerFormat, ContainerInit};
use crate::Result;
enum ContainerImpl<E: crate::container::ts::Catalog = ()> {
Fmp4(Box<crate::container::fmp4::Import<E>>),
Mkv(Box<crate::container::mkv::Import<E>>),
Ts(Box<crate::container::ts::Import<E>>),
Flv(Box<crate::container::flv::Import<E>>),
}
impl<E: crate::container::ts::Catalog> ContainerImpl<E> {
fn new(
broadcast: moq_net::broadcast::Producer,
reserved: crate::catalog::Reserved<E>,
format: ContainerFormat,
) -> Self {
match format {
ContainerFormat::Fmp4 => Self::fmp4(broadcast, reserved),
ContainerFormat::Mkv => Self::mkv(broadcast, reserved),
ContainerFormat::Ts => Self::ts(broadcast, reserved),
ContainerFormat::Flv => Self::flv(broadcast, reserved),
}
}
fn fmp4(broadcast: moq_net::broadcast::Producer, reserved: crate::catalog::Reserved<E>) -> Self {
ContainerImpl::Fmp4(Box::new(crate::container::fmp4::Import::new(broadcast, reserved)))
}
fn mkv(broadcast: moq_net::broadcast::Producer, reserved: crate::catalog::Reserved<E>) -> Self {
ContainerImpl::Mkv(Box::new(crate::container::mkv::Import::new(broadcast, reserved)))
}
fn ts(broadcast: moq_net::broadcast::Producer, reserved: crate::catalog::Reserved<E>) -> Self {
ContainerImpl::Ts(Box::new(crate::container::ts::Import::new(broadcast, reserved)))
}
fn flv(broadcast: moq_net::broadcast::Producer, reserved: crate::catalog::Reserved<E>) -> Self {
ContainerImpl::Flv(Box::new(crate::container::flv::Import::new(broadcast, reserved)))
}
fn decode(&mut self, data: &[u8]) -> Result<()> {
match self {
ContainerImpl::Fmp4(decoder) => decoder.decode(data),
ContainerImpl::Mkv(decoder) => decoder.decode(data),
ContainerImpl::Ts(decoder) => decoder.decode(data).map_err(Into::into),
ContainerImpl::Flv(decoder) => decoder.decode(data),
}
}
fn finish(&mut self) -> Result<()> {
match self {
ContainerImpl::Fmp4(decoder) => decoder.finish(),
ContainerImpl::Mkv(decoder) => decoder.finish(),
ContainerImpl::Ts(decoder) => decoder.finish().map_err(Into::into),
ContainerImpl::Flv(decoder) => decoder.finish(),
}
}
fn abort(self, err: moq_net::Error) {
match self {
ContainerImpl::Fmp4(decoder) => decoder.abort(err),
ContainerImpl::Mkv(decoder) => decoder.abort(err),
ContainerImpl::Ts(decoder) => decoder.abort(err),
ContainerImpl::Flv(decoder) => decoder.abort(err),
}
}
fn cut(&mut self) {
if let ContainerImpl::Fmp4(decoder) = self {
decoder.cut();
}
}
fn seek(&mut self, sequence: u64) -> Result<()> {
match self {
ContainerImpl::Fmp4(decoder) => decoder.seek(sequence),
ContainerImpl::Mkv(decoder) => decoder.seek(sequence),
ContainerImpl::Ts(decoder) => decoder.seek(sequence).map_err(Into::into),
ContainerImpl::Flv(decoder) => decoder.seek(sequence),
}
}
}
pub struct Container<E: crate::container::ts::Catalog = ()> {
inner: ContainerImpl<E>,
}
impl<E: crate::container::ts::Catalog> Container<E> {
pub fn new(
broadcast: moq_net::broadcast::Producer,
reserved: crate::catalog::Reserved<E>,
init: &ContainerInit,
) -> Result<Self> {
let mut inner = ContainerImpl::new(broadcast, reserved, init.format);
inner.decode(&init.data)?;
Ok(Self { inner })
}
pub fn decode(&mut self, data: &[u8]) -> Result<()> {
self.inner.decode(data)
}
pub fn finish(&mut self) -> Result<()> {
self.inner.finish()
}
pub fn abort(self, err: moq_net::Error) {
self.inner.abort(err)
}
pub fn cut(&mut self) {
self.inner.cut()
}
pub fn seek(&mut self, sequence: u64) -> Result<()> {
self.inner.seek(sequence)
}
}
pub struct ContainerStream<E: crate::container::ts::Catalog = ()> {
inner: ContainerImpl<E>,
}
impl<E: crate::container::ts::Catalog> ContainerStream<E> {
pub fn new(
broadcast: moq_net::broadcast::Producer,
reserved: crate::catalog::Reserved<E>,
format: ContainerFormat,
) -> Result<Self> {
let inner = ContainerImpl::new(broadcast, reserved, format);
Ok(Self { inner })
}
pub fn decode(&mut self, data: &[u8]) -> Result<()> {
self.inner.decode(data)
}
pub fn finish(&mut self) -> Result<()> {
self.inner.finish()
}
pub fn abort(self, err: moq_net::Error) {
self.inner.abort(err)
}
pub fn cut(&mut self) {
self.inner.cut()
}
pub fn seek(&mut self, sequence: u64) -> Result<()> {
self.inner.seek(sequence)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn a_split_stream_publishes_its_tracks() {
let data = include_bytes!("../container/fmp4/test_data/bbb.mp4");
let (head, tail) = data.split_at(100);
let mut broadcast = moq_net::broadcast::Info::new().produce();
let catalog = crate::catalog::Producer::new(&mut broadcast, crate::catalog::Config::default()).unwrap();
let mut stream: ContainerStream =
ContainerStream::new(broadcast, catalog.reserve(), ContainerFormat::Fmp4).unwrap();
stream.decode(head).unwrap();
let _ = stream.decode(tail);
let snapshot = catalog.snapshot();
assert_eq!(
snapshot.video.renditions.len(),
1,
"video rendition missing from a split stream"
);
assert_eq!(
snapshot.audio.renditions.len(),
1,
"audio rendition missing from a split stream"
);
}
}