use crate::error::Result;
use crate::mp4::mux::bytes::invalid;
use crate::track::FourCc;
pub const DEFAULT_CHUNK_DURATION_MS: u32 = 500;
pub const DEFAULT_MAX_BUFFER: usize = 64 << 20;
pub const MAX_CHUNK_BYTES: usize = 1 << 20;
pub const MAX_CHUNK_SAMPLES: u32 = 65_536;
pub const MAX_CHUNK_DURATION_MS: u32 = 60_000;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Brand {
Isom,
Mp41,
Mp42,
QuickTime,
}
impl Brand {
pub(crate) fn ftyp(self) -> (FourCc, u32, Vec<FourCc>) {
let brands =
|list: &[&[u8; 4]]| -> Vec<FourCc> { list.iter().map(|b| FourCc(**b)).collect() };
match self {
Self::Isom => (
FourCc(*b"isom"),
512,
brands(&[b"isom", b"iso2", b"iso4", b"mp41"]),
),
Self::Mp41 => (FourCc(*b"mp41"), 0, brands(&[b"mp41", b"isom"])),
Self::Mp42 => (FourCc(*b"mp42"), 0, brands(&[b"mp42", b"isom", b"iso4"])),
Self::QuickTime => (FourCc(*b"qt "), 512, brands(&[b"qt "])),
}
}
pub(crate) fn signed_offsets(self) -> bool {
!matches!(self, Self::Mp41)
}
pub(crate) fn quicktime(self) -> bool {
matches!(self, Self::QuickTime)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct MuxOptions {
pub brand: Brand,
pub faststart: bool,
pub movie_timescale: u32,
pub chunk_duration_ms: u32,
pub max_buffer: usize,
}
impl Default for MuxOptions {
fn default() -> Self {
Self {
brand: Brand::Isom,
faststart: false,
movie_timescale: 1000,
chunk_duration_ms: DEFAULT_CHUNK_DURATION_MS,
max_buffer: DEFAULT_MAX_BUFFER,
}
}
}
impl MuxOptions {
pub(crate) fn check(&self) -> Result<()> {
if self.movie_timescale == 0 {
return Err(invalid(
"`MuxOptions::movie_timescale` is 0. Use a positive tick rate, such as 1000"
.to_owned(),
));
}
if self.chunk_duration_ms == 0 || self.chunk_duration_ms > MAX_CHUNK_DURATION_MS {
return Err(invalid(format!(
"`MuxOptions::chunk_duration_ms` is {}. Use 1 to {MAX_CHUNK_DURATION_MS}",
self.chunk_duration_ms
)));
}
if self.max_buffer < MAX_CHUNK_BYTES {
return Err(invalid(format!(
"`MuxOptions::max_buffer` is {}, below one chunk of {MAX_CHUNK_BYTES} bytes",
self.max_buffer
)));
}
Ok(())
}
}