From 411319198a178cf984169efc387e8ce453f77b36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 20 Nov 2018 23:40:39 +0200 Subject: [PATCH] Port BaseTransform subclassing --- Gir_GstBase.toml | 6 +- gstreamer-base/src/auto/base_transform.rs | 3 +- gstreamer-base/src/base_transform.rs | 27 +- gstreamer-base/src/lib.rs | 1 + gstreamer-base/src/subclass/base_transform.rs | 636 ++++++++++++++++++ gstreamer-base/src/subclass/mod.rs | 4 + 6 files changed, 674 insertions(+), 3 deletions(-) create mode 100644 gstreamer-base/src/subclass/base_transform.rs diff --git a/Gir_GstBase.toml b/Gir_GstBase.toml index c76420714..551212336 100644 --- a/Gir_GstBase.toml +++ b/Gir_GstBase.toml @@ -16,7 +16,6 @@ external_libraries = [ ] generate = [ - "GstBase.BaseTransform", "GstBase.PushSrc", ] @@ -87,6 +86,11 @@ status = "generate" # Pass by value, to be added manually ignore = true +[[object]] +name = "GstBase.BaseTransform" +subclassing = true +status = "generate" + [[object]] name = "GstBase.Aggregator" status = "generate" diff --git a/gstreamer-base/src/auto/base_transform.rs b/gstreamer-base/src/auto/base_transform.rs index ba8397382..775c55f6d 100644 --- a/gstreamer-base/src/auto/base_transform.rs +++ b/gstreamer-base/src/auto/base_transform.rs @@ -2,6 +2,7 @@ // from gir-files (https://github.com/gtk-rs/gir-files) // DO NOT EDIT +use BaseTransformClass; use ffi; use glib; use glib::StaticType; @@ -21,7 +22,7 @@ use std::mem::transmute; use std::ptr; glib_wrapper! { - pub struct BaseTransform(Object): [ + pub struct BaseTransform(Object): [ gst::Element => gst_ffi::GstElement, gst::Object => gst_ffi::GstObject, ]; diff --git a/gstreamer-base/src/base_transform.rs b/gstreamer-base/src/base_transform.rs index 04fb6e0dc..6254893e9 100644 --- a/gstreamer-base/src/base_transform.rs +++ b/gstreamer-base/src/base_transform.rs @@ -8,8 +8,9 @@ use ffi; use glib::translate::*; -use glib::IsA; +use glib::{IsA, IsClassFor}; use gst; +use std::ops; use BaseTransform; pub trait BaseTransformExtManual { @@ -26,3 +27,27 @@ impl> BaseTransformExtManual for O { } } } + +#[repr(C)] +pub struct BaseTransformClass(ffi::GstBaseTransformClass); + +unsafe impl IsClassFor for BaseTransformClass { + type Instance = BaseTransform; +} + +unsafe impl Send for BaseTransformClass {} +unsafe impl Sync for BaseTransformClass {} + +impl ops::Deref for BaseTransformClass { + type Target = gst::ElementClass; + + fn deref(&self) -> &Self::Target { + self.upcast_ref() + } +} + +impl ops::DerefMut for BaseTransformClass { + fn deref_mut(&mut self) -> &mut Self::Target { + self.upcast_ref_mut() + } +} diff --git a/gstreamer-base/src/lib.rs b/gstreamer-base/src/lib.rs index 871c28587..549f88173 100644 --- a/gstreamer-base/src/lib.rs +++ b/gstreamer-base/src/lib.rs @@ -50,6 +50,7 @@ pub use base_sink::BaseSinkClass; mod base_src; pub use base_src::BaseSrcClass; mod base_transform; +pub use base_transform::BaseTransformClass; // Re-export all the traits in a prelude module, so that applications // can always "use gst::prelude::*" without getting conflicts diff --git a/gstreamer-base/src/subclass/base_transform.rs b/gstreamer-base/src/subclass/base_transform.rs new file mode 100644 index 000000000..45454c7cd --- /dev/null +++ b/gstreamer-base/src/subclass/base_transform.rs @@ -0,0 +1,636 @@ +// Copyright (C) 2017,2018 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 glib_ffi; +use gst_ffi; + +use glib::translate::*; +use prelude::*; + +use glib::subclass::prelude::*; +use gst; +use gst::subclass::prelude::*; + +use BaseTransform; +use BaseTransformClass; + +pub trait BaseTransformImpl: ElementImpl + Send + Sync + 'static { + fn start(&self, _element: &BaseTransform) -> bool { + true + } + + fn stop(&self, _element: &BaseTransform) -> bool { + true + } + + fn transform_caps( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + filter: Option<&gst::Caps>, + ) -> gst::Caps { + self.parent_transform_caps(element, direction, caps, filter) + } + + fn fixate_caps( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + othercaps: gst::Caps, + ) -> gst::Caps { + self.parent_fixate_caps(element, direction, caps, othercaps) + } + + fn set_caps( + &self, + _element: &BaseTransform, + _incaps: &gst::Caps, + _outcaps: &gst::Caps, + ) -> bool { + true + } + + fn accept_caps( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + ) -> bool { + self.parent_accept_caps(element, direction, caps) + } + + fn query( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + query: &mut gst::QueryRef, + ) -> bool { + BaseTransformImpl::parent_query(self, element, direction, query) + } + + fn transform_size( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + size: usize, + othercaps: &gst::Caps, + ) -> Option { + self.parent_transform_size(element, direction, caps, size, othercaps) + } + + fn get_unit_size(&self, _element: &BaseTransform, _caps: &gst::Caps) -> Option { + unimplemented!(); + } + + fn sink_event(&self, element: &BaseTransform, event: gst::Event) -> bool { + self.parent_sink_event(element, event) + } + + fn src_event(&self, element: &BaseTransform, event: gst::Event) -> bool { + self.parent_src_event(element, event) + } + + fn transform( + &self, + _element: &BaseTransform, + _inbuf: &gst::Buffer, + _outbuf: &mut gst::BufferRef, + ) -> gst::FlowReturn { + unimplemented!(); + } + + fn transform_ip(&self, _element: &BaseTransform, _buf: &mut gst::BufferRef) -> gst::FlowReturn { + unimplemented!(); + } + + fn transform_ip_passthrough( + &self, + _element: &BaseTransform, + _buf: &gst::BufferRef, + ) -> gst::FlowReturn { + unimplemented!(); + } + + fn parent_transform_caps( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + filter: Option<&gst::Caps>, + ) -> gst::Caps { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + match (*parent_class).transform_caps { + Some(f) => from_glib_full(f( + element.to_glib_none().0, + direction.to_glib(), + caps.to_glib_none().0, + filter.to_glib_none().0, + )), + None => caps.clone(), + } + } + } + + fn parent_fixate_caps( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + othercaps: gst::Caps, + ) -> gst::Caps { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + match (*parent_class).fixate_caps { + Some(f) => from_glib_full(f( + element.to_glib_none().0, + direction.to_glib(), + caps.to_glib_none().0, + othercaps.into_ptr(), + )), + None => othercaps, + } + } + } + + fn parent_accept_caps( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + ) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + (*parent_class) + .accept_caps + .map(|f| { + from_glib(f( + element.to_glib_none().0, + direction.to_glib(), + caps.to_glib_none().0, + )) + }) + .unwrap_or(false) + } + } + + fn parent_query( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + query: &mut gst::QueryRef, + ) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + (*parent_class) + .query + .map(|f| { + from_glib(f( + element.to_glib_none().0, + direction.to_glib(), + query.as_mut_ptr(), + )) + }) + .unwrap_or(false) + } + } + + fn parent_transform_size( + &self, + element: &BaseTransform, + direction: gst::PadDirection, + caps: &gst::Caps, + size: usize, + othercaps: &gst::Caps, + ) -> Option { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + (*parent_class) + .transform_size + .map(|f| { + let mut othersize = 0; + let res: bool = from_glib(f( + element.to_glib_none().0, + direction.to_glib(), + caps.to_glib_none().0, + size, + othercaps.to_glib_none().0, + &mut othersize, + )); + if res { + Some(othersize) + } else { + None + } + }) + .unwrap_or(None) + } + } + + fn parent_sink_event(&self, element: &BaseTransform, event: gst::Event) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + (*parent_class) + .sink_event + .map(|f| from_glib(f(element.to_glib_none().0, event.into_ptr()))) + .unwrap_or(false) + } + } + + fn parent_src_event(&self, element: &BaseTransform, event: gst::Event) -> bool { + unsafe { + let data = self.get_type_data(); + let parent_class = data.as_ref().get_parent_class() as *mut ffi::GstBaseTransformClass; + (*parent_class) + .src_event + .map(|f| from_glib(f(element.to_glib_none().0, event.into_ptr()))) + .unwrap_or(false) + } + } +} + +#[derive(Copy, Clone, Debug, PartialEq, Eq)] +pub enum BaseTransformMode { + AlwaysInPlace, + NeverInPlace, + Both, +} + +unsafe impl IsSubclassable for BaseTransformClass +where + ::Instance: PanicPoison, +{ + fn override_vfuncs(&mut self) { + >::override_vfuncs(self); + unsafe { + let klass = &mut *(self as *const Self as *mut ffi::GstBaseTransformClass); + klass.start = Some(base_transform_start::); + klass.stop = Some(base_transform_stop::); + klass.transform_caps = Some(base_transform_transform_caps::); + klass.fixate_caps = Some(base_transform_fixate_caps::); + klass.set_caps = Some(base_transform_set_caps::); + klass.accept_caps = Some(base_transform_accept_caps::); + klass.query = Some(base_transform_query::); + klass.transform_size = Some(base_transform_transform_size::); + klass.get_unit_size = Some(base_transform_get_unit_size::); + klass.sink_event = Some(base_transform_sink_event::); + klass.src_event = Some(base_transform_src_event::); + } + } +} + +pub unsafe trait BaseTransformClassSubclassExt: Sized + 'static { + fn configure( + &mut self, + mode: BaseTransformMode, + passthrough_on_same_caps: bool, + transform_ip_on_passthrough: bool, + ) where + Self: ClassStruct, + ::Instance: PanicPoison, + { + unsafe { + let klass = &mut *(self as *const Self as *mut ffi::GstBaseTransformClass); + + klass.passthrough_on_same_caps = passthrough_on_same_caps.to_glib(); + klass.transform_ip_on_passthrough = transform_ip_on_passthrough.to_glib(); + + match mode { + BaseTransformMode::AlwaysInPlace => { + klass.transform_ip = Some(base_transform_transform_ip::); + } + BaseTransformMode::NeverInPlace => { + klass.transform = Some(base_transform_transform::); + } + BaseTransformMode::Both => { + klass.transform = Some(base_transform_transform::); + klass.transform_ip = Some(base_transform_transform_ip::); + } + } + } + } +} + +unsafe impl BaseTransformClassSubclassExt for T +where + T::Type: ObjectSubclass + BaseTransformImpl, + ::Instance: PanicPoison, +{ +} + +unsafe extern "C" fn base_transform_start( + ptr: *mut ffi::GstBaseTransform, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.start(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_transform_stop( + ptr: *mut ffi::GstBaseTransform, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.stop(&wrap) }).to_glib() +} + +unsafe extern "C" fn base_transform_transform_caps( + ptr: *mut ffi::GstBaseTransform, + direction: gst_ffi::GstPadDirection, + caps: *mut gst_ffi::GstCaps, + filter: *mut gst_ffi::GstCaps, +) -> *mut gst_ffi::GstCaps +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::Caps::new_empty(), { + let filter = if filter.is_null() { + None + } else { + Some(from_glib_borrow(filter)) + }; + + imp.transform_caps( + &wrap, + from_glib(direction), + &from_glib_borrow(caps), + filter.as_ref(), + ) + }) + .into_ptr() +} + +unsafe extern "C" fn base_transform_fixate_caps( + ptr: *mut ffi::GstBaseTransform, + direction: gst_ffi::GstPadDirection, + caps: *mut gst_ffi::GstCaps, + othercaps: *mut gst_ffi::GstCaps, +) -> *mut gst_ffi::GstCaps +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::Caps::new_empty(), { + imp.fixate_caps( + &wrap, + from_glib(direction), + &from_glib_borrow(caps), + from_glib_full(othercaps), + ) + }) + .into_ptr() +} + +unsafe extern "C" fn base_transform_set_caps( + ptr: *mut ffi::GstBaseTransform, + incaps: *mut gst_ffi::GstCaps, + outcaps: *mut gst_ffi::GstCaps, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.set_caps(&wrap, &from_glib_borrow(incaps), &from_glib_borrow(outcaps)) + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_accept_caps( + ptr: *mut ffi::GstBaseTransform, + direction: gst_ffi::GstPadDirection, + caps: *mut gst_ffi::GstCaps, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.accept_caps(&wrap, from_glib(direction), &from_glib_borrow(caps)) + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_query( + ptr: *mut ffi::GstBaseTransform, + direction: gst_ffi::GstPadDirection, + query: *mut gst_ffi::GstQuery, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + BaseTransformImpl::query( + imp, + &wrap, + from_glib(direction), + gst::QueryRef::from_mut_ptr(query), + ) + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_transform_size( + ptr: *mut ffi::GstBaseTransform, + direction: gst_ffi::GstPadDirection, + caps: *mut gst_ffi::GstCaps, + size: usize, + othercaps: *mut gst_ffi::GstCaps, + othersize: *mut usize, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + match imp.transform_size( + &wrap, + from_glib(direction), + &from_glib_borrow(caps), + size, + &from_glib_borrow(othercaps), + ) { + Some(s) => { + *othersize = s; + true + } + None => false, + } + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_get_unit_size( + ptr: *mut ffi::GstBaseTransform, + caps: *mut gst_ffi::GstCaps, + size: *mut usize, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + match imp.get_unit_size(&wrap, &from_glib_borrow(caps)) { + Some(s) => { + *size = s; + true + } + None => false, + } + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_sink_event( + ptr: *mut ffi::GstBaseTransform, + event: *mut gst_ffi::GstEvent, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.sink_event(&wrap, from_glib_full(event)) + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_src_event( + ptr: *mut ffi::GstBaseTransform, + event: *mut gst_ffi::GstEvent, +) -> glib_ffi::gboolean +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), false, { + imp.src_event(&wrap, from_glib_full(event)) + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_transform( + ptr: *mut ffi::GstBaseTransform, + inbuf: *mut gst_ffi::GstBuffer, + outbuf: *mut gst_ffi::GstBuffer, +) -> gst_ffi::GstFlowReturn +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.transform( + &wrap, + &from_glib_borrow(inbuf), + gst::BufferRef::from_mut_ptr(outbuf), + ) + }) + .to_glib() +} + +unsafe extern "C" fn base_transform_transform_ip( + ptr: *mut ffi::GstBaseTransform, + buf: *mut *mut gst_ffi::GstBuffer, +) -> gst_ffi::GstFlowReturn +where + T: BaseTransformImpl, + T::Instance: PanicPoison, +{ + glib_floating_reference_guard!(ptr); + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: BaseTransform = from_glib_borrow(ptr); + + // FIXME: Wrong signature in FFI + let buf = buf as *mut gst_ffi::GstBuffer; + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + if from_glib(ffi::gst_base_transform_is_passthrough(ptr)) { + imp.transform_ip_passthrough(&wrap, gst::BufferRef::from_ptr(buf)) + } else { + imp.transform_ip(&wrap, gst::BufferRef::from_mut_ptr(buf)) + } + }) + .to_glib() +} diff --git a/gstreamer-base/src/subclass/mod.rs b/gstreamer-base/src/subclass/mod.rs index 150265a54..68d346072 100644 --- a/gstreamer-base/src/subclass/mod.rs +++ b/gstreamer-base/src/subclass/mod.rs @@ -10,8 +10,12 @@ pub mod base_sink; pub mod base_src; +pub mod base_transform; + +pub use self::base_transform::BaseTransformMode; pub mod prelude { pub use super::base_sink::BaseSinkImpl; pub use super::base_src::BaseSrcImpl; + pub use super::base_transform::{BaseTransformClassSubclassExt, BaseTransformImpl}; }