ffmpeg_next/util/
interrupt.rs1use std::panic;
2use std::process;
3
4use crate::ffi::*;
5use libc::{c_int, c_void};
6
7pub struct Interrupt {
8 pub interrupt: AVIOInterruptCB,
9 pub guard: InterruptGuard,
10}
11
12pub struct InterruptGuard {
13 opaque: *mut c_void,
14 drop_fn: unsafe fn(*mut c_void),
15}
16
17unsafe impl Send for InterruptGuard {}
18unsafe impl Sync for InterruptGuard {}
19
20impl Drop for InterruptGuard {
21 fn drop(&mut self) {
22 if !self.opaque.is_null() {
23 unsafe { (self.drop_fn)(self.opaque) };
24 self.opaque = std::ptr::null_mut();
25 }
26 }
27}
28
29extern "C" fn callback<F>(opaque: *mut c_void) -> c_int
30where
31 F: FnMut() -> bool,
32{
33 #[allow(clippy::needless_borrow)]
35 match panic::catch_unwind(|| (unsafe { &mut *(opaque as *mut F) })()) {
36 Ok(ret) => ret as c_int,
37 Err(_) => process::abort(),
38 }
39}
40
41unsafe fn drop_box<F>(opaque: *mut c_void) {
42 unsafe {
43 drop(Box::from_raw(opaque as *mut F));
44 }
45}
46
47pub fn new<F>(opaque: Box<F>) -> Interrupt
48where
49 F: FnMut() -> bool + Send + 'static,
50{
51 let opaque = Box::into_raw(opaque) as *mut c_void;
52 let interrupt_cb = AVIOInterruptCB {
53 callback: Some(callback::<F>),
54 opaque,
55 };
56 Interrupt {
57 interrupt: interrupt_cb,
58 guard: InterruptGuard {
59 opaque,
60 drop_fn: drop_box::<F>,
61 },
62 }
63}