diff --git a/gstreamer-rtp/Gir.toml b/gstreamer-rtp/Gir.toml index a3b89d9ca..e160e7c2f 100644 --- a/gstreamer-rtp/Gir.toml +++ b/gstreamer-rtp/Gir.toml @@ -79,6 +79,25 @@ status = "generate" name = "rtp_source_meta_api_get_type" ignore = true +[[object]] +name = "GstRtp.RTPBaseDepayload" +status = "generate" + + [[object.function]] + name = "push" + # Move buffer + manual = true + + [[object.function]] + name = "push_list" + # Move buffer list + manual = true + + [[object.signal]] + name = "request-extension" + [object.signal.return] + nullable = true + [[object]] name = "GstRtp.RTPBasePayload" status = "generate" diff --git a/gstreamer-rtp/src/auto/mod.rs b/gstreamer-rtp/src/auto/mod.rs index 3afa00cee..f5f6f6e46 100644 --- a/gstreamer-rtp/src/auto/mod.rs +++ b/gstreamer-rtp/src/auto/mod.rs @@ -3,6 +3,9 @@ // from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git) // DO NOT EDIT +mod rtp_base_depayload; +pub use self::rtp_base_depayload::RTPBaseDepayload; + mod rtp_base_payload; pub use self::rtp_base_payload::RTPBasePayload; @@ -79,6 +82,7 @@ pub use self::constants::RTP_PAYLOAD_TS48_STRING; #[doc(hidden)] pub mod traits { + pub use super::rtp_base_depayload::RTPBaseDepayloadExt; pub use super::rtp_base_payload::RTPBasePayloadExt; #[cfg(any(feature = "v1_20", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] diff --git a/gstreamer-rtp/src/auto/rtp_base_depayload.rs b/gstreamer-rtp/src/auto/rtp_base_depayload.rs new file mode 100644 index 000000000..014342a63 --- /dev/null +++ b/gstreamer-rtp/src/auto/rtp_base_depayload.rs @@ -0,0 +1,440 @@ +// 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 + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +use crate::RTPHeaderExtension; +use glib::object::Cast; +use glib::object::IsA; +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +use glib::object::ObjectExt; +use glib::signal::connect_raw; +use glib::signal::SignalHandlerId; +use glib::translate::*; +use glib::StaticType; +#[cfg(any(feature = "v1_16", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] +use glib::ToValue; +use std::boxed::Box as Box_; +use std::mem::transmute; + +glib::wrapper! { + #[doc(alias = "GstRTPBaseDepayload")] + pub struct RTPBaseDepayload(Object) @extends gst::Element; + + match fn { + type_ => || ffi::gst_rtp_base_depayload_get_type(), + } +} + +impl RTPBaseDepayload { + pub const NONE: Option<&'static RTPBaseDepayload> = None; +} + +unsafe impl Send for RTPBaseDepayload {} +unsafe impl Sync for RTPBaseDepayload {} + +pub trait RTPBaseDepayloadExt: 'static { + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + #[doc(alias = "gst_rtp_base_depayload_is_source_info_enabled")] + fn is_source_info_enabled(&self) -> bool; + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + #[doc(alias = "gst_rtp_base_depayload_set_source_info_enabled")] + fn set_source_info_enabled(&self, enable: bool); + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "auto-header-extension")] + fn is_auto_header_extension(&self) -> bool; + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "auto-header-extension")] + fn set_auto_header_extension(&self, auto_header_extension: bool); + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + #[doc(alias = "max-reorder")] + fn max_reorder(&self) -> i32; + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + #[doc(alias = "max-reorder")] + fn set_max_reorder(&self, max_reorder: i32); + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + #[doc(alias = "source-info")] + fn is_source_info(&self) -> bool; + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + #[doc(alias = "source-info")] + fn set_source_info(&self, source_info: bool); + + fn stats(&self) -> Option; + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "add-extension")] + fn connect_add_extension( + &self, + f: F, + ) -> SignalHandlerId; + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn emit_add_extension(&self, ext: &RTPHeaderExtension); + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "clear-extensions")] + fn connect_clear_extensions( + &self, + f: F, + ) -> SignalHandlerId; + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn emit_clear_extensions(&self); + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "request-extension")] + fn connect_request_extension< + F: Fn(&Self, u32, Option<&str>) -> Option + Send + Sync + 'static, + >( + &self, + f: F, + ) -> SignalHandlerId; + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "auto-header-extension")] + fn connect_auto_header_extension_notify( + &self, + f: F, + ) -> SignalHandlerId; + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + #[doc(alias = "max-reorder")] + fn connect_max_reorder_notify( + &self, + f: F, + ) -> SignalHandlerId; + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + #[doc(alias = "source-info")] + fn connect_source_info_notify( + &self, + f: F, + ) -> SignalHandlerId; + + #[doc(alias = "stats")] + fn connect_stats_notify(&self, f: F) -> SignalHandlerId; +} + +impl> RTPBaseDepayloadExt for O { + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + fn is_source_info_enabled(&self) -> bool { + unsafe { + from_glib(ffi::gst_rtp_base_depayload_is_source_info_enabled( + self.as_ref().to_glib_none().0, + )) + } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + fn set_source_info_enabled(&self, enable: bool) { + unsafe { + ffi::gst_rtp_base_depayload_set_source_info_enabled( + self.as_ref().to_glib_none().0, + enable.into_glib(), + ); + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn is_auto_header_extension(&self) -> bool { + glib::ObjectExt::property(self.as_ref(), "auto-header-extension") + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn set_auto_header_extension(&self, auto_header_extension: bool) { + glib::ObjectExt::set_property( + self.as_ref(), + "auto-header-extension", + &auto_header_extension, + ) + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + fn max_reorder(&self) -> i32 { + glib::ObjectExt::property(self.as_ref(), "max-reorder") + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + fn set_max_reorder(&self, max_reorder: i32) { + glib::ObjectExt::set_property(self.as_ref(), "max-reorder", &max_reorder) + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + fn is_source_info(&self) -> bool { + glib::ObjectExt::property(self.as_ref(), "source-info") + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + fn set_source_info(&self, source_info: bool) { + glib::ObjectExt::set_property(self.as_ref(), "source-info", &source_info) + } + + fn stats(&self) -> Option { + glib::ObjectExt::property(self.as_ref(), "stats") + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn connect_add_extension( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn add_extension_trampoline< + P: IsA, + F: Fn(&P, &RTPHeaderExtension) + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + ext: *mut ffi::GstRTPHeaderExtension, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f( + RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref(), + &from_glib_full(ext), + ) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"add-extension\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + add_extension_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn emit_add_extension(&self, ext: &RTPHeaderExtension) { + self.emit_by_name::<()>("add-extension", &[&ext]); + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn connect_clear_extensions( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn clear_extensions_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"clear-extensions\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + clear_extensions_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn emit_clear_extensions(&self) { + self.emit_by_name::<()>("clear-extensions", &[]); + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn connect_request_extension< + F: Fn(&Self, u32, Option<&str>) -> Option + Send + Sync + 'static, + >( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn request_extension_trampoline< + P: IsA, + F: Fn(&P, u32, Option<&str>) -> Option + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + ext_id: libc::c_uint, + ext_uri: *mut libc::c_char, + f: glib::ffi::gpointer, + ) -> *mut ffi::GstRTPHeaderExtension { + let f: &F = &*(f as *const F); + f( + RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref(), + ext_id, + Option::::from_glib_borrow(ext_uri) + .as_ref() + .as_ref() + .map(|s| s.as_str()), + ) + .to_glib_full() + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"request-extension\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + request_extension_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + fn connect_auto_header_extension_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_auto_header_extension_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::auto-header-extension\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_auto_header_extension_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))] + fn connect_max_reorder_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_max_reorder_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::max-reorder\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_max_reorder_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))] + fn connect_source_info_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_source_info_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::source-info\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_source_info_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + fn connect_stats_notify(&self, f: F) -> SignalHandlerId { + unsafe extern "C" fn notify_stats_trampoline< + P: IsA, + F: Fn(&P) + Send + Sync + 'static, + >( + this: *mut ffi::GstRTPBaseDepayload, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(RTPBaseDepayload::from_glib_borrow(this).unsafe_cast_ref()) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::stats\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_stats_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } +} diff --git a/gstreamer-rtp/src/lib.rs b/gstreamer-rtp/src/lib.rs index 20157aa73..610d17075 100644 --- a/gstreamer-rtp/src/lib.rs +++ b/gstreamer-rtp/src/lib.rs @@ -43,6 +43,8 @@ pub mod rtp_header_extension; #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] pub mod rtp_base_payload; +pub mod rtp_base_depayload; + // Re-export all the traits in a prelude module, so that applications // can always "use gst_rtp::prelude::*" without getting conflicts pub mod prelude { @@ -59,4 +61,6 @@ pub mod prelude { #[cfg(any(feature = "v1_20", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] pub use crate::rtp_base_payload::RTPBasePayloadExtManual; + + pub use crate::rtp_base_depayload::RTPBaseDepayloadExtManual; } diff --git a/gstreamer-rtp/src/rtp_base_depayload.rs b/gstreamer-rtp/src/rtp_base_depayload.rs new file mode 100644 index 000000000..24985c60f --- /dev/null +++ b/gstreamer-rtp/src/rtp_base_depayload.rs @@ -0,0 +1,31 @@ +use crate::RTPBaseDepayload; +use glib::object::IsA; +use glib::translate::*; + +pub trait RTPBaseDepayloadExtManual: 'static { + #[doc(alias = "gst_rtp_base_depayload_push")] + fn push(&self, buffer: gst::Buffer) -> Result; + + #[doc(alias = "gst_rtp_base_depayload_push_list")] + fn push_list(&self, list: gst::BufferList) -> Result; +} + +impl> RTPBaseDepayloadExtManual for O { + fn push(&self, out_buf: gst::Buffer) -> Result { + unsafe { + try_from_glib(ffi::gst_rtp_base_depayload_push( + self.as_ref().to_glib_none().0, + out_buf.into_ptr(), + )) + } + } + + fn push_list(&self, out_list: gst::BufferList) -> Result { + unsafe { + try_from_glib(ffi::gst_rtp_base_depayload_push_list( + self.as_ref().to_glib_none().0, + out_list.into_ptr(), + )) + } + } +} diff --git a/gstreamer-rtp/src/rtp_buffer.rs b/gstreamer-rtp/src/rtp_buffer.rs index e58c809e7..f79300941 100644 --- a/gstreamer-rtp/src/rtp_buffer.rs +++ b/gstreamer-rtp/src/rtp_buffer.rs @@ -49,6 +49,15 @@ impl<'a> RTPBuffer<'a, Readable> { } } } + + pub unsafe fn from_glib_borrow<'b>( + rtp_buffer: *mut ffi::GstRTPBuffer, + ) -> glib::translate::Borrowed> { + glib::translate::Borrowed::new(RTPBuffer { + rtp_buffer: *rtp_buffer, + phantom: PhantomData, + }) + } } impl<'a> RTPBuffer<'a, Writable> { @@ -385,6 +394,14 @@ impl<'a, T> RTPBuffer<'a, T> { )) } } + + pub unsafe fn as_ptr(&self) -> *const ffi::GstRTPBuffer { + &self.rtp_buffer as *const ffi::GstRTPBuffer + } + + pub unsafe fn as_mut_ptr(&self) -> *mut ffi::GstRTPBuffer { + &self.rtp_buffer as *const ffi::GstRTPBuffer as *mut ffi::GstRTPBuffer + } } impl<'a, T> Drop for RTPBuffer<'a, T> { diff --git a/gstreamer-rtp/src/subclass/mod.rs b/gstreamer-rtp/src/subclass/mod.rs index 0023ae4a1..e2190e0f4 100644 --- a/gstreamer-rtp/src/subclass/mod.rs +++ b/gstreamer-rtp/src/subclass/mod.rs @@ -6,6 +6,8 @@ #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] mod rtp_base_payload; +mod rtp_base_depayload; + #[cfg(any(feature = "v1_20", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] mod rtp_header_extension; @@ -18,6 +20,8 @@ pub mod prelude { #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] pub use super::rtp_base_payload::{RTPBasePayloadImpl, RTPBasePayloadImplExt}; + pub use super::rtp_base_depayload::{RTPBaseDepayloadImpl, RTPBaseDepayloadImplExt}; + #[cfg(any(feature = "v1_20", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] pub use super::rtp_header_extension::{RTPHeaderExtensionImpl, RTPHeaderExtensionImplExt}; diff --git a/gstreamer-rtp/src/subclass/rtp_base_depayload.rs b/gstreamer-rtp/src/subclass/rtp_base_depayload.rs new file mode 100644 index 000000000..792703937 --- /dev/null +++ b/gstreamer-rtp/src/subclass/rtp_base_depayload.rs @@ -0,0 +1,218 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +use glib::translate::*; + +use gst::subclass::prelude::*; + +use crate::prelude::*; +use crate::RTPBaseDepayload; +use std::ptr; + +pub trait RTPBaseDepayloadImpl: RTPBaseDepayloadImplExt + ElementImpl { + fn set_caps(&self, element: &Self::Type, caps: &gst::Caps) -> Result<(), gst::LoggableError> { + self.parent_set_caps(element, caps) + } + + fn handle_event(&self, element: &Self::Type, event: gst::Event) -> bool { + self.parent_handle_event(element, event) + } + + fn packet_lost(&self, element: &Self::Type, event: &gst::EventRef) -> bool { + self.parent_packet_lost(element, event) + } + + fn process_rtp_packet( + &self, + element: &Self::Type, + rtp_buffer: &crate::RTPBuffer, + ) -> Option { + self.parent_process_rtp_packet(element, rtp_buffer) + } +} + +pub trait RTPBaseDepayloadImplExt: ObjectSubclass { + fn parent_set_caps( + &self, + element: &Self::Type, + caps: &gst::Caps, + ) -> Result<(), gst::LoggableError>; + + fn parent_handle_event(&self, element: &Self::Type, event: gst::Event) -> bool; + + fn parent_packet_lost(&self, element: &Self::Type, event: &gst::EventRef) -> bool; + + fn parent_process_rtp_packet( + &self, + element: &Self::Type, + rtp_buffer: &crate::RTPBuffer, + ) -> Option; +} + +impl RTPBaseDepayloadImplExt for T { + fn parent_set_caps( + &self, + element: &Self::Type, + caps: &gst::Caps, + ) -> Result<(), gst::LoggableError> { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass; + (*parent_class) + .set_caps + .map(|f| { + gst::result_from_gboolean!( + f( + element + .unsafe_cast_ref::() + .to_glib_none() + .0, + caps.to_glib_none().0 + ), + gst::CAT_RUST, + "Parent function `set_caps` failed" + ) + }) + .unwrap_or(Ok(())) + } + } + + fn parent_handle_event(&self, element: &Self::Type, event: gst::Event) -> bool { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass; + (*parent_class) + .handle_event + .map(|f| { + from_glib(f( + element + .unsafe_cast_ref::() + .to_glib_none() + .0, + event.into_ptr(), + )) + }) + .unwrap_or(false) + } + } + + fn parent_packet_lost(&self, element: &Self::Type, event: &gst::EventRef) -> bool { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass; + (*parent_class) + .packet_lost + .map(|f| { + from_glib(f( + element + .unsafe_cast_ref::() + .to_glib_none() + .0, + event.as_mut_ptr(), + )) + }) + .unwrap_or(true) + } + } + + fn parent_process_rtp_packet( + &self, + element: &Self::Type, + rtp_buffer: &crate::RTPBuffer, + ) -> Option { + unsafe { + let data = Self::type_data(); + let parent_class = data.as_ref().parent_class() as *mut ffi::GstRTPBaseDepayloadClass; + + let f = (*parent_class) + .process_rtp_packet + .expect("no parent \"process\" implementation"); + + from_glib_full(f( + element + .unsafe_cast_ref::() + .to_glib_none() + .0, + mut_override(rtp_buffer.as_ptr()), + )) + } + } +} + +unsafe impl IsSubclassable for RTPBaseDepayload { + fn class_init(klass: &mut glib::Class) { + Self::parent_class_init::(klass); + let klass = klass.as_mut(); + + klass.process = None; + klass.process_rtp_packet = Some(rtp_base_depayload_process_rtp_packet::); + klass.set_caps = Some(rtp_base_depayload_set_caps::); + klass.handle_event = Some(rtp_base_depayload_handle_event::); + klass.packet_lost = Some(rtp_base_depayload_packet_lost::); + } +} + +unsafe extern "C" fn rtp_base_depayload_set_caps( + ptr: *mut ffi::GstRTPBaseDepayload, + caps: *mut gst::ffi::GstCaps, +) -> glib::ffi::gboolean { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed = from_glib_borrow(ptr); + let caps = from_glib_borrow(caps); + + gst::panic_to_error!(&wrap, imp.panicked(), false, { + match imp.set_caps(wrap.unsafe_cast_ref(), &caps) { + Ok(()) => true, + Err(err) => { + err.log_with_object(&*wrap); + false + } + } + }) + .into_glib() +} + +unsafe extern "C" fn rtp_base_depayload_handle_event( + ptr: *mut ffi::GstRTPBaseDepayload, + event: *mut gst::ffi::GstEvent, +) -> glib::ffi::gboolean { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst::panic_to_error!(&wrap, imp.panicked(), false, { + imp.handle_event(wrap.unsafe_cast_ref(), from_glib_full(event)) + }) + .into_glib() +} + +unsafe extern "C" fn rtp_base_depayload_packet_lost( + ptr: *mut ffi::GstRTPBaseDepayload, + event: *mut gst::ffi::GstEvent, +) -> glib::ffi::gboolean { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst::panic_to_error!(&wrap, imp.panicked(), false, { + imp.packet_lost(wrap.unsafe_cast_ref(), gst::EventRef::from_ptr(event)) + }) + .into_glib() +} + +unsafe extern "C" fn rtp_base_depayload_process_rtp_packet( + ptr: *mut ffi::GstRTPBaseDepayload, + rtp_packet: *mut ffi::GstRTPBuffer, +) -> *mut gst::ffi::GstBuffer { + let instance = &*(ptr as *mut T::Instance); + let imp = instance.imp(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst::panic_to_error!(&wrap, imp.panicked(), ptr::null_mut(), { + let bufwrap = crate::RTPBuffer::::from_glib_borrow(rtp_packet); + + imp.process_rtp_packet(wrap.unsafe_cast_ref(), &bufwrap) + .map(|buffer| buffer.into_ptr()) + .unwrap_or(ptr::null_mut()) + }) +}