diff --git a/examples/mp4info.rs b/examples/mp4info.rs index bd21737..65f3cda 100644 --- a/examples/mp4info.rs +++ b/examples/mp4info.rs @@ -1,8 +1,8 @@ extern crate mp4; +use mp4::TrackType; use std::env; use std::fs::File; -use mp4::{TrackType}; fn main() { let args: Vec = env::args().collect(); @@ -17,44 +17,71 @@ fn main() { // Print results. println!("File:"); - println!(" file size: {}", bmff.size); - println!(" brands: {:?} {:?}\n", bmff.ftyp.major_brand, bmff.ftyp.compatible_brands); + println!(" file size: {}", bmff.size); + println!( + " brands: {:?} {:?}\n", + bmff.ftyp.major_brand, bmff.ftyp.compatible_brands + ); println!("Movie:"); - println!(" duration: {:?}", moov.mvhd.duration); - println!(" timescale: {:?}\n", moov.mvhd.timescale); + println!(" version: {:?}", moov.mvhd.version); + println!( + " creation time: {}", + creation_time(moov.mvhd.creation_time) + ); + println!(" duration: {:?}", moov.mvhd.duration); + println!(" timescale: {:?}\n", moov.mvhd.timescale); println!("Found {} Tracks", moov.traks.len()); for trak in moov.traks.iter() { let tkhd = trak.tkhd.as_ref().unwrap(); - let mdia = trak.mdia.as_ref().unwrap(); - let hdlr = mdia.hdlr.as_ref().unwrap(); - let mdhd = mdia.mdhd.as_ref().unwrap(); - let stts= mdia.minf.as_ref().unwrap() - .stbl.as_ref().unwrap() - .stts.as_ref().unwrap(); - println!("Track: {:?}", tkhd.track_id); println!(" flags: {:?}", tkhd.flags); println!(" id: {:?}", tkhd.track_id); - println!(" type: {:?}", get_handler_type(hdlr.handler_type.value.as_ref())); println!(" duration: {:?}", tkhd.duration); - println!(" language: {:?}", mdhd.language_string); - - println!(" media:"); - println!(" sample count: {:?}", stts.sample_counts[0]); - println!(" timescale: {:?}", mdhd.timescale); - println!(" duration: {:?} (media timescale units)", mdhd.duration); - println!(" duration: {:?} (ms)", get_duration_ms(mdhd.duration, mdhd.timescale)); if tkhd.width != 0 && tkhd.height != 0 { println!(" width: {:?}", tkhd.width); println!(" height: {:?}", tkhd.height); } - if get_handler_type(hdlr.handler_type.value.as_ref()) == TrackType::Video { - println!(" frame rate: (computed): {:?}", get_framerate(&stts.sample_counts, mdhd.duration, mdhd.timescale)); + if let Some(ref mdia) = trak.mdia { + let hdlr = mdia.hdlr.as_ref().unwrap(); + let mdhd = mdia.mdhd.as_ref().unwrap(); + let stts = mdia + .minf + .as_ref() + .map(|m| m.stbl.as_ref().map(|s| s.stts.as_ref()).flatten()) + .flatten(); + + println!( + " type: {:?}", + get_handler_type(hdlr.handler_type.value.as_ref()) + ); + println!(" language: {:?}", mdhd.language_string); + + println!(" media:"); + if let Some(ref s) = stts { + println!(" sample count: {:?}", s.sample_counts[0]); + } + println!(" timescale: {:?}", mdhd.timescale); + println!( + " duration: {:?} (media timescale units)", + mdhd.duration + ); + println!( + " duration: {:?} (ms)", + get_duration_ms(mdhd.duration, mdhd.timescale) + ); + if get_handler_type(hdlr.handler_type.value.as_ref()) == TrackType::Video { + if let Some(ref s) = stts { + println!( + " frame rate: (computed): {:?}", + get_framerate(&s.sample_counts, mdhd.duration, mdhd.timescale) + ); + } + } } } - }, + } _ => { println!("Usage: mp4info "); } @@ -81,4 +108,13 @@ fn get_framerate(sample_counts: &Vec, duration: u32, timescale: u32) -> Str let sc = (sample_counts[0] as f64) * 1000.0; let ms = (duration as f64 / timescale as f64) * 1000.0; return format!("{:.2}", sc / ms.floor()); -} \ No newline at end of file +} + +fn creation_time(creation_time: u32) -> u32 { + // convert from MP4 epoch (1904-01-01) to Unix epoch (1970-01-01) + if creation_time >= 2082844800 { + creation_time - 2082844800 + } else { + creation_time + } +}