2020-08-24 05:11:59 +00:00
|
|
|
use std::env;
|
|
|
|
use std::fs::File;
|
|
|
|
use std::io::prelude::*;
|
|
|
|
use std::io::{self, BufReader};
|
|
|
|
use std::path::Path;
|
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
use mp4::{Result, Mp4Box};
|
2020-08-24 05:11:59 +00:00
|
|
|
|
|
|
|
fn main() {
|
|
|
|
let args: Vec<String> = env::args().collect();
|
|
|
|
|
|
|
|
if args.len() < 2 {
|
|
|
|
println!("Usage: mp4dump <filename>");
|
|
|
|
std::process::exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Err(err) = dump(&args[1]) {
|
|
|
|
let _ = writeln!(io::stderr(), "{}", err);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn dump<P: AsRef<Path>>(filename: &P) -> Result<()> {
|
|
|
|
let f = File::open(filename)?;
|
2020-08-25 04:49:58 +00:00
|
|
|
let boxes = get_boxes(f)?;
|
2020-08-24 05:11:59 +00:00
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
// print out boxes
|
|
|
|
for b in boxes.iter() {
|
2020-09-09 05:24:34 +00:00
|
|
|
println!("[{}] size={} {}", b.name, b.size, b.summary);
|
2020-08-25 04:49:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
|
|
|
pub struct Box {
|
|
|
|
name: String,
|
|
|
|
size: u64,
|
2020-09-09 05:24:34 +00:00
|
|
|
summary: String,
|
2020-08-25 04:49:58 +00:00
|
|
|
indent: u32,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn get_boxes(file: File) -> Result<Vec<Box>> {
|
|
|
|
let size = file.metadata()?.len();
|
|
|
|
let reader = BufReader::new(file);
|
2020-08-24 05:11:59 +00:00
|
|
|
let mp4 = mp4::Mp4Reader::read_header(reader, size)?;
|
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
// collect known boxes
|
|
|
|
let mut boxes = Vec::new();
|
2020-08-24 05:11:59 +00:00
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
// ftyp, moov, mvhd
|
|
|
|
boxes.push(build_box(&mp4.ftyp));
|
|
|
|
boxes.push(build_box(&mp4.moov));
|
|
|
|
boxes.push(build_box(&mp4.moov.mvhd));
|
2020-08-24 05:11:59 +00:00
|
|
|
|
2020-09-15 01:05:34 +00:00
|
|
|
if let Some(ref mvex) = &mp4.moov.mvex {
|
|
|
|
boxes.push(build_box(mvex));
|
2021-01-27 03:31:32 +00:00
|
|
|
if let Some(mehd) = &mvex.mehd {
|
|
|
|
boxes.push(build_box(mehd));
|
|
|
|
}
|
2020-09-15 01:05:34 +00:00
|
|
|
boxes.push(build_box(&mvex.trex));
|
|
|
|
}
|
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
// trak.
|
2021-07-30 02:57:15 +00:00
|
|
|
for track in mp4.tracks().values() {
|
2020-08-25 04:49:58 +00:00
|
|
|
boxes.push(build_box(&track.trak));
|
|
|
|
boxes.push(build_box(&track.trak.tkhd));
|
2020-08-24 05:11:59 +00:00
|
|
|
if let Some(ref edts) = track.trak.edts {
|
2020-08-25 04:49:58 +00:00
|
|
|
boxes.push(build_box(edts));
|
2020-08-24 05:11:59 +00:00
|
|
|
if let Some(ref elst) = edts.elst {
|
2020-08-25 04:49:58 +00:00
|
|
|
boxes.push(build_box(elst));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
// trak.mdia
|
|
|
|
let mdia = &track.trak.mdia;
|
|
|
|
boxes.push(build_box(mdia));
|
|
|
|
boxes.push(build_box(&mdia.mdhd));
|
|
|
|
boxes.push(build_box(&mdia.hdlr));
|
|
|
|
boxes.push(build_box(&track.trak.mdia.minf));
|
2020-08-24 05:11:59 +00:00
|
|
|
|
|
|
|
// trak.mdia.minf
|
2020-08-25 04:49:58 +00:00
|
|
|
let minf = &track.trak.mdia.minf;
|
|
|
|
if let Some(ref vmhd) = &minf.vmhd {
|
|
|
|
boxes.push(build_box(vmhd));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
2020-08-25 04:49:58 +00:00
|
|
|
if let Some(ref smhd) = &minf.smhd {
|
|
|
|
boxes.push(build_box(smhd));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// trak.mdia.minf.stbl
|
2020-08-25 04:49:58 +00:00
|
|
|
let stbl = &track.trak.mdia.minf.stbl;
|
|
|
|
boxes.push(build_box(stbl));
|
|
|
|
boxes.push(build_box(&stbl.stsd));
|
|
|
|
if let Some(ref avc1) = &stbl.stsd.avc1 {
|
|
|
|
boxes.push(build_box(avc1));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
2020-09-02 03:49:55 +00:00
|
|
|
if let Some(ref hev1) = &stbl.stsd.hev1 {
|
|
|
|
boxes.push(build_box(hev1));
|
|
|
|
}
|
2020-08-25 04:49:58 +00:00
|
|
|
if let Some(ref mp4a) = &stbl.stsd.mp4a {
|
|
|
|
boxes.push(build_box(mp4a));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
2020-08-25 04:49:58 +00:00
|
|
|
boxes.push(build_box(&stbl.stts));
|
|
|
|
if let Some(ref ctts) = &stbl.ctts {
|
|
|
|
boxes.push(build_box(ctts));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
2020-08-25 04:49:58 +00:00
|
|
|
if let Some(ref stss) = &stbl.stss {
|
|
|
|
boxes.push(build_box(stss));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
2020-08-25 04:49:58 +00:00
|
|
|
boxes.push(build_box(&stbl.stsc));
|
|
|
|
boxes.push(build_box(&stbl.stsz));
|
|
|
|
if let Some(ref stco) = &stbl.stco {
|
|
|
|
boxes.push(build_box(stco));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
2020-08-25 04:49:58 +00:00
|
|
|
if let Some(ref co64) = &stbl.co64 {
|
|
|
|
boxes.push(build_box(co64));
|
2020-08-24 05:11:59 +00:00
|
|
|
}
|
|
|
|
}
|
2020-09-04 04:33:45 +00:00
|
|
|
|
|
|
|
// If fragmented, add moof boxes.
|
|
|
|
for moof in mp4.moofs.iter() {
|
|
|
|
boxes.push(build_box(moof));
|
|
|
|
boxes.push(build_box(&moof.mfhd));
|
|
|
|
for traf in moof.trafs.iter() {
|
|
|
|
boxes.push(build_box(traf));
|
|
|
|
boxes.push(build_box(&traf.tfhd));
|
2020-09-15 01:05:34 +00:00
|
|
|
if let Some(ref trun) = &traf.trun {
|
|
|
|
boxes.push(build_box(trun));
|
|
|
|
}
|
2020-09-04 04:33:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
Ok(boxes)
|
|
|
|
}
|
2020-08-24 05:11:59 +00:00
|
|
|
|
2020-08-25 04:49:58 +00:00
|
|
|
fn build_box<M: Mp4Box + std::fmt::Debug>(ref m: &M) -> Box {
|
|
|
|
return Box{
|
|
|
|
name: m.box_type().to_string(),
|
|
|
|
size: m.box_size(),
|
2020-09-09 05:24:34 +00:00
|
|
|
summary: m.summary().unwrap(),
|
2020-08-25 04:49:58 +00:00
|
|
|
indent: 0,
|
|
|
|
};
|
2020-09-09 05:24:34 +00:00
|
|
|
}
|