use serde::{Deserialize, Serialize};
use symphonia::core::codecs::CodecParameters;
use crate::{
errors::ContainerError,
media_container::{channel_layout::ChannelLayout, codec::Codec, sample_format::SampleFormat},
};
#[derive(Debug, PartialEq, Clone, Serialize, Deserialize, Copy)]
pub struct Stream {
pub(crate) codec: Codec,
pub(crate) sample_rate: u32,
pub(crate) time_base: Option<(u32, u32)>,
pub(crate) n_frames: Option<u64>,
pub(crate) start_ts: u64,
pub(crate) sample_format: Option<SampleFormat>,
pub(crate) bits_per_sample: Option<u32>,
pub(crate) bits_per_coded_sample: Option<u32>,
pub(crate) channels: usize,
pub(crate) channel_layout: Option<ChannelLayout>,
pub(crate) delay: Option<u32>,
pub(crate) padding: Option<u32>,
pub(crate) max_frames_per_packet: Option<u64>,
pub(crate) packet_data_integrity: bool,
pub(crate) frames_per_block: Option<u64>,
}
impl Stream {
#[must_use]
pub fn sample_rate(&self) -> u32 {
self.sample_rate
}
#[must_use]
pub fn duration(&self) -> Option<f64> {
let frames = self.n_frames? as f64;
let rate = f64::from(self.sample_rate);
Some(frames / rate)
}
#[must_use]
pub fn channel_count(&self) -> usize {
self.channels
}
#[must_use]
pub fn channel_layout(&self) -> Option<&ChannelLayout> {
self.channel_layout.as_ref()
}
}
impl TryFrom<CodecParameters> for Stream {
type Error = ContainerError;
fn try_from(value: CodecParameters) -> Result<Self, Self::Error> {
Ok(Self {
codec: Codec::try_from(value.codec)?,
sample_rate: value.sample_rate.ok_or(ContainerError::NoSampleRate)?,
time_base: value.time_base.map(|b| (b.numer, b.denom)),
n_frames: value.n_frames,
start_ts: value.start_ts,
sample_format: value.sample_format.map(SampleFormat::from),
bits_per_sample: value.bits_per_sample,
bits_per_coded_sample: value.bits_per_coded_sample,
channels: value
.channels
.ok_or(ContainerError::NoChannelCount)?
.count(),
channel_layout: value.channel_layout.map(ChannelLayout::from),
delay: value.delay,
padding: value.padding,
max_frames_per_packet: value.max_frames_per_packet,
packet_data_integrity: value.packet_data_integrity,
frames_per_block: value.frames_per_block,
})
}
}