#[allow(dead_code)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerDef {
Mxf,
QuickTime,
Avid,
Bwf,
Wave,
}
impl ContainerDef {
#[must_use]
pub fn extension(&self) -> &'static str {
match self {
ContainerDef::Mxf => "mxf",
ContainerDef::QuickTime => "mov",
ContainerDef::Avid => "omf",
ContainerDef::Bwf => "bwf",
ContainerDef::Wave => "wav",
}
}
#[must_use]
pub fn is_mxf(&self) -> bool {
matches!(self, ContainerDef::Mxf)
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct VideoDescriptor {
pub codec: String,
pub width: u32,
pub height: u32,
pub frame_rate_num: u32,
pub frame_rate_den: u32,
pub bit_depth: u8,
pub color_space: String,
}
impl VideoDescriptor {
#[must_use]
pub fn new(
codec: String,
width: u32,
height: u32,
frame_rate_num: u32,
frame_rate_den: u32,
bit_depth: u8,
color_space: String,
) -> Self {
Self {
codec,
width,
height,
frame_rate_num,
frame_rate_den,
bit_depth,
color_space,
}
}
#[allow(clippy::cast_precision_loss)]
#[must_use]
pub fn frame_rate(&self) -> f64 {
if self.frame_rate_den == 0 {
return 0.0;
}
self.frame_rate_num as f64 / self.frame_rate_den as f64
}
#[must_use]
pub fn is_hd(&self) -> bool {
(self.width >= 1280 && self.height >= 720) && !self.is_4k()
}
#[must_use]
pub fn is_4k(&self) -> bool {
self.width >= 3840
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct AudioDescriptor {
pub codec: String,
pub sample_rate: u32,
pub channels: u8,
pub bit_depth: u8,
}
impl AudioDescriptor {
#[must_use]
pub fn new(codec: String, sample_rate: u32, channels: u8, bit_depth: u8) -> Self {
Self {
codec,
sample_rate,
channels,
bit_depth,
}
}
#[must_use]
pub fn is_pcm(&self) -> bool {
self.codec.to_uppercase() == "PCM"
}
}
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct MediaDescriptor {
pub container: ContainerDef,
pub essence_length: u64,
}
impl MediaDescriptor {
#[must_use]
pub fn new(container: ContainerDef, essence_length: u64) -> Self {
Self {
container,
essence_length,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_container_mxf_extension() {
assert_eq!(ContainerDef::Mxf.extension(), "mxf");
}
#[test]
fn test_container_quicktime_extension() {
assert_eq!(ContainerDef::QuickTime.extension(), "mov");
}
#[test]
fn test_container_avid_extension() {
assert_eq!(ContainerDef::Avid.extension(), "omf");
}
#[test]
fn test_container_bwf_extension() {
assert_eq!(ContainerDef::Bwf.extension(), "bwf");
}
#[test]
fn test_container_wave_extension() {
assert_eq!(ContainerDef::Wave.extension(), "wav");
}
#[test]
fn test_container_is_mxf_true() {
assert!(ContainerDef::Mxf.is_mxf());
}
#[test]
fn test_container_is_mxf_false() {
assert!(!ContainerDef::QuickTime.is_mxf());
}
fn hd_video() -> VideoDescriptor {
VideoDescriptor::new("ProRes 422".into(), 1920, 1080, 25, 1, 8, "YCbCr".into())
}
fn uhd_video() -> VideoDescriptor {
VideoDescriptor::new("H.265".into(), 3840, 2160, 24, 1, 10, "YCbCr".into())
}
fn sd_video() -> VideoDescriptor {
VideoDescriptor::new("DV".into(), 720, 576, 25, 1, 8, "YCbCr".into())
}
#[test]
fn test_video_descriptor_frame_rate() {
let v = hd_video();
assert!((v.frame_rate() - 25.0).abs() < f64::EPSILON);
}
#[test]
fn test_video_descriptor_frame_rate_zero_den() {
let v = VideoDescriptor::new("X".into(), 1920, 1080, 25, 0, 8, "YCbCr".into());
assert_eq!(v.frame_rate(), 0.0);
}
#[test]
fn test_video_descriptor_is_hd_true() {
assert!(hd_video().is_hd());
}
#[test]
fn test_video_descriptor_is_hd_false_sd() {
assert!(!sd_video().is_hd());
}
#[test]
fn test_video_descriptor_is_hd_false_4k() {
assert!(!uhd_video().is_hd());
}
#[test]
fn test_video_descriptor_is_4k_true() {
assert!(uhd_video().is_4k());
}
#[test]
fn test_video_descriptor_is_4k_false() {
assert!(!hd_video().is_4k());
}
#[test]
fn test_audio_descriptor_is_pcm_true() {
let a = AudioDescriptor::new("PCM".into(), 48000, 2, 24);
assert!(a.is_pcm());
}
#[test]
fn test_audio_descriptor_is_pcm_case_insensitive() {
let a = AudioDescriptor::new("pcm".into(), 48000, 2, 24);
assert!(a.is_pcm());
}
#[test]
fn test_audio_descriptor_is_pcm_false() {
let a = AudioDescriptor::new("AAC".into(), 44100, 2, 16);
assert!(!a.is_pcm());
}
#[test]
fn test_media_descriptor_fields() {
let md = MediaDescriptor::new(ContainerDef::Mxf, 1_000_000);
assert!(md.container.is_mxf());
assert_eq!(md.essence_length, 1_000_000);
}
}