mirror of
https://github.com/alfg/mp4-rust.git
synced 2024-06-02 13:39:54 +00:00
3104a2d95b
* 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>
85 lines
2.2 KiB
Rust
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
|
|
))
|
|
}
|