use alloc::vec::Vec;
use mpeg_ts::pid::Pid;
use super::{CodecConfig, DisplayGeometry, ProgramNumber, Sample, TrackId};
use crate::dovi::DoviDecoderConfigurationRecord;
use crate::hdr::HdrStaticMetadata;
#[derive(Clone, PartialEq, Eq)]
#[non_exhaustive]
pub struct TrackSpec {
pub track_id: TrackId,
pub timescale: u32,
pub config: CodecConfig,
pub source_pid: Option<Pid>,
pub es_info_descriptors: Vec<u8>,
pub program_number: Option<ProgramNumber>,
pub display: Option<DisplayGeometry>,
pub hdr: Option<HdrStaticMetadata>,
pub dovi: Option<DoviDecoderConfigurationRecord>,
pub hdr10plus: bool,
}
impl core::fmt::Debug for TrackSpec {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let mut d = f.debug_struct("TrackSpec");
d.field("track_id", &self.track_id)
.field("timescale", &self.timescale)
.field("config", &self.config)
.field("source_pid", &self.source_pid)
.field("es_info_descriptors", &self.es_info_descriptors)
.field("program_number", &self.program_number)
.field("display", &self.display);
if let Some(hdr) = &self.hdr {
d.field("hdr", hdr);
}
if let Some(dovi) = &self.dovi {
d.field("dovi", dovi);
}
if self.hdr10plus {
d.field("hdr10plus", &self.hdr10plus);
}
d.finish()
}
}
impl TrackSpec {
pub fn new(track_id: TrackId, timescale: u32, config: CodecConfig) -> Self {
let display = DisplayGeometry::from_codec_config(&config);
let hdr = match &config {
CodecConfig::Hevc { config, .. } => HdrStaticMetadata::from_hevc_record(&config.config),
_ => None,
};
Self {
track_id,
timescale,
config,
source_pid: None,
es_info_descriptors: Vec::new(),
program_number: None,
display,
hdr,
dovi: None,
hdr10plus: false,
}
}
pub fn with_hdr(mut self, hdr: Option<HdrStaticMetadata>) -> Self {
self.hdr = hdr;
self
}
pub fn with_hdr10plus(mut self, hdr10plus: bool) -> Self {
self.hdr10plus = hdr10plus;
self
}
pub fn with_dovi(mut self, dovi: Option<DoviDecoderConfigurationRecord>) -> Self {
self.dovi = dovi;
self
}
pub fn with_display(mut self, display: Option<DisplayGeometry>) -> Self {
self.display = display;
self
}
pub fn with_source(mut self, source_pid: Pid, es_info_descriptors: Vec<u8>) -> Self {
self.source_pid = Some(source_pid);
if matches!(self.config, CodecConfig::Hevc { .. }) {
self.dovi =
crate::dovi::find_video_stream_descriptor(&es_info_descriptors).map(|d| d.record);
}
self.es_info_descriptors = es_info_descriptors;
self
}
pub fn with_program(mut self, program_number: ProgramNumber) -> Self {
self.program_number = Some(program_number);
self
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct Track {
pub spec: TrackSpec,
pub samples: Vec<Sample>,
pub start_decode_time: u64,
pub encryption: Option<TrackEncryption>,
}
impl Track {
pub fn new(spec: TrackSpec, samples: Vec<Sample>) -> Self {
Self {
spec,
samples,
start_decode_time: 0,
encryption: None,
}
}
pub fn new_at(spec: TrackSpec, samples: Vec<Sample>, start_decode_time: u64) -> Self {
Self {
spec,
samples,
start_decode_time,
encryption: None,
}
}
pub fn with_start_decode_time(mut self, start_decode_time: u64) -> Self {
self.start_decode_time = start_decode_time;
self
}
pub fn track_id(&self) -> TrackId {
self.spec.track_id
}
pub fn timescale(&self) -> u32 {
self.spec.timescale
}
pub fn config(&self) -> &CodecConfig {
&self.spec.config
}
}
#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct TrackEncryption {
pub scheme: crate::cenc::CencScheme,
pub tenc: crate::cenc::TrackEncryptionBox,
pub samples: Vec<crate::cenc::SampleEncryptionEntry>,
pub constant_iv_senc: crate::cenc::ConstantIvSenc,
}
impl TrackEncryption {
#[allow(clippy::too_many_arguments)]
pub fn new(
scheme: crate::cenc::CencScheme,
tenc: crate::cenc::TrackEncryptionBox,
samples: Vec<crate::cenc::SampleEncryptionEntry>,
constant_iv_senc: crate::cenc::ConstantIvSenc,
) -> Self {
Self {
scheme,
tenc,
samples,
constant_iv_senc,
}
}
}