199 lines
7.1 KiB
Rust
199 lines
7.1 KiB
Rust
use log::info;
|
|
use mp4parse_capi::*;
|
|
use std::env;
|
|
use std::fs::File;
|
|
use std::io::Read;
|
|
|
|
extern "C" fn buf_read(buf: *mut u8, size: usize, userdata: *mut std::os::raw::c_void) -> isize {
|
|
let input: &mut std::fs::File = unsafe { &mut *(userdata as *mut _) };
|
|
let buf = unsafe { std::slice::from_raw_parts_mut(buf, size) };
|
|
match input.read(buf) {
|
|
Ok(n) => n as isize,
|
|
Err(_) => -1,
|
|
}
|
|
}
|
|
|
|
fn dump_avif(filename: &str, strictness: ParseStrictness) {
|
|
let mut file = File::open(filename).expect("Unknown file");
|
|
let io = Mp4parseIo {
|
|
read: Some(buf_read),
|
|
userdata: &mut file as *mut _ as *mut std::os::raw::c_void,
|
|
};
|
|
|
|
unsafe {
|
|
let mut parser = std::ptr::null_mut();
|
|
let rv = mp4parse_avif_new(&io, strictness, &mut parser);
|
|
println!("mp4parse_avif_new -> {rv:?}");
|
|
if rv == Mp4parseStatus::Ok {
|
|
println!(
|
|
"mp4parse_avif_get_image_safe -> {:?}",
|
|
mp4parse_avif_get_image_safe(&*parser)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
fn dump_file(filename: &str, strictness: ParseStrictness) {
|
|
let mut file = File::open(filename).expect("Unknown file");
|
|
let io = Mp4parseIo {
|
|
read: Some(buf_read),
|
|
userdata: &mut file as *mut _ as *mut std::os::raw::c_void,
|
|
};
|
|
|
|
unsafe {
|
|
let mut parser = std::ptr::null_mut();
|
|
let rv = mp4parse_new(&io, &mut parser);
|
|
|
|
match rv {
|
|
Mp4parseStatus::Ok => (),
|
|
Mp4parseStatus::Invalid => {
|
|
println!("-- failed to parse as mp4 video, trying AVIF");
|
|
dump_avif(filename, strictness);
|
|
}
|
|
_ => {
|
|
println!("-- fail to parse: {rv:?}, '-v' for more info");
|
|
return;
|
|
}
|
|
}
|
|
|
|
let mut frag_info = Mp4parseFragmentInfo::default();
|
|
match mp4parse_get_fragment_info(parser, &mut frag_info) {
|
|
Mp4parseStatus::Ok => {
|
|
println!("-- mp4parse_fragment_info {frag_info:?}");
|
|
}
|
|
rv => {
|
|
println!("-- mp4parse_fragment_info failed with {rv:?}");
|
|
return;
|
|
}
|
|
}
|
|
|
|
let mut counts: u32 = 0;
|
|
match mp4parse_get_track_count(parser, &mut counts) {
|
|
Mp4parseStatus::Ok => (),
|
|
_ => {
|
|
println!("-- mp4parse_get_track_count failed");
|
|
return;
|
|
}
|
|
}
|
|
|
|
for i in 0..counts {
|
|
let mut track_info = Mp4parseTrackInfo {
|
|
track_type: Mp4parseTrackType::Audio,
|
|
..Default::default()
|
|
};
|
|
match mp4parse_get_track_info(parser, i, &mut track_info) {
|
|
Mp4parseStatus::Ok => {
|
|
println!("-- mp4parse_get_track_info {track_info:?}");
|
|
}
|
|
_ => {
|
|
println!("-- mp4parse_get_track_info failed, track id: {i}");
|
|
return;
|
|
}
|
|
}
|
|
|
|
match track_info.track_type {
|
|
Mp4parseTrackType::Audio => {
|
|
let mut audio_info = Mp4parseTrackAudioInfo::default();
|
|
match mp4parse_get_track_audio_info(parser, i, &mut audio_info) {
|
|
Mp4parseStatus::Ok => {
|
|
println!("-- mp4parse_get_track_audio_info {audio_info:?}");
|
|
for i in 0..audio_info.sample_info_count as isize {
|
|
let sample_info = audio_info.sample_info.offset(i);
|
|
println!(
|
|
" -- mp4parse_get_track_audio_info sample_info[{:?}] {:?}",
|
|
i, *sample_info
|
|
);
|
|
}
|
|
}
|
|
_ => {
|
|
println!("-- mp4parse_get_track_audio_info failed, track id: {i}");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
Mp4parseTrackType::Video
|
|
| Mp4parseTrackType::Picture
|
|
| Mp4parseTrackType::AuxiliaryVideo => {
|
|
let mut video_info = Mp4parseTrackVideoInfo::default();
|
|
match mp4parse_get_track_video_info(parser, i, &mut video_info) {
|
|
Mp4parseStatus::Ok => {
|
|
println!("-- mp4parse_get_track_video_info {video_info:?}");
|
|
for i in 0..video_info.sample_info_count as isize {
|
|
let sample_info = video_info.sample_info.offset(i);
|
|
println!(
|
|
" -- mp4parse_get_track_video_info sample_info[{:?}] {:?}",
|
|
i, *sample_info
|
|
);
|
|
}
|
|
}
|
|
_ => {
|
|
println!("-- mp4parse_get_track_video_info failed, track id: {i}");
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
Mp4parseTrackType::Metadata => {
|
|
println!("TODO metadata track");
|
|
}
|
|
}
|
|
|
|
let mut indices = Mp4parseByteData::default();
|
|
match mp4parse_get_indice_table(parser, track_info.track_id, &mut indices) {
|
|
Mp4parseStatus::Ok => {
|
|
println!(
|
|
"-- mp4parse_get_indice_table track_id {} indices {:?}",
|
|
track_info.track_id, indices
|
|
);
|
|
}
|
|
_ => {
|
|
println!(
|
|
"-- mp4parse_get_indice_table failed, track_info.track_id: {}",
|
|
track_info.track_id
|
|
);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
mp4parse_free(parser);
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let mut dump_func: fn(&str, ParseStrictness) = dump_file;
|
|
let mut verbose = false;
|
|
let mut strictness = ParseStrictness::Normal;
|
|
let mut filenames = Vec::new();
|
|
for arg in env::args().skip(1) {
|
|
match arg.as_str() {
|
|
"--avif" => dump_func = dump_avif,
|
|
"--strict" => strictness = ParseStrictness::Strict,
|
|
"--permissive" => strictness = ParseStrictness::Permissive,
|
|
"-v" | "--verbose" => verbose = true,
|
|
_ => {
|
|
if let Some("-") = arg.get(0..1) {
|
|
eprintln!("Ignoring unknown switch {arg:?}");
|
|
} else {
|
|
filenames.push(arg)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if filenames.is_empty() {
|
|
eprintln!("No files to dump, exiting...");
|
|
return;
|
|
}
|
|
|
|
let env = env_logger::Env::default();
|
|
let mut logger = env_logger::Builder::from_env(env);
|
|
if verbose {
|
|
logger.filter(None, log::LevelFilter::Debug);
|
|
}
|
|
logger.init();
|
|
|
|
for filename in filenames {
|
|
info!("-- dump of '{}' --", filename);
|
|
dump_func(filename.as_str(), strictness);
|
|
info!("-- end of '{}' --", filename);
|
|
}
|
|
}
|