use crate::colour::ContainerColour;
#[cfg(any(feature = "mp4", feature = "mkv"))]
use crate::packet::Packet;
#[cfg(any(feature = "mp4", feature = "mkv"))]
use crate::track::{Track, TrackKind};
#[cfg(any(feature = "mp4", feature = "mkv"))]
pub(crate) fn last_packet_duration(track: &Track, packets: &[Packet]) -> Option<u64> {
let last = packets.last()?;
if last.duration.is_some() {
return last.duration;
}
if !matches!(track.kind, TrackKind::Audio | TrackKind::Video) {
return None;
}
let latest = packets.iter().map(|packet| packet.pts).max()?;
let previous = packets
.iter()
.map(|packet| packet.pts)
.filter(|&pts| pts < latest)
.max()?;
let gap = u64::try_from(i128::from(latest) - i128::from(previous)).ok()?;
let padding = i128::from(last.discard_padding.unwrap_or(0).max(0));
if padding == 0 {
return Some(gap);
}
let tick = i128::from(track.timebase.num.max(1));
let left = i128::from(gap) * tick - padding;
if left <= 0 {
return None;
}
u64::try_from(((2 * left + tick) / (2 * tick)).max(1)).ok()
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct RawElement {
pub id: u32,
pub body: Vec<u8>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MatroskaTrack {
pub uid: Option<u64>,
pub track_type: u64,
pub codec_id: String,
pub codec_private: Option<Vec<u8>>,
pub codec_name: Option<String>,
pub name: Option<String>,
pub language: String,
pub language_bcp47: Option<String>,
pub default_duration: Option<u64>,
pub codec_delay: u64,
pub seek_pre_roll: u64,
pub enabled: bool,
pub default: bool,
pub forced: bool,
pub lacing: bool,
pub content_encodings: Vec<ContentEncoding>,
pub video: Option<MatroskaVideo>,
pub audio: Option<MatroskaAudio>,
pub extra: Vec<RawElement>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum DisplayUnit {
Pixels,
Centimeters,
Inches,
AspectRatio,
Unknown,
Other(u64),
}
impl DisplayUnit {
pub fn from_value(value: u64) -> Self {
match value {
0 => Self::Pixels,
1 => Self::Centimeters,
2 => Self::Inches,
3 => Self::AspectRatio,
4 => Self::Unknown,
other => Self::Other(other),
}
}
pub const fn value(self) -> u64 {
match self {
Self::Pixels => 0,
Self::Centimeters => 1,
Self::Inches => 2,
Self::AspectRatio => 3,
Self::Unknown => 4,
Self::Other(value) => value,
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct Projection {
pub projection_type: u64,
pub private: Option<Vec<u8>>,
pub pose_yaw: f64,
pub pose_pitch: f64,
pub pose_roll: f64,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MatroskaVideo {
pub pixel_width: u64,
pub pixel_height: u64,
pub display_width: Option<u64>,
pub display_height: Option<u64>,
pub display_unit: DisplayUnit,
pub crop: [u64; 4],
pub interlaced: u64,
pub projection: Option<Projection>,
pub colour: Option<ContainerColour>,
pub extra: Vec<RawElement>,
}
#[derive(Clone, Debug, PartialEq)]
pub struct MatroskaAudio {
pub sampling_frequency: f64,
pub output_sampling_frequency: Option<f64>,
pub channels: u64,
pub bit_depth: Option<u64>,
pub extra: Vec<RawElement>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ContentEncoding {
pub order: u64,
pub scope: u64,
pub encoding_type: u64,
pub compression_algorithm: Option<u64>,
pub compression_settings: Option<Vec<u8>>,
pub encryption_algorithm: Option<u64>,
pub encryption_settings: Option<Vec<u8>>,
}