From dfe87cf5c9132ad5fb8bb8965933ad12440b8a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 11 Aug 2020 10:04:09 +0300 Subject: [PATCH] Add various new 1.18 APIs --- gstreamer-base/src/aggregator.rs | 142 ++++++++++++++++++++++ gstreamer-base/src/base_src.rs | 19 +++ gstreamer-base/src/subclass/aggregator.rs | 106 ++++++++++++++++ gstreamer-video/src/video_info.rs | 105 ++++++++++++++++ 4 files changed, 372 insertions(+) diff --git a/gstreamer-base/src/aggregator.rs b/gstreamer-base/src/aggregator.rs index eeba1b34c..38fadf4e4 100644 --- a/gstreamer-base/src/aggregator.rs +++ b/gstreamer-base/src/aggregator.rs @@ -28,6 +28,13 @@ pub trait AggregatorExtManual: 'static { fn get_allocator(&self) -> (Option, gst::AllocationParams); fn finish_buffer(&self, buffer: gst::Buffer) -> Result; + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn finish_buffer_list( + &self, + bufferlist: gst::BufferList, + ) -> Result; + #[cfg(any(feature = "v1_16", feature = "dox"))] fn get_property_min_upstream_latency(&self) -> gst::ClockTime; @@ -42,6 +49,35 @@ pub trait AggregatorExtManual: 'static { #[cfg(any(feature = "v1_18", feature = "dox"))] fn update_segment(&self, segment: &gst::FormattedSegment); + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn selected_samples( + &self, + pts: gst::ClockTime, + dts: gst::ClockTime, + duration: gst::ClockTime, + info: Option<&gst::StructureRef>, + ); + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn connect_samples_selected< + P, + F: Fn( + &P, + &gst::Segment, + gst::ClockTime, + gst::ClockTime, + gst::ClockTime, + Option<&gst::StructureRef>, + ) + Send + + Sync + + 'static, + >( + &self, + f: F, + ) -> SignalHandlerId + where + P: IsA; } impl> AggregatorExtManual for O { @@ -68,6 +104,20 @@ impl> AggregatorExtManual for O { ret.into_result() } + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn finish_buffer_list( + &self, + bufferlist: gst::BufferList, + ) -> Result { + let ret: gst::FlowReturn = unsafe { + from_glib(gst_base_sys::gst_aggregator_finish_buffer_list( + self.as_ref().to_glib_none().0, + bufferlist.into_ptr(), + )) + }; + ret.into_result() + } + #[cfg(any(feature = "v1_16", feature = "dox"))] fn get_property_min_upstream_latency(&self) -> gst::ClockTime { unsafe { @@ -121,6 +171,98 @@ impl> AggregatorExtManual for O { ) } } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn selected_samples( + &self, + pts: gst::ClockTime, + dts: gst::ClockTime, + duration: gst::ClockTime, + info: Option<&gst::StructureRef>, + ) { + unsafe { + gst_base_sys::gst_aggregator_selected_samples( + self.as_ref().to_glib_none().0, + pts.to_glib(), + dts.to_glib(), + duration.to_glib(), + info.as_ref() + .map(|s| s.as_ptr() as *mut _) + .unwrap_or(ptr::null_mut()), + ); + } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn connect_samples_selected< + P, + F: Fn( + &P, + &gst::Segment, + gst::ClockTime, + gst::ClockTime, + gst::ClockTime, + Option<&gst::StructureRef>, + ) + Send + + Sync + + 'static, + >( + &self, + f: F, + ) -> SignalHandlerId + where + P: IsA, + { + unsafe extern "C" fn samples_selected_trampoline< + P, + F: Fn( + &P, + &gst::Segment, + gst::ClockTime, + gst::ClockTime, + gst::ClockTime, + Option<&gst::StructureRef>, + ) + Send + + Sync + + 'static, + >( + this: *mut gst_base_sys::GstAggregator, + segment: *mut gst_sys::GstSegment, + pts: gst_sys::GstClockTime, + dts: gst_sys::GstClockTime, + duration: gst_sys::GstClockTime, + info: *mut gst_sys::GstStructure, + f: glib_sys::gpointer, + ) where + P: IsA, + { + let f: &F = &*(f as *const F); + f( + &Aggregator::from_glib_borrow(this).unsafe_cast_ref(), + &gst::Segment::from_glib_borrow(segment), + from_glib(pts), + from_glib(dts), + from_glib(duration), + if info.is_null() { + None + } else { + Some(gst::StructureRef::from_glib_borrow(info)) + }, + ) + } + + unsafe { + let f: Box_ = Box_::new(f); + connect_raw( + self.as_ptr() as *mut _, + b"samples-selected\0".as_ptr() as *const _, + Some(transmute::<_, unsafe extern "C" fn()>( + samples_selected_trampoline:: as *const (), + )), + Box_::into_raw(f), + ) + } + } } #[cfg(any(feature = "v1_16", feature = "dox"))] diff --git a/gstreamer-base/src/base_src.rs b/gstreamer-base/src/base_src.rs index 791daba43..71fa4cdc8 100644 --- a/gstreamer-base/src/base_src.rs +++ b/gstreamer-base/src/base_src.rs @@ -27,6 +27,9 @@ pub trait BaseSrcExtManual: 'static { fn wait_playing(&self) -> Result; fn query_latency(&self) -> Result<(bool, gst::ClockTime, gst::ClockTime), glib::BoolError>; + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn new_segment(&self, segment: &gst::Segment) -> Result<(), glib::BoolError>; } impl> BaseSrcExtManual for O { @@ -104,4 +107,20 @@ impl> BaseSrcExtManual for O { } } } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn new_segment(&self, segment: &gst::Segment) -> Result<(), glib::BoolError> { + unsafe { + let ret = from_glib(gst_base_sys::gst_base_src_new_segment( + self.as_ref().to_glib_none().0, + segment.to_glib_none().0, + )); + + if ret { + Ok(()) + } else { + Err(glib_bool_error!("Failed to configure new segment")) + } + } + } } diff --git a/gstreamer-base/src/subclass/aggregator.rs b/gstreamer-base/src/subclass/aggregator.rs index 10f202b42..7dcf758aa 100644 --- a/gstreamer-base/src/subclass/aggregator.rs +++ b/gstreamer-base/src/subclass/aggregator.rs @@ -38,6 +38,15 @@ pub trait AggregatorImpl: AggregatorImplExt + ElementImpl { self.parent_clip(aggregator, aggregator_pad, buffer) } + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn finish_buffer_list( + &self, + aggregator: &Aggregator, + buffer_list: gst::BufferList, + ) -> Result { + self.parent_finish_buffer_list(aggregator, buffer_list) + } + fn finish_buffer( &self, aggregator: &Aggregator, @@ -155,6 +164,15 @@ pub trait AggregatorImpl: AggregatorImplExt + ElementImpl { fn negotiate(&self, aggregator: &Aggregator) -> bool { self.parent_negotiate(aggregator) } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn peek_next_sample( + &self, + aggregator: &Aggregator, + pad: &AggregatorPad, + ) -> Option { + self.parent_peek_next_sample(aggregator, pad) + } } pub trait AggregatorImplExt { @@ -173,6 +191,13 @@ pub trait AggregatorImplExt { buffer: gst::Buffer, ) -> Result; + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn parent_finish_buffer_list( + &self, + aggregator: &Aggregator, + buffer_list: gst::BufferList, + ) -> Result; + fn parent_sink_event( &self, aggregator: &Aggregator, @@ -250,6 +275,13 @@ pub trait AggregatorImplExt { #[cfg(any(feature = "v1_18", feature = "dox"))] fn parent_negotiate(&self, aggregator: &Aggregator) -> bool; + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn parent_peek_next_sample( + &self, + aggregator: &Aggregator, + pad: &AggregatorPad, + ) -> Option; } impl AggregatorImplExt for T { @@ -304,6 +336,24 @@ impl AggregatorImplExt for T { } } + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn parent_finish_buffer_list( + &self, + aggregator: &Aggregator, + buffer_list: gst::BufferList, + ) -> Result { + unsafe { + let data = T::type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_base_sys::GstAggregatorClass; + let f = (*parent_class) + .finish_buffer_list + .expect("Missing parent function `finish_buffer_list`"); + gst::FlowReturn::from_glib(f(aggregator.to_glib_none().0, buffer_list.into_ptr())) + .into_result() + } + } + fn parent_sink_event( &self, aggregator: &Aggregator, @@ -604,6 +654,23 @@ impl AggregatorImplExt for T { .unwrap_or(true) } } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + fn parent_peek_next_sample( + &self, + aggregator: &Aggregator, + pad: &AggregatorPad, + ) -> Option { + unsafe { + let data = T::type_data(); + let parent_class = + data.as_ref().get_parent_class() as *mut gst_base_sys::GstAggregatorClass; + (*parent_class) + .peek_next_sample + .map(|f| from_glib_full(f(aggregator.to_glib_none().0, pad.to_glib_none().0))) + .unwrap_or(None) + } + } } unsafe impl IsSubclassable for AggregatorClass @@ -635,6 +702,8 @@ where klass.sink_event_pre_queue = Some(aggregator_sink_event_pre_queue::); klass.sink_query_pre_queue = Some(aggregator_sink_query_pre_queue::); klass.negotiate = Some(aggregator_negotiate::); + klass.peek_next_sample = Some(aggregator_peek_next_sample::); + klass.finish_buffer_list = Some(aggregator_finish_buffer_list::); } } } @@ -696,6 +765,25 @@ where .to_glib() } +#[cfg(any(feature = "v1_18", feature = "dox"))] +unsafe extern "C" fn aggregator_finish_buffer_list( + ptr: *mut gst_base_sys::GstAggregator, + buffer_list: *mut gst_sys::GstBufferList, +) -> gst_sys::GstFlowReturn +where + T::Instance: PanicPoison, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), gst::FlowReturn::Error, { + imp.finish_buffer_list(&wrap, from_glib_full(buffer_list)) + .into() + }) + .to_glib() +} + unsafe extern "C" fn aggregator_sink_event( ptr: *mut gst_base_sys::GstAggregator, aggregator_pad: *mut gst_base_sys::GstAggregatorPad, @@ -1029,3 +1117,21 @@ where gst_panic_to_error!(&wrap, &instance.panicked(), false, { imp.negotiate(&wrap) }).to_glib() } + +#[cfg(any(feature = "v1_18", feature = "dox"))] +unsafe extern "C" fn aggregator_peek_next_sample( + ptr: *mut gst_base_sys::GstAggregator, + pad: *mut gst_base_sys::GstAggregatorPad, +) -> *mut gst_sys::GstSample +where + T::Instance: PanicPoison, +{ + let instance = &*(ptr as *mut T::Instance); + let imp = instance.get_impl(); + let wrap: Borrowed = from_glib_borrow(ptr); + + gst_panic_to_error!(&wrap, &instance.panicked(), None, { + imp.peek_next_sample(&wrap, &from_glib_borrow(pad)) + }) + .to_glib_full() +} diff --git a/gstreamer-video/src/video_info.rs b/gstreamer-video/src/video_info.rs index eceed8eb1..180579978 100644 --- a/gstreamer-video/src/video_info.rs +++ b/gstreamer-video/src/video_info.rs @@ -187,6 +187,111 @@ impl fmt::Display for ::VideoColorimetry { } } +impl str::FromStr for ::VideoChromaSite { + type Err = glib::error::BoolError; + + fn from_str(s: &str) -> Result { + assert_initialized_main_thread!(); + + unsafe { + let chroma_site = from_glib(gst_video_sys::gst_video_chroma_from_string( + s.to_glib_none().0, + )); + if chroma_site == ::VideoChromaSite::empty() { + Err(glib_bool_error!("Invalid chroma site")) + } else { + Ok(chroma_site) + } + } + } +} + +impl fmt::Display for ::VideoChromaSite { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + let s = unsafe { + glib::GString::from_glib_full(gst_video_sys::gst_video_chroma_to_string(self.to_glib())) + }; + f.write_str(&s) + } +} + +impl ::VideoTransferFunction { + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn from_iso(iso: u32) -> Result<::VideoTransferFunction, glib::BoolError> { + assert_initialized_main_thread!(); + + unsafe { + let value = from_glib(gst_video_sys::gst_video_color_transfer_from_iso(iso)); + match value { + ::VideoTransferFunction::__Unknown(_) => Err(glib_bool_error!("Invalid ISO value")), + _ => Ok(value), + } + } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn to_iso(&self) -> u32 { + unsafe { gst_video_sys::gst_video_color_transfer_to_iso(self.to_glib()) } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn is_equivalent( + &self, + from_bpp: u32, + to_func: ::VideoTransferFunction, + to_bpp: u32, + ) -> bool { + unsafe { + from_glib(gst_video_sys::gst_video_color_transfer_is_equivalent( + self.to_glib(), + from_bpp, + to_func.to_glib(), + to_bpp, + )) + } + } +} + +impl ::VideoColorMatrix { + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn from_iso(iso: u32) -> Result<::VideoColorMatrix, glib::BoolError> { + assert_initialized_main_thread!(); + + unsafe { + let value = from_glib(gst_video_sys::gst_video_color_matrix_from_iso(iso)); + match value { + ::VideoColorMatrix::__Unknown(_) => Err(glib_bool_error!("Invalid ISO value")), + _ => Ok(value), + } + } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn to_iso(&self) -> u32 { + unsafe { gst_video_sys::gst_video_color_matrix_to_iso(self.to_glib()) } + } +} + +impl ::VideoColorPrimaries { + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn from_iso(iso: u32) -> Result<::VideoColorPrimaries, glib::BoolError> { + assert_initialized_main_thread!(); + + unsafe { + let value = from_glib(gst_video_sys::gst_video_color_primaries_from_iso(iso)); + match value { + ::VideoColorPrimaries::__Unknown(_) => Err(glib_bool_error!("Invalid ISO value")), + _ => Ok(value), + } + } + } + + #[cfg(any(feature = "v1_18", feature = "dox"))] + pub fn to_iso(&self) -> u32 { + unsafe { gst_video_sys::gst_video_color_primaries_to_iso(self.to_glib()) } + } +} + impl From<::VideoMultiviewFramePacking> for ::VideoMultiviewMode { fn from(v: ::VideoMultiviewFramePacking) -> Self { skip_assert_initialized!();