From 991bbc24e89b03b3b6e897cfa89249d39a74429b Mon Sep 17 00:00:00 2001 From: Tadas Barzdzius Date: Mon, 3 Jul 2017 12:14:11 +0300 Subject: [PATCH] format: add interrupt callback support --- src/format/mod.rs | 25 +++++++++++++++++++++++-- src/util/interrupt.rs | 28 ++++++++++++++++++++++++++++ src/util/mod.rs | 1 + 3 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 src/util/interrupt.rs diff --git a/src/format/mod.rs b/src/format/mod.rs index 40ca382..72ca2a6 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -1,5 +1,6 @@ pub use ::util::format::{sample, Sample}; pub use ::util::format::{pixel, Pixel}; +use ::util::interrupt; pub mod stream; @@ -155,7 +156,7 @@ pub fn input>(path: &P) -> Result { } } -pub fn input_with>(path: &P, options: Dictionary) -> Result { +pub fn input_with_dictionary>(path: &P, options: Dictionary) -> Result { unsafe { let mut ps = ptr::null_mut(); let path = from_path(path); @@ -171,7 +172,27 @@ pub fn input_with>(path: &P, options: Dictionary) -> Result Err(Error::from(e)), } } - + + e => Err(Error::from(e)) + } + } +} + +pub fn input_with_interrupt, F>(path: &P, closure: F) -> Result + where F: FnMut() -> bool { + unsafe { + let mut ps = context::Input::wrap(avformat_alloc_context()); + let path = from_path(path); + (*ps.as_mut_ptr()).interrupt_callback = interrupt::new(Box::new(closure)).interrupt; + + match avformat_open_input(&mut ps.as_mut_ptr(), path.as_ptr(), ptr::null_mut(), ptr::null_mut()) { + 0 => { + match avformat_find_stream_info(ps.as_mut_ptr(), ptr::null_mut()) { + r if r >= 0 => Ok(ps), + e => Err(Error::from(e)), + } + } + e => Err(Error::from(e)) } } diff --git a/src/util/interrupt.rs b/src/util/interrupt.rs new file mode 100644 index 0000000..a417507 --- /dev/null +++ b/src/util/interrupt.rs @@ -0,0 +1,28 @@ +use std::panic; +use std::process; + +use ffi::*; +use libc::{c_void, c_int}; + +pub struct Interrupt { + pub interrupt: AVIOInterruptCB, +} + +extern "C" fn callback(opaque: *mut c_void) -> c_int + where F: FnMut() -> bool +{ + match panic::catch_unwind(|| (unsafe { &mut *(opaque as *mut F) })()) { + Ok(ret) => ret as c_int, + Err(_) => process::abort(), + } +} + +pub fn new(opaque: Box) -> Interrupt + where F: FnMut() -> bool +{ + let interrupt_cb = AVIOInterruptCB { + callback: Some(callback::), + opaque: Box::into_raw(opaque) as *mut c_void, + }; + Interrupt { interrupt: interrupt_cb } +} diff --git a/src/util/mod.rs b/src/util/mod.rs index 252f51f..09c841d 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -13,6 +13,7 @@ pub mod channel_layout; pub mod option; pub mod range; pub mod mathematics; +pub mod interrupt; use std::ffi::CStr; use std::str::from_utf8_unchecked;