From 2006bd51cc39bc0d0e4d9e8598f79a6104e03b43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 29 Mar 2020 22:40:22 +0300 Subject: [PATCH] gstreamer-base: Add pushsrc subclassing bindings Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/244 --- gstreamer-base/src/subclass/mod.rs | 2 + gstreamer-base/src/subclass/push_src.rs | 204 ++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 gstreamer-base/src/subclass/push_src.rs diff --git a/gstreamer-base/src/subclass/mod.rs b/gstreamer-base/src/subclass/mod.rs index 7654ba07b..37c765edf 100644 --- a/gstreamer-base/src/subclass/mod.rs +++ b/gstreamer-base/src/subclass/mod.rs @@ -12,6 +12,7 @@ pub mod base_parse; pub mod base_sink; pub mod base_src; pub mod base_transform; +pub mod push_src; pub use self::base_transform::BaseTransformMode; @@ -31,4 +32,5 @@ pub mod prelude { pub use super::base_transform::{ BaseTransformClassSubclassExt, BaseTransformImpl, BaseTransformImplExt, }; + pub use super::push_src::{PushSrcImpl, PushSrcImplExt}; } diff --git a/gstreamer-base/src/subclass/push_src.rs b/gstreamer-base/src/subclass/push_src.rs new file mode 100644 index 000000000..f12aade56 --- /dev/null +++ b/gstreamer-base/src/subclass/push_src.rs @@ -0,0 +1,204 @@ +// Copyright (C) 2020 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 gst_base_sys; +use gst_sys; + +use glib::translate::*; +use prelude::*; + +use glib::subclass::prelude::*; +use gst; +use gst::subclass::prelude::*; + +use std::ptr; + +use super::base_src::BaseSrcImpl; +use PushSrc; +use PushSrcClass; + +pub trait PushSrcImpl: PushSrcImplExt + BaseSrcImpl + Send + Sync + 'static { + fn fill( + &self, + element: &PushSrc, + buffer: &mut gst::BufferRef, + ) -> Result { + PushSrcImplExt::parent_fill(self, element, buffer) + } + + fn alloc(&self, element: &PushSrc) -> Result { + PushSrcImplExt::parent_alloc(self, element) + } + + fn create(&self, element: &PushSrc) -> Result { + PushSrcImplExt::parent_create(self, element) + } +} + +pub trait PushSrcImplExt { + fn parent_fill( + &self, + element: &PushSrc, + buffer: &mut gst::BufferRef, + ) -> Result; + + fn parent_alloc(&self, element: &PushSrc) -> Result; + + fn parent_create(&self, element: &PushSrc) -> Result; +} + +impl PushSrcImplExt for T { + fn parent_fill( + &self, + element: &PushSrc, + buffer: &mut gst::BufferRef, + ) -> Result { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_base_sys::GstPushSrcClass; + (*parent_class) + .fill + .map(|f| { + gst::FlowReturn::from_glib(f(element.to_glib_none().0, buffer.as_mut_ptr())) + }) + .unwrap_or(gst::FlowReturn::NotSupported) + .into_result() + } + } + + fn parent_alloc(&self, element: &PushSrc) -> Result { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_base_sys::GstPushSrcClass; + (*parent_class) + .alloc + .map(|f| { + let mut buffer_ptr: *mut gst_sys::GstBuffer = ptr::null_mut(); + + // FIXME: Wrong signature in -sys bindings + // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 + let buffer_ref = &mut buffer_ptr as *mut _ as *mut gst_sys::GstBuffer; + + let res = gst::FlowReturn::from_glib(f(element.to_glib_none().0, buffer_ref)); + res.into_result_value(|| from_glib_full(buffer_ref)) + }) + .unwrap_or(Err(gst::FlowError::NotSupported)) + } + } + + fn parent_create(&self, element: &PushSrc) -> Result { + unsafe { + let data = self.get_type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_base_sys::GstPushSrcClass; + (*parent_class) + .create + .map(|f| { + let mut buffer_ptr: *mut gst_sys::GstBuffer = ptr::null_mut(); + + // FIXME: Wrong signature in -sys bindings + // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 + let buffer_ref = &mut buffer_ptr as *mut _ as *mut gst_sys::GstBuffer; + + let res = gst::FlowReturn::from_glib(f(element.to_glib_none().0, buffer_ref)); + res.into_result_value(|| from_glib_full(buffer_ref)) + }) + .unwrap_or(Err(gst::FlowError::NotSupported)) + } + } +} + +unsafe impl IsSubclassable for PushSrcClass +where + ::Instance: PanicPoison, +{ + fn override_vfuncs(&mut self) { + <::BaseSrcClass as IsSubclassable>::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *mut Self as *mut gst_base_sys::GstPushSrcClass); + klass.fill = Some(push_src_fill::); + klass.alloc = Some(push_src_alloc::); + klass.create = Some(push_src_create::); + } + } +} + +unsafe extern "C" fn push_src_fill( + ptr: *mut gst_base_sys::GstPushSrc, + buffer: *mut gst_sys::GstBuffer, +) -> gst_sys::GstFlowReturn +where + T: PushSrcImpl, + T::Instance: PanicPoison, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: PushSrc = from_glib_borrow(ptr); + let buffer = gst::BufferRef::from_mut_ptr(buffer); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + PushSrcImpl::fill(imp, &wrap, buffer).into() + }) + .to_glib() +} + +unsafe extern "C" fn push_src_alloc( + ptr: *mut gst_base_sys::GstPushSrc, + buffer_ptr: *mut gst_sys::GstBuffer, +) -> gst_sys::GstFlowReturn +where + T: PushSrcImpl, + T::Instance: PanicPoison, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: PushSrc = from_glib_borrow(ptr); + // FIXME: Wrong signature in -sys bindings + // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 + let buffer_ptr = buffer_ptr as *mut *mut gst_sys::GstBuffer; + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + match PushSrcImpl::alloc(imp, &wrap) { + Ok(buffer) => { + *buffer_ptr = buffer.into_ptr(); + gst::FlowReturn::Ok + } + Err(err) => gst::FlowReturn::from(err), + } + }) + .to_glib() +} + +unsafe extern "C" fn push_src_create( + ptr: *mut gst_base_sys::GstPushSrc, + buffer_ptr: *mut gst_sys::GstBuffer, +) -> gst_sys::GstFlowReturn +where + T: PushSrcImpl, + T::Instance: PanicPoison, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: PushSrc = from_glib_borrow(ptr); + // FIXME: Wrong signature in -sys bindings + // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs-sys/issues/3 + let buffer_ptr = buffer_ptr as *mut *mut gst_sys::GstBuffer; + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + match PushSrcImpl::create(imp, &wrap) { + Ok(buffer) => { + *buffer_ptr = buffer.into_ptr(); + gst::FlowReturn::Ok + } + Err(err) => gst::FlowReturn::from(err), + } + }) + .to_glib() +}