use std::{
fs::File,
io::{Seek, SeekFrom},
path::{Path, PathBuf},
};
use crate::{decoding::SYMPHONIA_PROBE, errors::ContainerError, utils::pair_extension};
use serde::{Deserialize, Serialize};
use symphonia::core::{
formats::FormatOptions, io::MediaSourceStream, meta::MetadataOptions, probe::Hint,
};
mod channel_layout;
pub use channel_layout::*;
mod codec;
pub use codec::*;
mod format;
pub use format::*;
mod sample_format;
pub use sample_format::*;
mod stream;
pub use stream::*;
#[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
pub struct MediaContainer {
path: PathBuf,
format: ContainerFormat,
stream: Stream,
}
impl MediaContainer {
pub(crate) fn set_path(&mut self, path: PathBuf) {
self.path = path;
}
}
impl MediaContainer {
pub(crate) fn from_file(mut file: File, path: PathBuf) -> Result<Self, ContainerError> {
let container_format = ContainerFormat::from_file(&mut file)
.ok_or_else(|| ContainerError::InvalidSource(path.clone()))?;
file.seek(SeekFrom::Start(0))?;
let mss = MediaSourceStream::new(Box::new(file), Default::default());
let fmt_opts = FormatOptions::default();
let metadata_opts = MetadataOptions::default();
let probed = SYMPHONIA_PROBE.format(&Hint::new(), mss, &fmt_opts, &metadata_opts)?;
let track = probed.format.default_track().unwrap().codec_params.clone();
let stream = Stream::try_from(track)?;
Ok(Self {
path,
format: container_format,
stream,
})
}
#[must_use]
pub fn path(&self) -> &Path {
&self.path
}
#[must_use]
pub fn container(&self) -> &ContainerFormat {
&self.format
}
#[must_use]
pub fn codec(&self) -> &Codec {
&self.stream.codec
}
#[must_use]
pub fn extension(&self) -> Option<&str> {
pair_extension(self.format, self.stream.codec)
}
#[must_use]
pub fn stream(&self) -> &Stream {
&self.stream
}
}