use libav_sys::ffi::{ avformat_open_input, AVFormatContext, avformat_network_init, av_strerror, avformat_find_stream_info, av_dump_format }; use std::{os::raw::c_char, error::Error}; fn main() -> Result<(), Box> { println!("Hello, world!"); // initialize and deinitialize libav let _guard = InitGuard::new(); let url = r#"file:C:/Users/lucac/downloads/BigBuckBunny.mp4"#; //let url = r#"http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4"#; let c_url = std::ffi::CString::new(url)?; let mut format_context_ptr: *mut AVFormatContext = std::ptr::null_mut(); handle_result(unsafe { avformat_open_input( &mut format_context_ptr, c_url.as_ptr(), std::ptr::null_mut(), std::ptr::null_mut() ) }, "avformat_open_input failed")?; println!("Input opened!"); println!("format_context_ptr: {:?}", format_context_ptr); handle_result(unsafe { avformat_find_stream_info( format_context_ptr, std::ptr::null_mut() ) }, "failed to find stream info")?; unsafe { av_dump_format( format_context_ptr, 0, c_url.as_ptr() as *const c_char, 0 ); } // Find the first video stream let video_stream_index = { let mut video_stream_index = -1; for i in 0..unsafe { (*format_context_ptr).nb_streams } { let stream = unsafe { *(*format_context_ptr).streams.offset(i as isize) }; if unsafe { (*(*stream).codecpar).codec_type } == libav_sys::ffi::AVMediaType_AVMEDIA_TYPE_VIDEO { video_stream_index = i as i32; break; } } video_stream_index }; if video_stream_index < 0 { return Err("Could not find a video stream".into()); } Ok(()) } struct InitGuard; impl InitGuard { fn new() -> Self { init(); InitGuard } } impl Drop for InitGuard { fn drop(&mut self) { deinit(); } } fn init() { // TODO ??? libav_sys::ffi::av_register_all(); let result = unsafe { avformat_network_init() }; if result != 0 { panic!("avformat_network_init failed"); } } fn deinit() { let result = unsafe { libav_sys::ffi::avformat_network_deinit() }; if result != 0 { panic!("avformat_network_deinit failed"); } } fn av_error_to_string(error_code: std::os::raw::c_int) -> String { // create a buffer for the error message let mut error_buffer: Vec = vec![0; 1024]; // get the error message let result = unsafe { av_strerror( error_code, error_buffer.as_mut_ptr(), error_buffer.len() ) }; if result != 0 { panic!("av_strerror failed"); } // convert to rust string error_buffer.iter().take_while(|c| **c != 0).map(|c| *c as u8 as char).collect() } fn handle_result(result: std::os::raw::c_int, error_message: &str) -> Result<(), Box> { if result < 0 { return Err(format!("{}: {}", error_message, av_error_to_string(result)).into()); } Ok(()) } fn tmp() { Drop }