diff --git a/gstreamer-app/Gir.toml b/gstreamer-app/Gir.toml index 70ef176bb..c97ec5b00 100644 --- a/gstreamer-app/Gir.toml +++ b/gstreamer-app/Gir.toml @@ -26,6 +26,7 @@ manual = [ "Gst.Element", "Gst.URIHandler", "Gst.Format", + "Gst.MiniObject", ] [[object]] @@ -52,6 +53,11 @@ final_type = true # Action signal ignore = true + [[object.signal]] + name = "pull-object" + # Action signal + ignore = true + [[object.signal]] name = "try-pull-sample" # Action signal @@ -62,6 +68,11 @@ final_type = true # Action signal ignore = true + [[object.signal]] + name = "try-pull-object" + # Action signal + ignore = true + [[object.property]] name = "emit-signals" # Use callbacks instead @@ -92,6 +103,11 @@ final_type = true # Use callbacks instead ignore = true + [[object.signal]] + name = "new-serialized-event" + # Use callbacks instead + ignore = true + [[object.function]] name = "set_caps" [[object.function.parameter]] @@ -108,6 +124,11 @@ final_type = true [object.function.return] nullable_return_is_error = "Failed to pull sample" + [[object.function]] + name = "pull_object" + [object.function.return] + nullable_return_is_error = "Failed to pull object" + [[object]] name = "GstApp.AppSrc" status = "generate" diff --git a/gstreamer-app/src/app_sink.rs b/gstreamer-app/src/app_sink.rs index e5db64901..3dec94682 100644 --- a/gstreamer-app/src/app_sink.rs +++ b/gstreamer-app/src/app_sink.rs @@ -33,6 +33,7 @@ pub struct AppSinkCallbacks { Box Result + Send + 'static>, >, >, + new_event: Option bool + Send + 'static>>>, panicked: AtomicBool, callbacks: ffi::GstAppSinkCallbacks, } @@ -47,6 +48,7 @@ impl AppSinkCallbacks { eos: None, new_preroll: None, new_sample: None, + new_event: None, } } } @@ -64,6 +66,7 @@ pub struct AppSinkCallbacksBuilder { Box Result + Send + 'static>, >, >, + new_event: Option bool + Send + 'static>>>, } impl AppSinkCallbacksBuilder { @@ -98,15 +101,26 @@ impl AppSinkCallbacksBuilder { } } + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + pub fn new_event bool + Send + 'static>(self, new_event: F) -> Self { + Self { + new_event: Some(RefCell::new(Box::new(new_event))), + ..self + } + } + pub fn build(self) -> AppSinkCallbacks { let have_eos = self.eos.is_some(); let have_new_preroll = self.new_preroll.is_some(); let have_new_sample = self.new_sample.is_some(); + let have_new_event = self.new_event.is_some(); AppSinkCallbacks { eos: self.eos, new_preroll: self.new_preroll, new_sample: self.new_sample, + new_event: self.new_event, panicked: AtomicBool::new(false), callbacks: ffi::GstAppSinkCallbacks { eos: if have_eos { Some(trampoline_eos) } else { None }, @@ -120,12 +134,12 @@ impl AppSinkCallbacksBuilder { } else { None }, - _gst_reserved: [ - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ptr::null_mut(), - ], + new_event: if have_new_event { + Some(trampoline_new_event) + } else { + None + }, + _gst_reserved: [ptr::null_mut(), ptr::null_mut(), ptr::null_mut()], }, } } @@ -232,6 +246,39 @@ unsafe extern "C" fn trampoline_new_sample( ret.into_glib() } +unsafe extern "C" fn trampoline_new_event( + appsink: *mut ffi::GstAppSink, + callbacks: gpointer, +) -> glib::ffi::gboolean { + let callbacks = &*(callbacks as *const AppSinkCallbacks); + let element: Borrowed = from_glib_borrow(appsink); + + if callbacks.panicked.load(Ordering::Relaxed) { + let element: Borrowed = from_glib_borrow(appsink); + gst::element_error!(element, gst::LibraryError::Failed, ["Panicked"]); + return false.into_glib(); + } + + let ret = if let Some(ref new_event) = callbacks.new_event { + let result = panic::catch_unwind(panic::AssertUnwindSafe(|| { + (&mut *new_event.borrow_mut())(&element) + })); + match result { + Ok(result) => result, + Err(err) => { + callbacks.panicked.store(true, Ordering::Relaxed); + post_panic_error_message(&element, &err); + + false + } + } + } else { + false + }; + + ret.into_glib() +} + unsafe extern "C" fn destroy_callbacks(ptr: gpointer) { Box::::from_raw(ptr as *mut _); } diff --git a/gstreamer-app/src/auto/app_sink.rs b/gstreamer-app/src/auto/app_sink.rs index 8bc0959e9..59f6e65c0 100644 --- a/gstreamer-app/src/auto/app_sink.rs +++ b/gstreamer-app/src/auto/app_sink.rs @@ -3,9 +3,6 @@ // 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 glib::object::ObjectExt; use glib::object::ObjectType as ObjectType_; use glib::signal::connect_raw; use glib::signal::SignalHandlerId; @@ -66,12 +63,15 @@ impl AppSink { unsafe { from_glib(ffi::gst_app_sink_is_eos(self.to_glib_none().0)) } } - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "gst_app_sink_pull_object")] - //pub fn pull_object(&self) -> /*Ignored*/Option { - // unsafe { TODO: call ffi:gst_app_sink_pull_object() } - //} + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_app_sink_pull_object")] + pub fn pull_object(&self) -> Result { + unsafe { + Option::<_>::from_glib_full(ffi::gst_app_sink_pull_object(self.to_glib_none().0)) + .ok_or_else(|| glib::bool_error!("Failed to pull object")) + } + } #[doc(alias = "gst_app_sink_pull_preroll")] pub fn pull_preroll(&self) -> Result { @@ -134,12 +134,20 @@ impl AppSink { } } - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "gst_app_sink_try_pull_object")] - //pub fn try_pull_object(&self, timeout: impl Into>) -> /*Ignored*/Option { - // unsafe { TODO: call ffi:gst_app_sink_try_pull_object() } - //} + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_app_sink_try_pull_object")] + pub fn try_pull_object( + &self, + timeout: impl Into>, + ) -> Option { + unsafe { + from_glib_full(ffi::gst_app_sink_try_pull_object( + self.to_glib_none().0, + timeout.into().into_glib(), + )) + } + } #[cfg(any(feature = "v1_10", feature = "dox"))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_10")))] @@ -197,42 +205,6 @@ impl AppSink { } } - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "new-serialized-event")] - pub fn connect_new_serialized_event bool + Send + Sync + 'static>( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn new_serialized_event_trampoline< - F: Fn(&AppSink) -> bool + Send + Sync + 'static, - >( - this: *mut ffi::GstAppSink, - f: glib::ffi::gpointer, - ) -> glib::ffi::gboolean { - let f: &F = &*(f as *const F); - f(&from_glib_borrow(this)).into_glib() - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"new-serialized-event\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - new_serialized_event_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "try-pull-object")] - //pub fn connect_try_pull_object(&self, f: F) -> SignalHandlerId { - // Ignored return value Gst.MiniObject - //} - #[doc(alias = "buffer-list")] pub fn connect_buffer_list_notify( &self, diff --git a/gstreamer-pbutils/Gir.toml b/gstreamer-pbutils/Gir.toml index 1bece0698..676c678d3 100644 --- a/gstreamer-pbutils/Gir.toml +++ b/gstreamer-pbutils/Gir.toml @@ -17,6 +17,7 @@ external_libraries = [ generate = [ "GstPbutils.DiscovererResult", + "GstPbutils.PbUtilsCapsDescriptionFlags", ] manual = [ diff --git a/gstreamer-pbutils/src/auto/flags.rs b/gstreamer-pbutils/src/auto/flags.rs index 1b805748f..c89ad5b51 100644 --- a/gstreamer-pbutils/src/auto/flags.rs +++ b/gstreamer-pbutils/src/auto/flags.rs @@ -71,3 +71,87 @@ impl ToValue for DiscovererSerializeFlags { Self::static_type() } } + +#[cfg(any(feature = "v1_20", feature = "dox"))] +bitflags! { + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "GstPbUtilsCapsDescriptionFlags")] + pub struct PbUtilsCapsDescriptionFlags: u32 { + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_CONTAINER")] + const CONTAINER = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_CONTAINER as u32; + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_AUDIO")] + const AUDIO = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_AUDIO as u32; + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_VIDEO")] + const VIDEO = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_VIDEO as u32; + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_IMAGE")] + const IMAGE = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_IMAGE as u32; + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_SUBTITLE")] + const SUBTITLE = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_SUBTITLE as u32; + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_TAG")] + const TAG = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_TAG as u32; + #[doc(alias = "GST_PBUTILS_CAPS_DESCRIPTION_FLAG_GENERIC")] + const GENERIC = ffi::GST_PBUTILS_CAPS_DESCRIPTION_FLAG_GENERIC as u32; + } +} + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +#[doc(hidden)] +impl IntoGlib for PbUtilsCapsDescriptionFlags { + type GlibType = ffi::GstPbUtilsCapsDescriptionFlags; + + fn into_glib(self) -> ffi::GstPbUtilsCapsDescriptionFlags { + self.bits() + } +} + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +#[doc(hidden)] +impl FromGlib for PbUtilsCapsDescriptionFlags { + unsafe fn from_glib(value: ffi::GstPbUtilsCapsDescriptionFlags) -> Self { + skip_assert_initialized!(); + Self::from_bits_truncate(value) + } +} + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +impl StaticType for PbUtilsCapsDescriptionFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_pb_utils_caps_description_flags_get_type()) } + } +} + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +impl glib::value::ValueType for PbUtilsCapsDescriptionFlags { + type Type = Self; +} + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +unsafe impl<'a> FromValue<'a> for PbUtilsCapsDescriptionFlags { + type Checker = glib::value::GenericValueTypeChecker; + + unsafe fn from_value(value: &'a glib::Value) -> Self { + skip_assert_initialized!(); + from_glib(glib::gobject_ffi::g_value_get_flags(value.to_glib_none().0)) + } +} + +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +impl ToValue for PbUtilsCapsDescriptionFlags { + fn to_value(&self) -> glib::Value { + let mut value = glib::Value::for_value_type::(); + unsafe { + glib::gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, self.into_glib()); + } + value + } + + fn value_type(&self) -> glib::Type { + Self::static_type() + } +} diff --git a/gstreamer-pbutils/src/auto/functions.rs b/gstreamer-pbutils/src/auto/functions.rs index d26bb5e2c..ef4012021 100644 --- a/gstreamer-pbutils/src/auto/functions.rs +++ b/gstreamer-pbutils/src/auto/functions.rs @@ -4,6 +4,9 @@ // DO NOT EDIT use crate::EncodingTarget; +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +use crate::PbUtilsCapsDescriptionFlags; use glib::translate::*; use std::mem; @@ -23,12 +26,17 @@ pub fn encoding_list_available_categories() -> Vec { unsafe { FromGlibPtrContainer::from_glib_full(ffi::gst_encoding_list_available_categories()) } } -//#[cfg(any(feature = "v1_20", feature = "dox"))] -//#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] -//#[doc(alias = "gst_pb_utils_get_caps_description_flags")] -//pub fn pb_utils_get_caps_description_flags(caps: &gst::Caps) -> /*Ignored*/PbUtilsCapsDescriptionFlags { -// unsafe { TODO: call ffi:gst_pb_utils_get_caps_description_flags() } -//} +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +#[doc(alias = "gst_pb_utils_get_caps_description_flags")] +pub fn pb_utils_get_caps_description_flags(caps: &gst::Caps) -> PbUtilsCapsDescriptionFlags { + assert_initialized_main_thread!(); + unsafe { + from_glib(ffi::gst_pb_utils_get_caps_description_flags( + caps.to_glib_none().0, + )) + } +} #[doc(alias = "gst_pb_utils_get_element_description")] pub fn pb_utils_get_element_description( diff --git a/gstreamer-pbutils/src/auto/mod.rs b/gstreamer-pbutils/src/auto/mod.rs index 36013de50..26e227276 100644 --- a/gstreamer-pbutils/src/auto/mod.rs +++ b/gstreamer-pbutils/src/auto/mod.rs @@ -44,6 +44,9 @@ pub use self::enums::DiscovererResult; mod flags; pub use self::flags::DiscovererSerializeFlags; +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +pub use self::flags::PbUtilsCapsDescriptionFlags; pub mod functions; diff --git a/gstreamer-rtp/src/rtp_buffer.rs b/gstreamer-rtp/src/rtp_buffer.rs index c870c8b13..5ac8255e7 100644 --- a/gstreamer-rtp/src/rtp_buffer.rs +++ b/gstreamer-rtp/src/rtp_buffer.rs @@ -175,6 +175,15 @@ impl<'a> RTPBuffer<'a, Writable> { } } } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_rtp_buffer_remove_extension_data")] + pub fn remove_extension_data(&mut self) { + unsafe { + ffi::gst_rtp_buffer_remove_extension_data(&mut self.rtp_buffer); + } + } } impl<'a, T> RTPBuffer<'a, T> { diff --git a/gstreamer-rtp/src/rtp_header_extension.rs b/gstreamer-rtp/src/rtp_header_extension.rs index 12ebd8ba1..4d0d135f6 100644 --- a/gstreamer-rtp/src/rtp_header_extension.rs +++ b/gstreamer-rtp/src/rtp_header_extension.rs @@ -19,7 +19,7 @@ pub trait RTPHeaderExtensionExtManual: 'static { write_flags: RTPHeaderExtensionFlags, output: &mut gst::BufferRef, data: &mut [u8], - ) -> usize; + ) -> Result; } impl> RTPHeaderExtensionExtManual for O { @@ -47,17 +47,23 @@ impl> RTPHeaderExtensionExtManual for O { write_flags: RTPHeaderExtensionFlags, output: &mut gst::BufferRef, data: &mut [u8], - ) -> usize { + ) -> Result { let size = data.len() as usize; unsafe { - ffi::gst_rtp_header_extension_write( + let res = ffi::gst_rtp_header_extension_write( self.as_ref().to_glib_none().0, input_meta.to_glib_none().0, write_flags.into_glib(), output.as_mut_ptr(), data.to_glib_none().0, size, - ) + ); + + if res < 0 { + Err(glib::bool_error!("Failed to write header extension")) + } else { + Ok(res as usize) + } } } } diff --git a/gstreamer-video/Gir.toml b/gstreamer-video/Gir.toml index 2532a4ec5..86ef48d81 100644 --- a/gstreamer-video/Gir.toml +++ b/gstreamer-video/Gir.toml @@ -156,6 +156,26 @@ manual_traits = ["VideoDecoderExtManual"] name = "drop_frame" manual = true + [[object.function]] + name = "finish_subframe" + manual = true + + [[object.function]] + name = "drop_subframe" + manual = true + + [[object.function]] + name = "have_last_subframe" + manual = true + + [[object.function]] + name = "get_processed_subframe_index" + manual = true + + [[object.function]] + name = "get_input_subframe_index" + manual = true + [[object.function]] name = "set_latency" manual = true diff --git a/gstreamer-video/src/auto/video_decoder.rs b/gstreamer-video/src/auto/video_decoder.rs index c79068e0c..4fbf66ba2 100644 --- a/gstreamer-video/src/auto/video_decoder.rs +++ b/gstreamer-video/src/auto/video_decoder.rs @@ -52,16 +52,6 @@ pub trait VideoDecoderExt: 'static { #[doc(alias = "gst_video_decoder_allocate_output_buffer")] fn allocate_output_buffer(&self) -> Result; - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_video_decoder_drop_subframe")] - fn drop_subframe(&self, frame: &VideoCodecFrame) -> gst::FlowReturn; - - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_video_decoder_finish_subframe")] - fn finish_subframe(&self, frame: &VideoCodecFrame) -> gst::FlowReturn; - #[doc(alias = "gst_video_decoder_get_buffer_pool")] #[doc(alias = "get_buffer_pool")] fn buffer_pool(&self) -> Option; @@ -70,12 +60,6 @@ pub trait VideoDecoderExt: 'static { #[doc(alias = "get_estimate_rate")] fn estimate_rate(&self) -> i32; - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_video_decoder_get_input_subframe_index")] - #[doc(alias = "get_input_subframe_index")] - fn input_subframe_index(&self, frame: &VideoCodecFrame) -> u32; - #[doc(alias = "gst_video_decoder_get_max_decode_time")] #[doc(alias = "get_max_decode_time")] fn max_decode_time(&self, frame: &VideoCodecFrame) -> gst::ClockTimeDiff; @@ -102,12 +86,6 @@ pub trait VideoDecoderExt: 'static { #[doc(alias = "get_pending_frame_size")] fn pending_frame_size(&self) -> usize; - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_video_decoder_get_processed_subframe_index")] - #[doc(alias = "get_processed_subframe_index")] - fn processed_subframe_index(&self, frame: &VideoCodecFrame) -> u32; - #[doc(alias = "gst_video_decoder_get_qos_proportion")] #[doc(alias = "get_qos_proportion")] fn qos_proportion(&self) -> f64; @@ -121,11 +99,6 @@ pub trait VideoDecoderExt: 'static { #[doc(alias = "gst_video_decoder_have_frame")] fn have_frame(&self) -> gst::FlowReturn; - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_video_decoder_have_last_subframe")] - fn have_last_subframe(&self, frame: &VideoCodecFrame) -> gst::FlowReturn; - #[doc(alias = "gst_video_decoder_merge_tags")] fn merge_tags(&self, tags: Option<&gst::TagList>, mode: gst::TagMergeMode); @@ -236,28 +209,6 @@ impl> VideoDecoderExt for O { } } - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - fn drop_subframe(&self, frame: &VideoCodecFrame) -> gst::FlowReturn { - unsafe { - from_glib(ffi::gst_video_decoder_drop_subframe( - self.as_ref().to_glib_none().0, - frame.to_glib_full(), - )) - } - } - - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - fn finish_subframe(&self, frame: &VideoCodecFrame) -> gst::FlowReturn { - unsafe { - from_glib(ffi::gst_video_decoder_finish_subframe( - self.as_ref().to_glib_none().0, - frame.to_glib_full(), - )) - } - } - fn buffer_pool(&self) -> Option { unsafe { from_glib_full(ffi::gst_video_decoder_get_buffer_pool( @@ -270,17 +221,6 @@ impl> VideoDecoderExt for O { unsafe { ffi::gst_video_decoder_get_estimate_rate(self.as_ref().to_glib_none().0) } } - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - fn input_subframe_index(&self, frame: &VideoCodecFrame) -> u32 { - unsafe { - ffi::gst_video_decoder_get_input_subframe_index( - self.as_ref().to_glib_none().0, - frame.to_glib_none().0, - ) - } - } - fn max_decode_time(&self, frame: &VideoCodecFrame) -> gst::ClockTimeDiff { unsafe { ffi::gst_video_decoder_get_max_decode_time( @@ -324,17 +264,6 @@ impl> VideoDecoderExt for O { unsafe { ffi::gst_video_decoder_get_pending_frame_size(self.as_ref().to_glib_none().0) } } - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - fn processed_subframe_index(&self, frame: &VideoCodecFrame) -> u32 { - unsafe { - ffi::gst_video_decoder_get_processed_subframe_index( - self.as_ref().to_glib_none().0, - frame.to_glib_none().0, - ) - } - } - fn qos_proportion(&self) -> f64 { unsafe { ffi::gst_video_decoder_get_qos_proportion(self.as_ref().to_glib_none().0) } } @@ -357,17 +286,6 @@ impl> VideoDecoderExt for O { } } - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - fn have_last_subframe(&self, frame: &VideoCodecFrame) -> gst::FlowReturn { - unsafe { - from_glib(ffi::gst_video_decoder_have_last_subframe( - self.as_ref().to_glib_none().0, - frame.to_glib_none().0, - )) - } - } - fn merge_tags(&self, tags: Option<&gst::TagList>, mode: gst::TagMergeMode) { unsafe { ffi::gst_video_decoder_merge_tags( diff --git a/gstreamer-video/src/video_codec_frame.rs b/gstreamer-video/src/video_codec_frame.rs index a76334665..69ae53d7a 100644 --- a/gstreamer-video/src/video_codec_frame.rs +++ b/gstreamer-video/src/video_codec_frame.rs @@ -22,7 +22,7 @@ impl<'a> ::glib::translate::ToGlibPtr<'a, *mut ffi::GstVideoCodecFrame> for Vide } fn to_glib_full(&self) -> *mut ffi::GstVideoCodecFrame { - unimplemented!() + unsafe { ffi::gst_video_codec_frame_ref(self.frame) } } } @@ -192,6 +192,20 @@ impl<'a> VideoCodecFrame<'a> { unsafe { from_glib((*self.to_glib_none().0).deadline) } } + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_get_processed_subframe_index")] + pub fn subframes_processed(&self) -> u32 { + unsafe { (*self.to_glib_none().0).abidata.ABI.subframes_processed } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_get_input_subframe_index")] + pub fn num_subframes(&self) -> u32 { + unsafe { (*self.to_glib_none().0).abidata.ABI.num_subframes } + } + #[doc(hidden)] pub unsafe fn into_ptr(self) -> *mut ffi::GstVideoCodecFrame { let stream_lock = self.element.stream_lock(); diff --git a/gstreamer-video/src/video_decoder.rs b/gstreamer-video/src/video_decoder.rs index d9cf0be89..39f398ecd 100644 --- a/gstreamer-video/src/video_decoder.rs +++ b/gstreamer-video/src/video_decoder.rs @@ -50,6 +50,22 @@ pub trait VideoDecoderExtManual: 'static { fn release_frame(&self, frame: VideoCodecFrame); fn drop_frame(&self, frame: VideoCodecFrame) -> Result; + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_finish_subframe")] + fn finish_subframe(&self, frame: &VideoCodecFrame) -> Result; + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_drop_subframe")] + fn drop_subframe(&self, frame: &VideoCodecFrame) -> Result; + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_have_last_subframe")] + fn have_last_subframe( + &self, + frame: &VideoCodecFrame, + ) -> Result; + #[doc(alias = "get_latency")] fn latency(&self) -> (gst::ClockTime, Option); fn set_latency( @@ -352,6 +368,45 @@ impl> VideoDecoderExtManual for O { )) } } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_finish_subframe")] + fn finish_subframe(&self, frame: &VideoCodecFrame) -> Result { + unsafe { + try_from_glib(ffi::gst_video_decoder_finish_subframe( + self.as_ref().to_glib_none().0, + frame.to_glib_full(), + )) + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_drop_subframe")] + fn drop_subframe(&self, frame: &VideoCodecFrame) -> Result { + unsafe { + try_from_glib(ffi::gst_video_decoder_drop_subframe( + self.as_ref().to_glib_none().0, + frame.to_glib_full(), + )) + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_video_decoder_have_last_subframe")] + fn have_last_subframe( + &self, + frame: &VideoCodecFrame, + ) -> Result { + unsafe { + try_from_glib(ffi::gst_video_decoder_have_last_subframe( + self.as_ref().to_glib_none().0, + frame.to_glib_none().0, + )) + } + } } impl HasStreamLock for VideoDecoder { diff --git a/gstreamer-webrtc/Gir.toml b/gstreamer-webrtc/Gir.toml index a678ec7f5..3c97627cd 100644 --- a/gstreamer-webrtc/Gir.toml +++ b/gstreamer-webrtc/Gir.toml @@ -99,3 +99,8 @@ status = "generate" name = "to_string" [object.function.return] nullable = false + +[[object]] +name = "GstWebRTC.WebRTCSCTPTransport" +status = "generate" +version = "1.20" diff --git a/gstreamer-webrtc/src/auto/mod.rs b/gstreamer-webrtc/src/auto/mod.rs index 8b25da7a7..38c8fc7e6 100644 --- a/gstreamer-webrtc/src/auto/mod.rs +++ b/gstreamer-webrtc/src/auto/mod.rs @@ -25,6 +25,13 @@ pub use self::web_rtcrtp_sender::WebRTCRTPSender; mod web_rtcrtp_transceiver; pub use self::web_rtcrtp_transceiver::WebRTCRTPTransceiver; +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +mod web_rtcsctp_transport; +#[cfg(any(feature = "v1_20", feature = "dox"))] +#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] +pub use self::web_rtcsctp_transport::WebRTCSCTPTransport; + mod web_rtc_session_description; pub use self::web_rtc_session_description::WebRTCSessionDescription; diff --git a/gstreamer-webrtc/src/auto/web_rtcsctp_transport.rs b/gstreamer-webrtc/src/auto/web_rtcsctp_transport.rs new file mode 100644 index 000000000..9c5de11db --- /dev/null +++ b/gstreamer-webrtc/src/auto/web_rtcsctp_transport.rs @@ -0,0 +1,200 @@ +// 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::WebRTCDTLSTransport; +use crate::WebRTCSCTPTransportState; +use glib::object::ObjectType as ObjectType_; +use glib::signal::connect_raw; +use glib::signal::SignalHandlerId; +use glib::translate::*; +use glib::StaticType; +use std::boxed::Box as Box_; +use std::mem::transmute; + +glib::wrapper! { + #[doc(alias = "GstWebRTCSCTPTransport")] + pub struct WebRTCSCTPTransport(Object); + + match fn { + type_ => || ffi::gst_webrtc_sctp_transport_get_type(), + } +} + +impl WebRTCSCTPTransport { + #[doc(alias = "max-channels")] + pub fn max_channels(&self) -> u32 { + unsafe { + let mut value = glib::Value::from_type(::static_type()); + glib::gobject_ffi::g_object_get_property( + self.as_ptr() as *mut glib::gobject_ffi::GObject, + b"max-channels\0".as_ptr() as *const _, + value.to_glib_none_mut().0, + ); + value + .get() + .expect("Return Value for property `max-channels` getter") + } + } + + #[doc(alias = "max-message-size")] + pub fn max_message_size(&self) -> u64 { + unsafe { + let mut value = glib::Value::from_type(::static_type()); + glib::gobject_ffi::g_object_get_property( + self.as_ptr() as *mut glib::gobject_ffi::GObject, + b"max-message-size\0".as_ptr() as *const _, + value.to_glib_none_mut().0, + ); + value + .get() + .expect("Return Value for property `max-message-size` getter") + } + } + + pub fn state(&self) -> WebRTCSCTPTransportState { + unsafe { + let mut value = + glib::Value::from_type(::static_type()); + glib::gobject_ffi::g_object_get_property( + self.as_ptr() as *mut glib::gobject_ffi::GObject, + b"state\0".as_ptr() as *const _, + value.to_glib_none_mut().0, + ); + value + .get() + .expect("Return Value for property `state` getter") + } + } + + pub fn transport(&self) -> Option { + unsafe { + let mut value = + glib::Value::from_type(::static_type()); + glib::gobject_ffi::g_object_get_property( + self.as_ptr() as *mut glib::gobject_ffi::GObject, + b"transport\0".as_ptr() as *const _, + value.to_glib_none_mut().0, + ); + value + .get() + .expect("Return Value for property `transport` getter") + } + } + + #[doc(alias = "max-channels")] + pub fn connect_max_channels_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_max_channels_trampoline< + F: Fn(&WebRTCSCTPTransport) + Send + Sync + 'static, + >( + this: *mut ffi::GstWebRTCSCTPTransport, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(&from_glib_borrow(this)) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::max-channels\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_max_channels_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[doc(alias = "max-message-size")] + pub fn connect_max_message_size_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_max_message_size_trampoline< + F: Fn(&WebRTCSCTPTransport) + Send + Sync + 'static, + >( + this: *mut ffi::GstWebRTCSCTPTransport, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(&from_glib_borrow(this)) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::max-message-size\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_max_message_size_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[doc(alias = "state")] + pub fn connect_state_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_state_trampoline< + F: Fn(&WebRTCSCTPTransport) + Send + Sync + 'static, + >( + this: *mut ffi::GstWebRTCSCTPTransport, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(&from_glib_borrow(this)) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::state\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_state_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } + + #[doc(alias = "transport")] + pub fn connect_transport_notify( + &self, + f: F, + ) -> SignalHandlerId { + unsafe extern "C" fn notify_transport_trampoline< + F: Fn(&WebRTCSCTPTransport) + Send + Sync + 'static, + >( + this: *mut ffi::GstWebRTCSCTPTransport, + _param_spec: glib::ffi::gpointer, + f: glib::ffi::gpointer, + ) { + let f: &F = &*(f as *const F); + f(&from_glib_borrow(this)) + } + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"notify::transport\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + notify_transport_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } +} + +unsafe impl Send for WebRTCSCTPTransport {} +unsafe impl Sync for WebRTCSCTPTransport {} diff --git a/gstreamer-webrtc/sys/Gir.toml b/gstreamer-webrtc/sys/Gir.toml index 13f0090e0..ab84b7949 100644 --- a/gstreamer-webrtc/sys/Gir.toml +++ b/gstreamer-webrtc/sys/Gir.toml @@ -17,3 +17,10 @@ external_libraries = [ [external_libraries] gstreamer_sdp="GstSdp" + +[[object]] +name = "GstWebRTC.WebRTCSCTPTransport" +status = "generate" + [[object.function]] + name = "get_type" + version = "1.20" diff --git a/gstreamer-webrtc/sys/src/lib.rs b/gstreamer-webrtc/sys/src/lib.rs index d8d9e0f7b..aa77ab86c 100644 --- a/gstreamer-webrtc/sys/src/lib.rs +++ b/gstreamer-webrtc/sys/src/lib.rs @@ -443,6 +443,8 @@ extern "C" { //========================================================================= // GstWebRTCSCTPTransport //========================================================================= + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] pub fn gst_webrtc_sctp_transport_get_type() -> GType; } diff --git a/gstreamer/Gir.toml b/gstreamer/Gir.toml index 3cc019670..1f47e2dea 100644 --- a/gstreamer/Gir.toml +++ b/gstreamer/Gir.toml @@ -1052,6 +1052,36 @@ final_type = true [object.function.return] nullable_return_is_error = "Failed to create element from factory name" + [[object.function]] + name = "create_full" + # varargs + ignore = true + + [[object.function]] + name = "create_valist" + # varargs + ignore = true + + [[object.function]] + name = "create_with_properties" + # separate name/value arrays need to be merged + manual = true + + [[object.function]] + name = "make_full" + # varargs + ignore = true + + [[object.function]] + name = "make_valist" + # varargs + ignore = true + + [[object.function]] + name = "make_with_properties" + # separate name/value arrays need to be merged + manual = true + [[object]] name = "Gst.TypeFindFactory" status = "generate" diff --git a/gstreamer/src/auto/element_factory.rs b/gstreamer/src/auto/element_factory.rs index 87125f4e8..11ddae30c 100644 --- a/gstreamer/src/auto/element_factory.rs +++ b/gstreamer/src/auto/element_factory.rs @@ -75,39 +75,6 @@ impl ElementFactory { } } - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "gst_element_factory_create_full")] - //pub fn create_full(&self, first: Option<&str>, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> Option { - // unsafe { TODO: call ffi:gst_element_factory_create_full() } - //} - - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "gst_element_factory_create_valist")] - //pub fn create_valist(&self, first: Option<&str>, properties: /*Unknown conversion*//*Unimplemented*/Unsupported) -> Option { - // unsafe { TODO: call ffi:gst_element_factory_create_valist() } - //} - - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_element_factory_create_with_properties")] - pub fn create_with_properties( - &self, - n: u32, - names: Option<&str>, - values: Option<&glib::Value>, - ) -> Option { - unsafe { - from_glib_none(ffi::gst_element_factory_create_with_properties( - self.to_glib_none().0, - n, - names.to_glib_none().0, - values.to_glib_none().0, - )) - } - } - #[doc(alias = "gst_element_factory_get_element_type")] #[doc(alias = "get_element_type")] pub fn element_type(&self) -> glib::types::Type { @@ -237,40 +204,6 @@ impl ElementFactory { .ok_or_else(|| glib::bool_error!("Failed to create element from factory name")) } } - - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "gst_element_factory_make_full")] - //pub fn make_full(factoryname: &str, first: Option<&str>, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> Option { - // unsafe { TODO: call ffi:gst_element_factory_make_full() } - //} - - //#[cfg(any(feature = "v1_20", feature = "dox"))] - //#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - //#[doc(alias = "gst_element_factory_make_valist")] - //pub fn make_valist(factoryname: &str, first: Option<&str>, properties: /*Unknown conversion*//*Unimplemented*/Unsupported) -> Option { - // unsafe { TODO: call ffi:gst_element_factory_make_valist() } - //} - - #[cfg(any(feature = "v1_20", feature = "dox"))] - #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] - #[doc(alias = "gst_element_factory_make_with_properties")] - pub fn make_with_properties( - factoryname: &str, - n: u32, - names: Option<&str>, - values: Option<&glib::Value>, - ) -> Option { - assert_initialized_main_thread!(); - unsafe { - from_glib_none(ffi::gst_element_factory_make_with_properties( - factoryname.to_glib_none().0, - n, - names.to_glib_none().0, - values.to_glib_none().0, - )) - } - } } unsafe impl Send for ElementFactory {} diff --git a/gstreamer/src/element_factory.rs b/gstreamer/src/element_factory.rs new file mode 100644 index 000000000..e4885227e --- /dev/null +++ b/gstreamer/src/element_factory.rs @@ -0,0 +1,65 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#[cfg(any(feature = "v1_20", feature = "dox"))] +use crate::Element; +use crate::ElementFactory; + +#[cfg(any(feature = "v1_20", feature = "dox"))] +use glib::prelude::*; +#[cfg(any(feature = "v1_20", feature = "dox"))] +use glib::translate::*; + +impl ElementFactory { + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_element_factory_create_with_properties")] + pub fn create_with_properties( + &self, + properties: &[(&str, &dyn ToValue)], + ) -> Result { + assert_initialized_main_thread!(); + let n = properties.len() as u32; + let names = properties.iter().map(|(name, _)| *name).collect::>(); + let values = properties + .iter() + .map(|(_, value)| value.to_value()) + .collect::>(); + + unsafe { + Option::<_>::from_glib_none(ffi::gst_element_factory_create_with_properties( + self.to_glib_none().0, + n, + names.to_glib_none().0, + values.as_ptr() as *const glib::gobject_ffi::GValue, + )) + .ok_or_else(|| glib::bool_error!("Failed to create element from factory")) + } + } + + #[cfg(any(feature = "v1_20", feature = "dox"))] + #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))] + #[doc(alias = "gst_element_factory_make_with_properties")] + pub fn make_with_properties( + factoryname: &str, + properties: &[(&str, &dyn ToValue)], + ) -> Result { + assert_initialized_main_thread!(); + let n = properties.len() as u32; + let names = properties.iter().map(|(name, _)| *name).collect::>(); + let values = properties + .iter() + .map(|(_, value)| value.to_value()) + .collect::>(); + + assert_initialized_main_thread!(); + unsafe { + Option::<_>::from_glib_none(ffi::gst_element_factory_make_with_properties( + factoryname.to_glib_none().0, + n, + names.to_glib_none().0, + values.as_ptr() as *const glib::gobject_ffi::GValue, + )) + .ok_or_else(|| glib::bool_error!("Failed to create element from factory name")) + } + } +} diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index d8439d58f..7df82a764 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -129,6 +129,7 @@ pub use promise::{Promise, PromiseError}; pub mod bus; mod element; +mod element_factory; mod bin;