diff --git a/examples/mp4info.rs b/examples/mp4info.rs index ed070bc..cb9cb6e 100644 --- a/examples/mp4info.rs +++ b/examples/mp4info.rs @@ -2,6 +2,8 @@ extern crate mp4; use std::env; use std::fs::File; +use std::any::Any; +use mp4::{FourCC, TrackType}; fn main() { let args: Vec = env::args().collect(); @@ -11,14 +13,48 @@ fn main() { let filename = &args[1]; let f = File::open(filename).unwrap(); - let bmff = mp4::read_mp4(f); + let bmff = mp4::read_mp4(f).unwrap(); + let moov = bmff.moov.unwrap(); // Print results. - println!("{:?}", bmff.unwrap()); +// println!("{:?}", bmff.unwrap()); + println!("File:"); + 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!("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(); + + 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!(" width: {:?}", tkhd.width); + println!(" height: {:?}\n", tkhd.height); + } }, _ => { println!("Usage: mp4info "); } } +} +fn get_handler_type(handler: &str) -> TrackType { + let mut typ: TrackType = TrackType::Unknown; + match handler { + "vide" => typ = TrackType::Video, + "soun" => typ = TrackType::Audio, + "meta" => typ = TrackType::Unknown, + _ => (), + } + return typ; } \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 8397044..cf2d0ce 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,10 +16,19 @@ pub enum Error { } pub type Result = std::result::Result; +#[derive(Debug, PartialEq)] +pub enum TrackType { + Audio, + Video, + Metadata, + Unknown, +} + #[derive(Debug, Default)] pub struct BMFF { - ftyp: FtypBox, - moov: Option, + pub ftyp: FtypBox, + pub moov: Option, + pub size: u64, } impl BMFF { @@ -47,16 +56,16 @@ struct BoxHeader { } #[derive(Debug, Default)] -struct FtypBox { - major_brand: FourCC, - minor_version: u32, - compatible_brands: Vec, +pub struct FtypBox { + pub major_brand: FourCC, + pub minor_version: u32, + pub compatible_brands: Vec, } #[derive(Debug, Default)] -struct MoovBox { - mvhd: MvhdBox, - traks: Vec, +pub struct MoovBox { + pub mvhd: MvhdBox, + pub traks: Vec, } impl MoovBox { @@ -66,21 +75,21 @@ impl MoovBox { } #[derive(Debug, Default)] -struct MvhdBox { - version: u8, - flags: u32, - creation_time: u32, - modification_time: u32, - timescale: u32, - duration: u32, - rate: u32, +pub struct MvhdBox { + pub version: u8, + pub flags: u32, + pub creation_time: u32, + pub modification_time: u32, + pub timescale: u32, + pub duration: u32, + pub rate: u32, } #[derive(Debug, Default)] -struct TrakBox { - tkhd: Option, - edts: Option, - mdia: Option, +pub struct TrakBox { + pub tkhd: Option, + pub edts: Option, + pub mdia: Option, } impl TrakBox { @@ -90,23 +99,23 @@ impl TrakBox { } #[derive(Debug, Default)] -struct TkhdBox { - version: u8, - flags: u32, - creation_time: u32, - modification_time: u32, - track_id: u32, - duration: u64, - layer: u16, - alternate_group: u16, - volume: u16, - matrix: Matrix, - width: u32, - height: u32, +pub struct TkhdBox { + pub version: u8, + pub flags: u32, + pub creation_time: u32, + pub modification_time: u32, + pub track_id: u32, + pub duration: u64, + pub layer: u16, + pub alternate_group: u16, + pub volume: u16, + pub matrix: Matrix, + pub width: u32, + pub height: u32, } #[derive(Debug, Default)] -struct Matrix { +pub struct Matrix { a: i32, b: i32, u: i32, @@ -119,8 +128,8 @@ struct Matrix { } #[derive(Debug, Default)] -struct EdtsBox { - elst: Option, +pub struct EdtsBox { + pub elst: Option, } impl EdtsBox { @@ -130,10 +139,10 @@ impl EdtsBox { } #[derive(Debug, Default)] -struct ElstBox { - version: u32, - entry_count: u32, - entries: Vec, +pub struct ElstBox { + pub version: u32, + pub entry_count: u32, + pub entries: Vec, } impl ElstBox { @@ -143,17 +152,17 @@ impl ElstBox { } #[derive(Debug, Default)] -struct ElstEntry { - segment_duration: u32, - media_time: u32, - media_rate: u16, - media_rate_fraction: u16, +pub struct ElstEntry { + pub segment_duration: u32, + pub media_time: u32, + pub media_rate: u16, + pub media_rate_fraction: u16, } #[derive(Debug, Default)] -struct MdiaBox { - mdhd: Option, - hdlr: Option, +pub struct MdiaBox { + pub mdhd: Option, + pub hdlr: Option, } impl MdiaBox { @@ -163,15 +172,15 @@ impl MdiaBox { } #[derive(Debug, Default)] -struct MdhdBox { - version: u8, - flags: u32, - creation_time: u32, - modification_time: u32, - timescale: u32, - duration: u32, - language: u16, - language_string: String, +pub struct MdhdBox { + pub version: u8, + pub flags: u32, + pub creation_time: u32, + pub modification_time: u32, + pub timescale: u32, + pub duration: u32, + pub language: u16, + pub language_string: String, } impl MdhdBox { @@ -181,11 +190,11 @@ impl MdhdBox { } #[derive(Debug, Default)] -struct HdlrBox { - version: u8, - flags: u32, - handler_type: FourCC, - name: String, +pub struct HdlrBox { + pub version: u8, + pub flags: u32, + pub handler_type: FourCC, + pub name: String, } impl HdlrBox { @@ -238,6 +247,7 @@ fn read_boxes(f: File) -> Result { let filesize = f.metadata().unwrap().len(); let mut reader = BufReader::new(f); let mut bmff = BMFF::new(); + bmff.size = filesize; let mut start = 0u64; while start < filesize { @@ -313,8 +323,8 @@ fn read_box_header(reader: &mut BufReader, start: u64) -> Result, _offset: u64, size: u32) -> Result { - let major = f.read_u32::().unwrap(); - let minor = f.read_u32::().unwrap(); + let major = f.read_u32::().unwrap(); + let minor = f.read_u32::().unwrap(); if size % 4 != 0 { return Err(Error::InvalidData("invalid ftyp size")); } @@ -322,7 +332,7 @@ fn parse_ftyp_box(f: &mut BufReader, _offset: u64, size: u32) -> Result().unwrap(); + let b = f.read_u32::().unwrap(); brands.push(From::from(b)); } @@ -378,11 +388,11 @@ fn parse_mvhd_box(f: &mut BufReader, _offset: u64, size: u32) -> Result().unwrap(); - let modification_time = f.read_u32::().unwrap(); - let timescale = f.read_u32::().unwrap(); - let duration = f.read_u32::().unwrap(); - let rate = f.read_u32::().unwrap(); + let creation_time = f.read_u32::().unwrap(); + let modification_time = f.read_u32::().unwrap(); + let timescale = f.read_u32::().unwrap(); + let duration = f.read_u32::().unwrap(); + let rate = f.read_u32::().unwrap(); // Skip remaining bytes. let after = f.seek(SeekFrom::Current(0)).unwrap(); @@ -404,7 +414,7 @@ fn parse_trak_box(f: &mut BufReader, _offset: u64, size: u32) -> Result, _offset: u64, size: u32) -> Result().unwrap(); - let modification_time = f.read_u32::().unwrap(); - let track_id = f.read_u32::().unwrap(); - let duration = f.read_u64::().unwrap(); - f.read_u64::().unwrap(); // skip. - let layer = f.read_u16::().unwrap(); - let alternate_group = f.read_u16::().unwrap(); - let volume = f.read_u16::().unwrap() >> 8; + let creation_time = f.read_u32::().unwrap(); + let modification_time = f.read_u32::().unwrap(); + let track_id = f.read_u32::().unwrap(); + let duration = f.read_u64::().unwrap(); + f.read_u64::().unwrap(); // skip. + let layer = f.read_u16::().unwrap(); + let alternate_group = f.read_u16::().unwrap(); + let volume = f.read_u16::().unwrap() >> 8; f.read_u8().unwrap(); // skip. let matrix = Matrix{ a: f.read_i32::().unwrap(), - b: f.read_i32::().unwrap(), - u: f.read_i32::().unwrap(), - c: f.read_i32::().unwrap(), - d: f.read_i32::().unwrap(), - v: f.read_i32::().unwrap(), - x: f.read_i32::().unwrap(), - y: f.read_i32::().unwrap(), - w: f.read_i32::().unwrap(), + b: f.read_i32::().unwrap(), + u: f.read_i32::().unwrap(), + c: f.read_i32::().unwrap(), + d: f.read_i32::().unwrap(), + v: f.read_i32::().unwrap(), + x: f.read_i32::().unwrap(), + y: f.read_i32::().unwrap(), + w: f.read_i32::().unwrap(), }; - let width = f.read_u32::().unwrap() >> 8; - let height = f.read_u32::().unwrap() >> 8; + let width = f.read_u32::().unwrap() >> 8; + let height = f.read_u32::().unwrap() >> 8; // Skip remaining bytes. let after = f.seek(SeekFrom::Current(0)).unwrap(); @@ -502,7 +512,7 @@ fn parse_edts_box(f: &mut BufReader, _offset: u64, size: u32) -> Result, _offset: u64, size: u32) -> Result, _offset: u64, size: u32) -> Result { let current = f.seek(SeekFrom::Current(0)).unwrap(); // Current cursor position. - let version = f.read_u32::().unwrap(); - let entry_count = f.read_u32::().unwrap(); + let version = f.read_u32::().unwrap(); + let entry_count = f.read_u32::().unwrap(); let mut entries = Vec::new(); - for i in 0..entry_count { + for _i in 0..entry_count { let entry = ElstEntry{ - segment_duration: f.read_u32::().unwrap(), - media_time: f.read_u32::().unwrap(), - media_rate: f.read_u16::().unwrap(), - media_rate_fraction: f.read_u16::().unwrap(), + segment_duration: f.read_u32::().unwrap(), + media_time: f.read_u32::().unwrap(), + media_rate: f.read_u16::().unwrap(), + media_rate_fraction: f.read_u16::().unwrap(), }; entries.push(entry); } @@ -565,7 +575,7 @@ fn parse_mdia_box(f: &mut BufReader, _offset: u64, size: u32) -> Result, _offset: u64, size: u32) -> Result().unwrap(); - let modification_time = f.read_u32::().unwrap(); - let timescale = f.read_u32::().unwrap(); - let duration = f.read_u32::().unwrap(); - let language = f.read_u16::().unwrap(); + let creation_time = f.read_u32::().unwrap(); + let modification_time = f.read_u32::().unwrap(); + let timescale = f.read_u32::().unwrap(); + let duration = f.read_u32::().unwrap(); + let language = f.read_u16::().unwrap(); let language_string = get_language_string(language); // Skip remaining bytes. @@ -653,8 +663,8 @@ fn parse_hdlr_box(f: &mut BufReader, _offset: u64, size: u32) -> Result().unwrap(); // skip. - let handler = f.read_u32::().unwrap(); + f.read_u32::().unwrap(); // skip. + let handler = f.read_u32::().unwrap(); let n = f.seek(SeekFrom::Current(12)).unwrap(); // 12 bytes reserved. let buf_size = (size as u64 - (n - current)) - HEADER_SIZE as u64;