diff --git a/Cargo.lock b/Cargo.lock index d013301..1b9b278 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,6 +1,16 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "byteorder" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "mp4" version = "0.1.0" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] +[metadata] +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" diff --git a/Cargo.toml b/Cargo.toml index 799be7e..140d83c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,3 +7,4 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +byteorder = "1" diff --git a/src/main.rs b/src/main.rs index f563f66..f625d9f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ use std::io::prelude::*; use std::io::{BufReader, Read, SeekFrom}; use std::fs::File; +use std::fmt; use std::convert::TryInto; +use byteorder::{BigEndian, ReadBytesExt}; #[derive(Debug)] struct Box { @@ -10,13 +12,51 @@ struct Box { offset: u32, } +#[derive(Debug)] +struct FtypBox { + major_brand: FourCC, + minor_version: u32, + compatible_brands: Vec, +} + +#[derive(Default, PartialEq, Clone)] +pub struct FourCC { + pub value: String +} + +impl From for FourCC { + fn from(number: u32) -> FourCC { + let mut box_chars = Vec::new(); + for x in 0..4 { + let c = (number >> (x * 8) & 0x0000_00FF) as u8; + box_chars.push(c); + } + box_chars.reverse(); + + let box_string = match String::from_utf8(box_chars) { + Ok(t) => t, + _ => String::from("null"), // error to retrieve fourcc + }; + + FourCC { + value: box_string + } + } +} + +impl fmt::Debug for FourCC { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.value) + } +} + fn main() -> std::io::Result<()> { // Using BufReader. let f = File::open("tears-of-steel-2s.mp4")?; let filesize = f.metadata().unwrap().len(); let mut reader = BufReader::new(f); - let mut v = Vec::new(); + let mut boxes = Vec::new(); let mut offset = 0u64; while offset < filesize { @@ -42,13 +82,19 @@ fn main() -> std::io::Result<()> { Err(e) => panic!("Invalid UTF-8 sequence: {}", e), }; + match typ.as_ref() { + "ftyp" => parse_ftyp_box(&mut reader, 0, size), + _ => (), + }; + + // Make Box struct and add to vector. let b = Box{ - name: typ.try_into().expect("asdf"), + name: typ.try_into().unwrap(), size: size, offset: offset as u32, }; - v.push(b); + boxes.push(b); // This will find all boxes, including nested boxes. // let mut offset = match size { @@ -62,11 +108,41 @@ fn main() -> std::io::Result<()> { } // Print results. - for a in v { - println!("{:?}", a); + for b in boxes { + println!("{:?}", b); + } // Done. println!("done"); Ok(()) -} \ No newline at end of file +} + +fn parse_ftyp_box(f: &mut BufReader, offset: u64, size: u32) { + println!("found ftyp"); + + let major = f.read_u32::().unwrap(); + let minor = f.read_u32::().unwrap(); + let brand_count = (size - 16) / 4; // header + major + minor + + println!("{}", brand_count); + + let mut brands = Vec::new(); + for _ in 0..brand_count { + let b = f.read_u32::().unwrap(); + brands.push(From::from(b)); + } + + let ftyp = FtypBox { + major_brand: From::from(major), + minor_version: minor, + compatible_brands: brands, + }; + println!("{:?}", ftyp); + + println!("end ftyp"); + // Ok(FtypBox { + // major_brand: major, + // minor_version: minor, + // }) +}