1
0
Fork 0
mirror of https://github.com/alfg/mp4-rust.git synced 2024-06-02 13:39:54 +00:00
mp4-rust/examples/mp4info.rs
Ian Jun 3104a2d95b
Feature/mp4copy (#14)
* Add ReadBox trait

* Add boxtype macro

* Remove offset in BoxHeader

* Fix parsing error when box has largesize

* Remove duplicated codes reading version and flags

* Add avc1 box

* Add mp4a box

* Add mp4a box

* Add DecoderSpecificDescriptor in esds box

* Add necessary sub-boxes to stbl box

* Improve ReadBox::read_box()

* Add smhd box

* Refactor BoxHeader

* Refactor BMFF

* Refactor

* Add some functions to get offset and size of sample

* Add Mp4Reader::read_sample() that read media samples

* Move Mp4Reader to reader.rs

* Add mandatory check when reading boxes

Add some methods to Mp4Reader, TrackReader
Format codes

* Update mp4info

* Refactor common types

* Add FixedPointX types

* Add media configuration, profile, ...

* Add initial Mp4Writer

* Run cargo fmt

* Add Mp4Writer and examples/mp4copy

* Add test codes for Avc1Box and Mp4aBox

* Remove prefix "get_" from method names

* Rename atoms to mp4box

* Fix some bugs

Co-authored-by: Byungwan Jun <unipro.kr@gmail.com>
2020-08-04 16:56:59 -07:00

85 lines
2.2 KiB
Rust

use std::env;
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::path::Path;
use mp4::{Mp4Track, Result, TrackType};
fn main() {
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
println!("Usage: mp4info <filename>");
std::process::exit(1);
}
if let Err(err) = info(&args[1]) {
let _ = writeln!(io::stderr(), "{}", err);
}
}
fn info<P: AsRef<Path>>(filename: &P) -> Result<()> {
let f = File::open(filename)?;
let size = f.metadata()?.len();
let reader = BufReader::new(f);
let mp4 = mp4::Mp4Reader::read_header(reader, size)?;
println!("Metadata:");
println!(" size : {}", mp4.size());
println!(" major_brand : {}", mp4.major_brand());
let mut compatible_brands = String::new();
for brand in mp4.compatible_brands().iter() {
compatible_brands.push_str(&brand.to_string());
compatible_brands.push_str(",");
}
println!(" compatible_brands: {}", compatible_brands);
println!(
"Duration: {}, timescale: {}",
mp4.duration(),
mp4.timescale()
);
for track in mp4.tracks().iter() {
let media_info = match track.track_type()? {
TrackType::Video => video_info(track)?,
TrackType::Audio => audio_info(track)?,
};
println!(
" Track: #{}({}) {}: {}",
track.track_id(),
track.language(),
track.track_type()?,
media_info
);
}
Ok(())
}
fn video_info(track: &Mp4Track) -> Result<String> {
Ok(format!(
"{} ({}) ({:?}), {}x{}, {} kb/s, {:.2} fps",
track.media_type()?,
track.video_profile()?,
track.box_type()?,
track.width(),
track.height(),
track.bitrate() / 1000,
track.frame_rate_f64()
))
}
fn audio_info(track: &Mp4Track) -> Result<String> {
Ok(format!(
"{} ({}) ({:?}), {} Hz, {}, {} kb/s",
track.media_type()?,
track.audio_profile()?,
track.box_type()?,
track.sample_freq_index()?.freq(),
track.channel_config()?,
track.bitrate() / 1000
))
}