1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-06-02 13:39:54 +00:00

Make the example tolerant of videos missing parts

Some videos are missing certain parts that the example was assuming would be
present. This change makes all such access conditional on the parts being
present. Also added the display of the box version and the creation time in
a human-readable format. This serves to demonstrate the logic for converting
the MP4 epoch (1904-01-01) to Unix epoch (1970-01-01).
This commit is contained in:
Nathan Fiedler 2020-05-28 08:43:12 -07:00
parent e875c7da44
commit cad50c0c16
3 changed files with 141 additions and 24 deletions

75
Cargo.lock generated
View file

@ -1,16 +1,91 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "autocfg"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.71"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "mp4"
version = "0.4.0"
dependencies = [
"byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.42"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
"checksum chrono 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2"
"checksum libc 0.2.71 (registry+https://github.com/rust-lang/crates.io-index)" = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
"checksum num-integer 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba"
"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096"
"checksum time 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438"
"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

View file

@ -19,3 +19,6 @@ license = "MIT"
[dependencies]
byteorder = "1"
[dev-dependencies]
chrono = "0.4.11"

View file

@ -1,8 +1,9 @@
extern crate mp4;
use chrono::prelude::*;
use mp4::TrackType;
use std::env;
use std::fs::File;
use mp4::{TrackType};
fn main() {
let args: Vec<String> = env::args().collect();
@ -17,44 +18,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: {}",
format_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 <filename>");
}
@ -81,4 +109,15 @@ fn get_framerate(sample_counts: &Vec<u32>, 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());
}
}
fn format_creation_time(creation_time: u32) -> String {
// convert from MP4 epoch (1904-01-01) to Unix epoch (1970-01-01)
let time = if creation_time >= 2082844800 {
creation_time - 2082844800
} else {
creation_time
};
let dt = Utc.timestamp(time as i64, 0);
dt.format("%Y-%m-%d %H:%M:%S").to_string()
}