diff --git a/gstreamer-video/Gir.toml b/gstreamer-video/Gir.toml index 5c20154f7..cfe647aa2 100644 --- a/gstreamer-video/Gir.toml +++ b/gstreamer-video/Gir.toml @@ -24,6 +24,7 @@ generate = [ "GstVideo.NavigationQueryType", "GstVideo.VideoAFDSpec", "GstVideo.VideoAFDValue", + "GstVideo.VideoAggregator", "GstVideo.VideoAggregatorParallelConvertPad", "GstVideo.VideoAlphaMode", "GstVideo.VideoBufferPool", @@ -59,10 +60,13 @@ manual = [ "Gst.Memory", "Gst.Message", "Gst.Object", + "Gst.Pad", "Gst.Pipeline", "Gst.State", "Gst.TagList", "Gst.TagMergeMode", + "GstBase.Aggregator", + "GstBase.AggregatorPad", "GstBase.BaseSink", "GstBase.BaseTransform", "GstVideo.VideoCodecFrame", @@ -236,6 +240,30 @@ status = "generate" name = "mouse_scroll" version = "1.18" +[[object]] +name = "GstVideo.VideoAggregatorConvertPad" +status = "generate" + [[object.property]] + name = "converter-config" + # wrong type + manual = true + +[[object]] +name = "GstVideo.VideoAggregatorPad" +status = "generate" + [[object.function]] + name = "get_current_buffer" + # needs special considerations + manual = true + [[object.function]] + name = "get_prepared_frame" + # needs special considerations + manual = true + [[object.function]] + name = "has_current_buffer" + # needs special considerations + manual = true + [[object]] name = "GstVideo.VideoBufferFlags" status = "generate" diff --git a/gstreamer-video/src/auto/mod.rs b/gstreamer-video/src/auto/mod.rs index 793d6e747..d5d7a761b 100644 --- a/gstreamer-video/src/auto/mod.rs +++ b/gstreamer-video/src/auto/mod.rs @@ -12,6 +12,27 @@ pub use self::color_balance_channel::ColorBalanceChannel; mod navigation; pub use self::navigation::Navigation; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +mod video_aggregator; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +pub use self::video_aggregator::VideoAggregator; + +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +mod video_aggregator_convert_pad; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +pub use self::video_aggregator_convert_pad::VideoAggregatorConvertPad; + +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +mod video_aggregator_pad; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +pub use self::video_aggregator_pad::VideoAggregatorPad; + #[cfg(any(feature = "v1_20", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] mod video_aggregator_parallel_convert_pad; @@ -99,6 +120,15 @@ pub mod traits { pub use super::color_balance::ColorBalanceExt; pub use super::color_balance_channel::ColorBalanceChannelExt; pub use super::navigation::NavigationExt; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub use super::video_aggregator::VideoAggregatorExt; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub use super::video_aggregator_convert_pad::VideoAggregatorConvertPadExt; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub use super::video_aggregator_pad::VideoAggregatorPadExt; pub use super::video_decoder::VideoDecoderExt; pub use super::video_encoder::VideoEncoderExt; pub use super::video_orientation::VideoOrientationExt; diff --git a/gstreamer-video/src/auto/video_aggregator.rs b/gstreamer-video/src/auto/video_aggregator.rs new file mode 100644 index 000000000..4209af484 --- /dev/null +++ b/gstreamer-video/src/auto/video_aggregator.rs @@ -0,0 +1,38 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use glib::object::IsA; + +glib::wrapper! { + #[doc(alias = "GstVideoAggregator")] + pub struct VideoAggregator(Object) @extends gst_base::Aggregator, gst::Element, gst::Object; + + match fn { + type_ => || ffi::gst_video_aggregator_get_type(), + } +} + +impl VideoAggregator { + pub const NONE: Option<&'static VideoAggregator> = None; +} + +unsafe impl Send for VideoAggregator {} +unsafe impl Sync for VideoAggregator {} + +pub trait VideoAggregatorExt: 'static { + //#[cfg(any(feature = "v1_20", feature = "dox"))] + //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + //#[doc(alias = "gst_video_aggregator_get_execution_task_pool")] + //#[doc(alias = "get_execution_task_pool")] + //fn execution_task_pool(&self) -> /*Ignored*/Option; +} + +impl> VideoAggregatorExt for O { + //#[cfg(any(feature = "v1_20", feature = "dox"))] + //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + //fn execution_task_pool(&self) -> /*Ignored*/Option { + // unsafe { TODO: call ffi:gst_video_aggregator_get_execution_task_pool() } + //} +} diff --git a/gstreamer-video/src/auto/video_aggregator_convert_pad.rs b/gstreamer-video/src/auto/video_aggregator_convert_pad.rs new file mode 100644 index 000000000..270cb088f --- /dev/null +++ b/gstreamer-video/src/auto/video_aggregator_convert_pad.rs @@ -0,0 +1,39 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use crate::VideoAggregatorPad; +use glib::object::IsA; +use glib::translate::*; + +glib::wrapper! { + #[doc(alias = "GstVideoAggregatorConvertPad")] + pub struct VideoAggregatorConvertPad(Object) @extends VideoAggregatorPad, gst_base::AggregatorPad, gst::Pad, gst::Object; + + match fn { + type_ => || ffi::gst_video_aggregator_convert_pad_get_type(), + } +} + +impl VideoAggregatorConvertPad { + pub const NONE: Option<&'static VideoAggregatorConvertPad> = None; +} + +unsafe impl Send for VideoAggregatorConvertPad {} +unsafe impl Sync for VideoAggregatorConvertPad {} + +pub trait VideoAggregatorConvertPadExt: 'static { + #[doc(alias = "gst_video_aggregator_convert_pad_update_conversion_info")] + fn update_conversion_info(&self); +} + +impl> VideoAggregatorConvertPadExt for O { + fn update_conversion_info(&self) { + unsafe { + ffi::gst_video_aggregator_convert_pad_update_conversion_info( + self.as_ref().to_glib_none().0, + ); + } + } +} diff --git a/gstreamer-video/src/auto/video_aggregator_pad.rs b/gstreamer-video/src/auto/video_aggregator_pad.rs new file mode 100644 index 000000000..a586168fa --- /dev/null +++ b/gstreamer-video/src/auto/video_aggregator_pad.rs @@ -0,0 +1,186 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir) +// from gir-files (https://github.com/gtk-rs/gir-files) +// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) +// DO NOT EDIT + +use glib::object::Cast; +use glib::object::IsA; +use glib::signal::connect_raw; +use glib::signal::SignalHandlerId; +use glib::translate::*; +use glib::StaticType; +use glib::ToValue; +use std::boxed::Box as Box_; +use std::mem::transmute; + +glib::wrapper! { + #[doc(alias = "GstVideoAggregatorPad")] + pub struct VideoAggregatorPad(Object) @extends gst_base::AggregatorPad, gst::Pad, gst::Object; + + match fn { + type_ => || ffi::gst_video_aggregator_pad_get_type(), + } +} + +impl VideoAggregatorPad { + pub const NONE: Option<&'static VideoAggregatorPad> = None; +} + +unsafe impl Send for VideoAggregatorPad {} +unsafe impl Sync for VideoAggregatorPad {} + +pub trait VideoAggregatorPadExt: 'static { + #[doc(alias = "gst_video_aggregator_pad_set_needs_alpha")] + fn set_needs_alpha(&self, needs_alpha: bool); + + #[doc(alias = "max-last-buffer-repeat")] + fn max_last_buffer_repeat(&self) -> u64; + + #[doc(alias = "max-last-buffer-repeat")] + fn set_max_last_buffer_repeat(&self, max_last_buffer_repeat: u64); + + #[doc(alias = "repeat-after-eos")] + fn is_repeat_after_eos(&self) -> bool; + + #[doc(alias = "repeat-after-eos")] + fn set_repeat_after_eos(&self, repeat_after_eos: bool); + + fn zorder(&self) -> u32; + + fn set_zorder(&self, zorder: u32); + + #[doc(alias = "max-last-buffer-repeat")] + fn connect_max_last_buffer_repeat_notify( + &self, + f: F, + ) -> SignalHandlerId; + + #[doc(alias = "repeat-after-eos")] + fn connect_repeat_after_eos_notify( + &self, + f: F, + ) -> SignalHandlerId; + + #[doc(alias = "zorder")] + fn connect_zorder_notify(&self, f: F) -> SignalHandlerId; +} + +impl> VideoAggregatorPadExt for O { + fn set_needs_alpha(&self, needs_alpha: bool) { + unsafe { + ffi::gst_video_aggregator_pad_set_needs_alpha( + self.as_ref().to_glib_none().0, + needs_alpha.into_glib(), + ); + } + } + + fn max_last_buffer_repeat(&self) -> u64 { + glib::ObjectExt::property(self.as_ref(), "max-last-buffer-repeat") + } + + fn set_max_last_buffer_repeat(&self, max_last_buffer_repeat: u64) { + glib::ObjectExt::set_property( + self.as_ref(), + "max-last-buffer-repeat", + &max_last_buffer_repeat, + ) + } + + fn is_repeat_after_eos(&self) -> bool { + glib::ObjectExt::property(self.as_ref(), "repeat-after-eos") + } + + fn set_repeat_after_eos(&self, repeat_after_eos: bool) { + glib::ObjectExt::set_property(self.as_ref(), "repeat-after-eos", &repeat_after_eos) + } + + fn zorder(&self) -> u32 { + glib::ObjectExt::property(self.as_ref(), "zorder") + } + + fn set_zorder(&self, zorder: u32) { + glib::ObjectExt::set_property(self.as_ref(), "zorder", &zorder) + } + + fn connect_max_last_buffer_repeat_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_max_last_buffer_repeat_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstVideoAggregatorPad, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(VideoAggregatorPad::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::max-last-buffer-repeat\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_max_last_buffer_repeat_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + fn connect_repeat_after_eos_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_repeat_after_eos_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstVideoAggregatorPad, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(VideoAggregatorPad::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::repeat-after-eos\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_repeat_after_eos_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + fn connect_zorder_notify(&self, f: F) -> SignalHandlerId { + unsafe extern "C" fn notify_zorder_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstVideoAggregatorPad, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(VideoAggregatorPad::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::zorder\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_zorder_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } +} diff --git a/gstreamer-video/src/auto/video_aggregator_parallel_convert_pad.rs b/gstreamer-video/src/auto/video_aggregator_parallel_convert_pad.rs index 878658ce0..00bf37289 100644 --- a/gstreamer-video/src/auto/video_aggregator_parallel_convert_pad.rs +++ b/gstreamer-video/src/auto/video_aggregator_parallel_convert_pad.rs @@ -3,9 +3,12 @@ // from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) // DO NOT EDIT +use crate::VideoAggregatorConvertPad; +use crate::VideoAggregatorPad; + glib::wrapper! { #[doc(alias = "GstVideoAggregatorParallelConvertPad")] - pub struct VideoAggregatorParallelConvertPad(Object) @extends gst::Object; + pub struct VideoAggregatorParallelConvertPad(Object) @extends VideoAggregatorConvertPad, VideoAggregatorPad, gst_base::AggregatorPad, gst::Pad, gst::Object; match fn { type_ => || ffi::gst_video_aggregator_parallel_convert_pad_get_type(), diff --git a/gstreamer-video/src/lib.rs b/gstreamer-video/src/lib.rs index 6843f7e8b..5720e2130 100644 --- a/gstreamer-video/src/lib.rs +++ b/gstreamer-video/src/lib.rs @@ -125,6 +125,16 @@ pub use crate::video_hdr::*; mod color_balance_channel; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +mod video_aggregator; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +mod video_aggregator_convert_pad; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +mod video_aggregator_pad; + pub const VIDEO_ENCODER_FLOW_NEED_DATA: gst::FlowSuccess = gst::FlowSuccess::CustomSuccess; pub const VIDEO_DECODER_FLOW_NEED_DATA: gst::FlowSuccess = gst::FlowSuccess::CustomSuccess; @@ -136,6 +146,15 @@ pub mod prelude { pub use crate::auto::traits::*; pub use crate::navigation::NavigationExtManual; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub use crate::video_aggregator::VideoAggregatorExtManual; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub use crate::video_aggregator_convert_pad::VideoAggregatorConvertPadExtManual; + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + pub use crate::video_aggregator_pad::VideoAggregatorPadExtManual; pub use crate::video_buffer_pool::VideoBufferPoolConfig; pub use crate::video_decoder::VideoDecoderExtManual; pub use crate::video_encoder::VideoEncoderExtManual; diff --git a/gstreamer-video/src/subclass/mod.rs b/gstreamer-video/src/subclass/mod.rs index 52fba3b54..484484746 100644 --- a/gstreamer-video/src/subclass/mod.rs +++ b/gstreamer-video/src/subclass/mod.rs @@ -8,6 +8,10 @@ mod video_encoder; mod video_filter; mod video_sink; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +pub use video_aggregator::AggregateFramesToken; + pub mod prelude { #[doc(hidden)] pub use gst_base::subclass::prelude::*; diff --git a/gstreamer-video/src/utils.rs b/gstreamer-video/src/utils.rs index 6a62e289d..37218cefb 100644 --- a/gstreamer-video/src/utils.rs +++ b/gstreamer-video/src/utils.rs @@ -1,8 +1,35 @@ // Take a look at the license at the top of the repository in the LICENSE file. +use glib::translate::mut_override; + pub trait HasStreamLock { #[doc(alias = "get_stream_lock")] fn stream_lock(&self) -> *mut glib::ffi::GRecMutex; #[doc(alias = "get_element_as_ptr")] fn element_as_ptr(&self) -> *const gst::ffi::GstElement; } + +#[must_use = "if unused the Mutex will immediately unlock"] +#[doc(alias = "GMutex")] +pub struct MutexGuard<'a>(&'a glib::ffi::GMutex); + +impl<'a> MutexGuard<'a> { + #[allow(clippy::trivially_copy_pass_by_ref)] + #[allow(dead_code)] + #[doc(alias = "g_mutex_lock")] + pub fn lock(mutex: &'a glib::ffi::GMutex) -> Self { + skip_assert_initialized!(); + unsafe { + glib::ffi::g_mutex_lock(mut_override(mutex)); + } + MutexGuard(mutex) + } +} + +impl<'a> Drop for MutexGuard<'a> { + fn drop(&mut self) { + unsafe { + glib::ffi::g_mutex_unlock(mut_override(self.0)); + } + } +} diff --git a/gstreamer-video/src/video_aggregator.rs b/gstreamer-video/src/video_aggregator.rs new file mode 100644 index 000000000..f1f223b58 --- /dev/null +++ b/gstreamer-video/src/video_aggregator.rs @@ -0,0 +1,26 @@ +use crate::auto::VideoAggregator; +use glib::object::IsA; +use glib::translate::*; + +pub trait VideoAggregatorExtManual: 'static { + fn video_info(&self) -> Option; +} + +impl> VideoAggregatorExtManual for O { + fn video_info(&self) -> Option { + unsafe { + let ptr = self.as_ptr() as *mut ffi::GstVideoAggregator; + let _guard = crate::utils::MutexGuard::lock(&(*(ptr as *mut gst::ffi::GstObject)).lock); + + let info = &(*ptr).info; + + if info.finfo.is_null() || info.width <= 0 || info.height <= 0 { + return None; + } + + Some(from_glib_none(mut_override( + info as *const ffi::GstVideoInfo, + ))) + } + } +} diff --git a/gstreamer-video/src/video_aggregator_convert_pad.rs b/gstreamer-video/src/video_aggregator_convert_pad.rs new file mode 100644 index 000000000..158330939 --- /dev/null +++ b/gstreamer-video/src/video_aggregator_convert_pad.rs @@ -0,0 +1,64 @@ +use crate::auto::VideoAggregatorConvertPad; +use glib::object::IsA; +use glib::signal::{connect_raw, SignalHandlerId}; +use glib::translate::*; +use glib::Cast; + +use std::mem::transmute; + +pub trait VideoAggregatorConvertPadExtManual: 'static { + #[doc(alias = "converter-config")] + fn converter_config(&self) -> Option; + + #[doc(alias = "converter-config")] + fn set_converter_config(&self, converter_config: Option<&crate::VideoConverterConfig>); + + #[doc(alias = "converter-config")] + fn connect_converter_config_notify( + &self, + f: F, + ) -> SignalHandlerId; +} + +impl> VideoAggregatorConvertPadExtManual for O { + fn converter_config(&self) -> Option { + glib::ObjectExt::property::>(self.as_ref(), "converter-config") + .map(|c| c.try_into().unwrap()) + } + + fn set_converter_config(&self, converter_config: Option<&crate::VideoConverterConfig>) { + glib::ObjectExt::set_property( + self.as_ref(), + "converter-config", + converter_config.map(|s| s.as_ref()), + ) + } + + fn connect_converter_config_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_converter_config_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstVideoAggregatorConvertPad, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(VideoAggregatorConvertPad::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box = Box::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::converter-config\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_converter_config_trampoline:: as *const (), + )), + Box::into_raw(f), + ) + } + } +} diff --git a/gstreamer-video/src/video_aggregator_pad.rs b/gstreamer-video/src/video_aggregator_pad.rs new file mode 100644 index 000000000..02b5e37e0 --- /dev/null +++ b/gstreamer-video/src/video_aggregator_pad.rs @@ -0,0 +1,71 @@ +use crate::auto::VideoAggregatorPad; +use crate::subclass::AggregateFramesToken; +use glib::object::IsA; +use glib::translate::*; + +pub trait VideoAggregatorPadExtManual: 'static { + #[doc(alias = "gst_video_aggregator_pad_has_current_buffer")] + fn has_current_buffer(&self, token: &AggregateFramesToken) -> bool; + + #[doc(alias = "gst_video_aggregator_pad_get_current_buffer")] + fn current_buffer(&self, token: &AggregateFramesToken) -> Option; + + #[doc(alias = "gst_video_aggregator_pad_get_prepared_frame")] + fn prepared_frame<'a>( + &self, + token: &'a AggregateFramesToken, + ) -> Option>; + + fn video_info(&self) -> Option; +} + +impl> VideoAggregatorPadExtManual for O { + fn has_current_buffer(&self, _token: &AggregateFramesToken) -> bool { + unsafe { + from_glib(ffi::gst_video_aggregator_pad_has_current_buffer( + self.as_ref().to_glib_none().0, + )) + } + } + + fn current_buffer(&self, _token: &AggregateFramesToken) -> Option { + unsafe { + from_glib_none(ffi::gst_video_aggregator_pad_get_current_buffer( + self.as_ref().to_glib_none().0, + )) + } + } + + fn prepared_frame<'a>( + &self, + _token: &'a AggregateFramesToken, + ) -> Option> { + unsafe { + let ptr = + ffi::gst_video_aggregator_pad_get_prepared_frame(self.as_ref().to_glib_none().0); + + if ptr.is_null() { + None + } else { + Some(crate::VideoFrameRef::from_glib_borrow(ptr).into_inner()) + } + } + } + + fn video_info(&self) -> Option { + unsafe { + let ptr = self.as_ptr() as *mut ffi::GstVideoAggregatorPad; + let _guard = crate::utils::MutexGuard::lock(&(*(ptr as *mut gst::ffi::GstObject)).lock); + + let info = &(*ptr).info; + + if info.finfo.is_null() || info.width <= 0 || info.height <= 0 { + return None; + } + + Some(from_glib_none(mut_override( + info as *const ffi::GstVideoInfo, + ))) + } + } +}