use alloc::vec::Vec;
use crate::ac3::{Ac3SpecificBox, Ec3SpecificBox};
use crate::ac4::Ac4SpecificBox;
use crate::av1::Av1ConfigurationBox;
use crate::avc_config::AVCConfigurationBox;
use crate::dts::DtsSpecificBox;
use crate::flac::FlacSpecificBox;
use crate::hevc_config::HEVCConfigurationBox;
use crate::mp4esds::EsdsBox;
use crate::opus::OpusSpecificBox;
use crate::vp9::Vp9ConfigurationBox;
use crate::vvc_config::VvcConfigurationBox;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum DataCarriage {
Pes,
Sections,
}
impl DataCarriage {
pub fn name(&self) -> &'static str {
match self {
DataCarriage::Pes => "pes",
DataCarriage::Sections => "sections",
}
}
}
broadcast_common::impl_spec_display!(DataCarriage);
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum SubtitleFormat {
Ttml,
WebVtt,
DvbBitmap,
Teletext,
}
impl SubtitleFormat {
pub fn name(&self) -> &'static str {
match self {
SubtitleFormat::Ttml => "TTML (stpp)",
SubtitleFormat::WebVtt => "WebVTT (wvtt)",
SubtitleFormat::DvbBitmap => "DVB bitmap subtitle",
SubtitleFormat::Teletext => "Teletext",
}
}
}
broadcast_common::impl_spec_display!(SubtitleFormat);
#[derive(Debug, Clone)]
#[non_exhaustive]
pub enum CodecConfig {
Avc {
config: AVCConfigurationBox,
width: u16,
height: u16,
},
Hevc {
config: HEVCConfigurationBox,
width: u16,
height: u16,
},
Vvc {
config: VvcConfigurationBox,
width: u16,
height: u16,
},
Aac {
esds: EsdsBox,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Ac3 {
config: Ac3SpecificBox,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Eac3 {
config: Ec3SpecificBox,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Av1 {
config: Av1ConfigurationBox,
width: u16,
height: u16,
},
Vp9 {
config: Vp9ConfigurationBox,
width: u16,
height: u16,
},
Opus {
config: OpusSpecificBox,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Flac {
config: FlacSpecificBox,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Ac4 {
config: Ac4SpecificBox,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
MpegH {
config: crate::mpegh::MHADecoderConfigurationRecord,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Mpeg2Video {
esds: EsdsBox,
width: u16,
height: u16,
},
MpegAudio {
esds: EsdsBox,
layer: crate::mpeg_legacy::MpegAudioLayer,
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Dts {
config: DtsSpecificBox,
codec_fourcc: [u8; 4],
channel_count: u16,
sample_rate: u32,
sample_size: u16,
},
Vp8 {
width: u16,
height: u16,
},
Vorbis {
codec_private: Vec<u8>,
channels: u16,
sample_rate: u32,
},
Subtitle {
format: SubtitleFormat,
},
Data {
stream_type: u8,
descriptors: Vec<u8>,
carriage: DataCarriage,
},
}
impl CodecConfig {
pub(crate) fn is_audio(&self) -> bool {
matches!(
self,
CodecConfig::Aac { .. }
| CodecConfig::Ac3 { .. }
| CodecConfig::Eac3 { .. }
| CodecConfig::Opus { .. }
| CodecConfig::Flac { .. }
| CodecConfig::Ac4 { .. }
| CodecConfig::MpegH { .. }
| CodecConfig::Dts { .. }
| CodecConfig::MpegAudio { .. }
| CodecConfig::Vorbis { .. }
)
}
pub fn audio_sample_rate(&self) -> Option<u32> {
match self {
CodecConfig::Aac { sample_rate, .. }
| CodecConfig::Ac3 { sample_rate, .. }
| CodecConfig::Eac3 { sample_rate, .. }
| CodecConfig::Opus { sample_rate, .. }
| CodecConfig::Flac { sample_rate, .. }
| CodecConfig::Ac4 { sample_rate, .. }
| CodecConfig::MpegH { sample_rate, .. }
| CodecConfig::Dts { sample_rate, .. }
| CodecConfig::MpegAudio { sample_rate, .. }
| CodecConfig::Vorbis { sample_rate, .. } => Some(*sample_rate),
_ => None,
}
}
pub fn channels_with_lfe(&self) -> Option<u16> {
let n = match self {
CodecConfig::Ac3 { config, .. } => u16::from(config.channels_with_lfe()),
CodecConfig::Eac3 { config, .. } => u16::from(config.channels_with_lfe()),
CodecConfig::Aac { channel_count, .. }
| CodecConfig::Opus { channel_count, .. }
| CodecConfig::Flac { channel_count, .. }
| CodecConfig::Ac4 { channel_count, .. }
| CodecConfig::MpegH { channel_count, .. }
| CodecConfig::Dts { channel_count, .. }
| CodecConfig::MpegAudio { channel_count, .. } => *channel_count,
CodecConfig::Vorbis { channels, .. } => *channels,
_ => return None,
};
(n != 0).then_some(n)
}
pub fn nominal_bitrate(&self) -> Option<u32> {
let bps = match self {
CodecConfig::Ac3 { config, .. } => config.nominal_bitrate_kbps()?.checked_mul(1000)?,
CodecConfig::Eac3 { config, .. } => config.nominal_bitrate_kbps().checked_mul(1000)?,
CodecConfig::Aac { esds, .. } | CodecConfig::MpegAudio { esds, .. } => esds
.es_descriptor
.decoder_config
.as_ref()
.map_or(0, |dc| dc.avg_bitrate),
CodecConfig::Dts { config, .. } => config.avg_bitrate,
_ => return None,
};
(bps != 0).then_some(bps)
}
pub(crate) fn is_opaque_data(&self) -> bool {
matches!(self, CodecConfig::Data { .. })
}
pub(crate) fn is_subtitle(&self) -> bool {
matches!(self, CodecConfig::Subtitle { .. })
}
pub fn is_muxable_in_bmff(&self) -> bool {
!(self.is_opaque_data() || self.is_subtitle())
}
pub(crate) fn is_video(&self) -> bool {
matches!(
self,
CodecConfig::Avc { .. }
| CodecConfig::Hevc { .. }
| CodecConfig::Vvc { .. }
| CodecConfig::Av1 { .. }
| CodecConfig::Vp9 { .. }
| CodecConfig::Vp8 { .. }
| CodecConfig::Mpeg2Video { .. }
)
}
}