diff --git a/gstreamer-video/src/functions.rs b/gstreamer-video/src/functions.rs new file mode 100644 index 000000000..7bff9d539 --- /dev/null +++ b/gstreamer-video/src/functions.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use gst_ffi; +use glib_ffi; + +use gst; +use glib; +use glib::translate::{from_glib_full, from_glib_none, ToGlib, ToGlibPtr}; + +use std::ptr; +use std::mem; + +pub fn convert_sample( + sample: &gst::Sample, + caps: &gst::Caps, + timeout: gst::ClockTime, +) -> Result { + unsafe { + let mut error = ptr::null_mut(); + let ret = ffi::gst_video_convert_sample( + sample.to_glib_none().0, + caps.to_glib_none().0, + timeout.to_glib(), + &mut error, + ); + + if error.is_null() { + Ok(from_glib_full(ret)) + } else { + Err(from_glib_full(error)) + } + } +} + +pub fn convert_sample_async( + sample: &gst::Sample, + caps: &gst::Caps, + timeout: gst::ClockTime, + func: F, +) where + F: FnOnce(Result) + Send + 'static, +{ + unsafe extern "C" fn convert_sample_async_trampoline( + sample: *mut gst_ffi::GstSample, + error: *mut glib_ffi::GError, + user_data: glib_ffi::gpointer, + ) where + F: FnOnce(Result) + Send + 'static, + { + callback_guard!(); + let callback: &mut Option> = mem::transmute(user_data); + let callback = callback.take().unwrap(); + + if error.is_null() { + callback(Ok(from_glib_none(sample))) + } else { + callback(Err(from_glib_none(error))) + } + } + unsafe extern "C" fn convert_sample_async_free(user_data: glib_ffi::gpointer) + where + F: FnOnce(Result) + Send + 'static, + { + callback_guard!(); + let _: Box>> = Box::from_raw(user_data as *mut _); + } + + unsafe { + let user_data: Box>> = Box::new(Some(Box::new(func))); + + ffi::gst_video_convert_sample_async( + sample.to_glib_none().0, + caps.to_glib_none().0, + timeout.to_glib(), + Some(convert_sample_async_trampoline::), + Box::into_raw(user_data) as glib_ffi::gpointer, + Some(convert_sample_async_free::), + ); + } +} diff --git a/gstreamer-video/src/lib.rs b/gstreamer-video/src/lib.rs index f08cea771..ff33a6c47 100644 --- a/gstreamer-video/src/lib.rs +++ b/gstreamer-video/src/lib.rs @@ -31,6 +31,12 @@ macro_rules! skip_assert_initialized { ) } +macro_rules! callback_guard { + () => ( + let _guard = ::glib::CallbackGuard::new(); + ) +} + pub use glib::{Cast, Continue, Error, IsA, StaticType, ToValue, Type, TypedValue, Value}; #[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] @@ -52,6 +58,8 @@ mod video_overlay; pub use video_overlay::VideoOverlayExtManual; mod video_event; pub use video_event::*; +mod functions; +pub use functions::*; // Re-export all the traits in a prelude module, so that applications // can always "use gst::prelude::*" without getting conflicts