mirror of
https://github.com/alfg/mp4-rust.git
synced 2024-12-22 12:06:33 +00:00
5d648f1a72
* fix clippy::unused_io_amount See related clippy documentation, but in short some partial reads can occur in particular with io on the networl. read_exact/write_all transparently handle such errors. The fix actually revealed a bug in 'mp4a' atom parsing, but this is a dangerous change: Parsing bugs that were transparently ignored are now failing with error (unattended io eof). * fix trivial clippy errors * fix clippy error with always 0 value * run ci/cd with clippy and latest rust version
142 lines
3.7 KiB
Rust
142 lines
3.7 KiB
Rust
use std::env;
|
|
use std::fs::File;
|
|
use std::io::prelude::*;
|
|
use std::io::{self, BufReader};
|
|
use std::path::Path;
|
|
|
|
use mp4::{Mp4Box, Result};
|
|
|
|
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)?;
|
|
let boxes = get_boxes(f)?;
|
|
|
|
// print out boxes
|
|
for b in boxes.iter() {
|
|
println!("[{}] size={} {}", b.name, b.size, b.summary);
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Default)]
|
|
pub struct Box {
|
|
name: String,
|
|
size: u64,
|
|
summary: String,
|
|
indent: u32,
|
|
}
|
|
|
|
fn get_boxes(file: File) -> Result<Vec<Box>> {
|
|
let size = file.metadata()?.len();
|
|
let reader = BufReader::new(file);
|
|
let mp4 = mp4::Mp4Reader::read_header(reader, size)?;
|
|
|
|
// collect known boxes
|
|
let mut boxes = vec![
|
|
build_box(&mp4.ftyp),
|
|
build_box(&mp4.moov),
|
|
build_box(&mp4.moov.mvhd),
|
|
];
|
|
|
|
if let Some(ref mvex) = &mp4.moov.mvex {
|
|
boxes.push(build_box(mvex));
|
|
if let Some(mehd) = &mvex.mehd {
|
|
boxes.push(build_box(mehd));
|
|
}
|
|
boxes.push(build_box(&mvex.trex));
|
|
}
|
|
|
|
// trak.
|
|
for track in mp4.tracks().values() {
|
|
boxes.push(build_box(&track.trak));
|
|
boxes.push(build_box(&track.trak.tkhd));
|
|
if let Some(ref edts) = track.trak.edts {
|
|
boxes.push(build_box(edts));
|
|
if let Some(ref elst) = edts.elst {
|
|
boxes.push(build_box(elst));
|
|
}
|
|
}
|
|
|
|
// 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));
|
|
|
|
// trak.mdia.minf
|
|
let minf = &track.trak.mdia.minf;
|
|
if let Some(ref vmhd) = &minf.vmhd {
|
|
boxes.push(build_box(vmhd));
|
|
}
|
|
if let Some(ref smhd) = &minf.smhd {
|
|
boxes.push(build_box(smhd));
|
|
}
|
|
|
|
// trak.mdia.minf.stbl
|
|
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));
|
|
}
|
|
if let Some(ref hev1) = &stbl.stsd.hev1 {
|
|
boxes.push(build_box(hev1));
|
|
}
|
|
if let Some(ref mp4a) = &stbl.stsd.mp4a {
|
|
boxes.push(build_box(mp4a));
|
|
}
|
|
boxes.push(build_box(&stbl.stts));
|
|
if let Some(ref ctts) = &stbl.ctts {
|
|
boxes.push(build_box(ctts));
|
|
}
|
|
if let Some(ref stss) = &stbl.stss {
|
|
boxes.push(build_box(stss));
|
|
}
|
|
boxes.push(build_box(&stbl.stsc));
|
|
boxes.push(build_box(&stbl.stsz));
|
|
if let Some(ref stco) = &stbl.stco {
|
|
boxes.push(build_box(stco));
|
|
}
|
|
if let Some(ref co64) = &stbl.co64 {
|
|
boxes.push(build_box(co64));
|
|
}
|
|
}
|
|
|
|
// 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));
|
|
if let Some(ref trun) = &traf.trun {
|
|
boxes.push(build_box(trun));
|
|
}
|
|
}
|
|
}
|
|
|
|
Ok(boxes)
|
|
}
|
|
|
|
fn build_box<M: Mp4Box + std::fmt::Debug>(m: &M) -> Box {
|
|
Box {
|
|
name: m.box_type().to_string(),
|
|
size: m.box_size(),
|
|
summary: m.summary().unwrap(),
|
|
indent: 0,
|
|
}
|
|
}
|