From b2b8bfab52ac451c93643a1ea650cf9d4fc849c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 23 Apr 2019 19:53:10 +0300 Subject: [PATCH] Add manual implementations for various new 1.16 functions --- examples/src/bin/glupload.rs | 40 ++++++------ gstreamer-video/src/functions.rs | 2 +- gstreamer/src/caps.rs | 10 +++ gstreamer/src/event.rs | 46 ++++++++++--- gstreamer/src/message.rs | 54 ++++++++++++++++ gstreamer/src/meta.rs | 16 +++++ gstreamer/src/miniobject.rs | 29 ++++++--- gstreamer/src/query.rs | 29 +++++++++ gstreamer/src/sample.rs | 108 ++++++++++++++++++++++++++----- gstreamer/src/sample_serde.rs | 11 ++-- 10 files changed, 288 insertions(+), 57 deletions(-) diff --git a/examples/src/bin/glupload.rs b/examples/src/bin/glupload.rs index 118d694bb..7684b4aea 100644 --- a/examples/src/bin/glupload.rs +++ b/examples/src/bin/glupload.rs @@ -486,29 +486,31 @@ impl App { .new_sample(move |appsink| { let sample = appsink.pull_sample().ok_or(gst::FlowError::Eos)?; - let _buffer = sample.get_buffer().ok_or_else(|| { - gst_element_error!( - appsink, - gst::ResourceError::Failed, - ("Failed to get buffer from appsink") - ); - - gst::FlowError::Error - })?; - - let _info = sample - .get_caps() - .and_then(|caps| gst_video::VideoInfo::from_caps(caps.as_ref())) - .ok_or_else(|| { + { + let _buffer = sample.get_buffer().ok_or_else(|| { gst_element_error!( appsink, gst::ResourceError::Failed, - ("Failed to get video info from sample") + ("Failed to get buffer from appsink") ); gst::FlowError::Error })?; + let _info = sample + .get_caps() + .and_then(|caps| gst_video::VideoInfo::from_caps(caps)) + .ok_or_else(|| { + gst_element_error!( + appsink, + gst::ResourceError::Failed, + ("Failed to get video info from sample") + ); + + gst::FlowError::Error + })?; + } + sender_clone .lock() .unwrap() @@ -638,7 +640,7 @@ fn main_loop(mut app: App) -> Result<(), Error> { let buffer = sample.get_buffer().unwrap(); let info = sample .get_caps() - .and_then(|caps| gst_video::VideoInfo::from_caps(caps.as_ref())) + .and_then(|caps| gst_video::VideoInfo::from_caps(caps)) .unwrap(); { @@ -650,11 +652,13 @@ fn main_loop(mut app: App) -> Result<(), Error> { .get::(); } - let sync_meta = buffer.as_ref().get_meta::().unwrap(); + let sync_meta = buffer.get_meta::().unwrap(); sync_meta.set_sync_point(gst_gl_context.as_ref().unwrap()); } - if let Ok(frame) = gst_video::VideoFrame::from_buffer_readable_gl(buffer, &info) { + if let Ok(frame) = + gst_video::VideoFrame::from_buffer_readable_gl(buffer.to_owned(), &info) + { curr_frame = Some(Arc::new(frame)); } } diff --git a/gstreamer-video/src/functions.rs b/gstreamer-video/src/functions.rs index 2c8b972a5..189c5fcd7 100644 --- a/gstreamer-video/src/functions.rs +++ b/gstreamer-video/src/functions.rs @@ -165,7 +165,7 @@ mod tests { let res = res.unwrap(); let converted_out_caps = res.get_caps().unwrap(); - assert_eq!(out_caps, converted_out_caps); + assert_eq!(out_caps.as_ref(), converted_out_caps); let out_buffer = res.get_buffer().unwrap(); { let data = out_buffer.map_readable().unwrap(); diff --git a/gstreamer/src/caps.rs b/gstreamer/src/caps.rs index 4e175b3bc..d0cf154e9 100644 --- a/gstreamer/src/caps.rs +++ b/gstreamer/src/caps.rs @@ -208,6 +208,16 @@ impl CapsRef { } } + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_features_simple(&mut self, features: Option) { + unsafe { + gst_sys::gst_caps_set_features_simple( + self.as_mut_ptr(), + features.map(|f| f.into_ptr()).unwrap_or(ptr::null_mut()), + ) + } + } + pub fn get_size(&self) -> u32 { unsafe { gst_sys::gst_caps_get_size(self.as_ptr()) } } diff --git a/gstreamer/src/event.rs b/gstreamer/src/event.rs index 287fc8dd0..80aaefcc2 100644 --- a/gstreamer/src/event.rs +++ b/gstreamer/src/event.rs @@ -796,6 +796,20 @@ impl<'a> Seek<'a> { ) } } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn get_trickmode_interval(&self) -> ::ClockTime { + unsafe { + let mut trickmode_interval = mem::uninitialized(); + + gst_sys::gst_event_parse_seek_trickmode_interval( + self.as_mut_ptr(), + &mut trickmode_interval, + ); + + from_glib(trickmode_interval) + } + } } declare_concrete_event!(Navigation); @@ -1329,6 +1343,8 @@ pub struct SeekBuilder<'a> { start: GenericFormattedValue, stop_type: ::SeekType, stop: GenericFormattedValue, + #[allow(unused)] + trickmode_interval: Option<::ClockTime>, } impl<'a> SeekBuilder<'a> { fn new( @@ -1348,18 +1364,30 @@ impl<'a> SeekBuilder<'a> { start, stop_type, stop, + trickmode_interval: None, } } - event_builder_generic_impl!(|s: &Self| gst_sys::gst_event_new_seek( - s.rate, - s.start.get_format().to_glib(), - s.flags.to_glib(), - s.start_type.to_glib(), - s.start.get_value(), - s.stop_type.to_glib(), - s.stop.get_value(), - )); + event_builder_generic_impl!(|s: &Self| { + let ev = gst_sys::gst_event_new_seek( + s.rate, + s.start.get_format().to_glib(), + s.flags.to_glib(), + s.start_type.to_glib(), + s.start.get_value(), + s.stop_type.to_glib(), + s.stop.get_value(), + ); + + #[cfg(any(feature = "v1_16", feature = "dox"))] + { + if let Some(trickmode_interval) = s.trickmode_interval { + gst_sys::gst_event_set_seek_trickmode_interval(ev, trickmode_interval.to_glib()); + } + } + + ev + }); } pub struct NavigationBuilder<'a> { diff --git a/gstreamer/src/message.rs b/gstreamer/src/message.rs index 4743ccb21..f2452cfbd 100644 --- a/gstreamer/src/message.rs +++ b/gstreamer/src/message.rs @@ -102,6 +102,7 @@ impl MessageRef { gst_sys::GST_MESSAGE_STREAMS_SELECTED => { MessageView::StreamsSelected(StreamsSelected(self)) } + gst_sys::GST_MESSAGE_DEVICE_CHANGED => MessageView::DeviceChanged(DeviceChanged(self)), _ => MessageView::Other, } } @@ -340,6 +341,15 @@ impl Message { assert_initialized_main_thread!(); RedirectBuilder::new(location) } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn new_device_changed<'a>( + device: &'a ::Device, + changed_device: &'a ::Device, + ) -> DeviceChangedBuilder<'a> { + assert_initialized_main_thread!(); + DeviceChangedBuilder::new(device, changed_device) + } } impl fmt::Debug for MessageRef { @@ -396,6 +406,7 @@ pub enum MessageView<'a> { StreamCollection(StreamCollection<'a>), StreamsSelected(StreamsSelected<'a>), Redirect(Redirect<'a>), + DeviceChanged(DeviceChanged<'a>), Other, __NonExhaustive, } @@ -1153,6 +1164,25 @@ impl<'a> Redirect<'a> { } } +declare_concrete_message!(DeviceChanged); +impl<'a> DeviceChanged<'a> { + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn get_device_changed(&self) -> (::Device, ::Device) { + unsafe { + let mut device = ptr::null_mut(); + let mut changed_device = ptr::null_mut(); + + gst_sys::gst_message_parse_device_changed( + self.as_mut_ptr(), + &mut device, + &mut changed_device, + ); + + (from_glib_full(device), from_glib_full(changed_device)) + } + } +} + struct MessageBuilder<'a> { src: Option, seqnum: Option, @@ -2365,6 +2395,30 @@ impl<'a> RedirectBuilder<'a> { }); } +#[cfg(any(feature = "v1_16", feature = "dox"))] +pub struct DeviceChangedBuilder<'a> { + builder: MessageBuilder<'a>, + device: &'a ::Device, + changed_device: &'a ::Device, +} +#[cfg(any(feature = "v1_16", feature = "dox"))] +impl<'a> DeviceChangedBuilder<'a> { + fn new(device: &'a ::Device, changed_device: &'a ::Device) -> Self { + skip_assert_initialized!(); + Self { + builder: MessageBuilder::new(), + device, + changed_device, + } + } + + message_builder_generic_impl!(|s: &mut Self, src| gst_sys::gst_message_new_device_changed( + src, + s.device.to_glib_none().0, + s.changed_device.to_glib_none().0, + )); +} + #[cfg(test)] mod tests { use super::*; diff --git a/gstreamer/src/meta.rs b/gstreamer/src/meta.rs index 10f0507cd..40861c7c9 100644 --- a/gstreamer/src/meta.rs +++ b/gstreamer/src/meta.rs @@ -121,6 +121,14 @@ impl<'a, T: MetaAPI> MetaRef<'a, T> { } } + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn get_seqnum(&self) -> u64 { + unsafe { + let meta = self.meta as *const _ as *const gst_sys::GstMeta; + gst_sys::gst_meta_get_seqnum(meta) + } + } + pub fn as_ptr(&self) -> *const T::GstType { self.meta as *const _ as *const ::GstType } @@ -148,6 +156,14 @@ impl<'a, T: MetaAPI, U> MetaRefMut<'a, T, U> { } } + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn get_seqnum(&self) -> u64 { + unsafe { + let meta = self.meta as *const _ as *const gst_sys::GstMeta; + gst_sys::gst_meta_get_seqnum(meta) + } + } + pub fn as_ptr(&self) -> *const T::GstType { self.meta as *const _ as *const ::GstType } diff --git a/gstreamer/src/miniobject.rs b/gstreamer/src/miniobject.rs index 1a6e3e93d..0ea4bca72 100644 --- a/gstreamer/src/miniobject.rs +++ b/gstreamer/src/miniobject.rs @@ -99,6 +99,26 @@ impl GstRc { ptr } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn add_parent(&self, parent: &U) { + unsafe { + gst_sys::gst_mini_object_add_parent( + self.as_ptr() as *mut gst_sys::GstMiniObject, + parent.as_ptr() as *mut gst_sys::GstMiniObject, + ); + } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn remove_parent(&self, parent: &U) { + unsafe { + gst_sys::gst_mini_object_remove_parent( + self.as_ptr() as *mut gst_sys::GstMiniObject, + parent.as_ptr() as *mut gst_sys::GstMiniObject, + ); + } + } } impl ops::Deref for GstRc { @@ -120,15 +140,6 @@ impl borrow::Borrow for GstRc { } } -// FIXME: Not generally possible because neither T nor ToOwned are defined here... -//impl ToOwned for T { -// type Owned = GstRc; -// -// fn to_owned(&self) -> GstRc { -// unsafe { GstRc::from_unowned_ptr(self.as_ptr()) } -// } -//} - impl Clone for GstRc { fn clone(&self) -> GstRc { unsafe { GstRc::from_glib_none(self.as_ptr()) } diff --git a/gstreamer/src/query.rs b/gstreamer/src/query.rs index 90e2f0c20..41dbc306d 100644 --- a/gstreamer/src/query.rs +++ b/gstreamer/src/query.rs @@ -158,6 +158,12 @@ impl Query { ))) } } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn new_bitrate() -> Bitrate { + assert_initialized_main_thread!(); + unsafe { Bitrate::(from_glib_full(gst_sys::gst_query_new_bitrate())) } + } } impl QueryRef { @@ -213,6 +219,7 @@ impl QueryRef { gst_sys::GST_QUERY_CAPS => QueryView::Caps(Caps(self)), gst_sys::GST_QUERY_DRAIN => QueryView::Drain(Drain(self)), gst_sys::GST_QUERY_CONTEXT => QueryView::Context(Context(self)), + gst_sys::GST_QUERY_BITRATE => QueryView::Bitrate(Bitrate(self)), _ => QueryView::Other(Other(self)), } } @@ -293,6 +300,7 @@ pub enum QueryView { Caps(Caps), Drain(Drain), Context(Context), + Bitrate(Bitrate), Other(Other), __NonExhaustive, } @@ -1218,6 +1226,27 @@ impl Context { } } +declare_concrete_query!(Bitrate, T); +impl Bitrate { + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn get_bitrate(&self) -> u32 { + unsafe { + let mut bitrate = 0; + gst_sys::gst_query_parse_bitrate(self.0.as_ptr(), &mut bitrate); + bitrate + } + } +} + +impl Bitrate { + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_bitrate(&mut self, bitrate: u32) { + unsafe { + gst_sys::gst_query_set_bitrate(self.0.as_mut_ptr(), bitrate); + } + } +} + declare_concrete_query!(Other, T); #[cfg(test)] diff --git a/gstreamer/src/sample.rs b/gstreamer/src/sample.rs index a076a7177..13942532c 100644 --- a/gstreamer/src/sample.rs +++ b/gstreamer/src/sample.rs @@ -15,9 +15,9 @@ use glib; use glib::translate::{from_glib_full, from_glib_none, mut_override, ToGlibPtr}; use miniobject::*; -use Buffer; -use BufferList; -use Caps; +use BufferListRef; +use BufferRef; +use CapsRef; use FormattedSegment; use FormattedValue; use Segment; @@ -30,8 +30,8 @@ gst_define_mini_object_wrapper!(Sample, SampleRef, gst_sys::GstSample, [Debug,], impl Sample { pub fn new( - buffer: Option<&Buffer>, - caps: Option<&Caps>, + buffer: Option<&BufferRef>, + caps: Option<&CapsRef>, segment: Option<&FormattedSegment>, info: Option, ) -> Self { @@ -40,8 +40,11 @@ impl Sample { let info = info.map(|i| i.into_ptr()).unwrap_or(ptr::null_mut()); from_glib_full(gst_sys::gst_sample_new( - buffer.to_glib_none().0, - caps.to_glib_none().0, + buffer + .map(|buffer| buffer.as_mut_ptr()) + .unwrap_or(ptr::null_mut()), + caps.map(|caps| caps.as_mut_ptr()) + .unwrap_or(ptr::null_mut()), segment.to_glib_none().0, mut_override(info), )) @@ -49,8 +52,8 @@ impl Sample { } pub fn with_buffer_list( - buffer_list: Option<&BufferList>, - caps: Option<&Caps>, + buffer_list: Option<&BufferListRef>, + caps: Option<&CapsRef>, segment: Option<&FormattedSegment>, info: Option, ) -> Self { @@ -59,7 +62,9 @@ impl Sample { unsafe { gst_sys::gst_sample_set_buffer_list( sample.to_glib_none().0, - buffer_list.to_glib_none().0, + buffer_list + .map(|buffer_list| buffer_list.as_mut_ptr()) + .unwrap_or(ptr::null_mut()), ); } sample @@ -67,16 +72,37 @@ impl Sample { } impl SampleRef { - pub fn get_buffer(&self) -> Option { - unsafe { from_glib_none(gst_sys::gst_sample_get_buffer(self.as_mut_ptr())) } + pub fn get_buffer(&self) -> Option<&BufferRef> { + unsafe { + let ptr = gst_sys::gst_sample_get_buffer(self.as_mut_ptr()); + if ptr.is_null() { + None + } else { + Some(BufferRef::from_ptr(ptr)) + } + } } - pub fn get_buffer_list(&self) -> Option { - unsafe { from_glib_none(gst_sys::gst_sample_get_buffer_list(self.as_mut_ptr())) } + pub fn get_buffer_list(&self) -> Option<&BufferListRef> { + unsafe { + let ptr = gst_sys::gst_sample_get_buffer_list(self.as_mut_ptr()); + if ptr.is_null() { + None + } else { + Some(BufferListRef::from_ptr(ptr)) + } + } } - pub fn get_caps(&self) -> Option { - unsafe { from_glib_none(gst_sys::gst_sample_get_caps(self.as_mut_ptr())) } + pub fn get_caps(&self) -> Option<&CapsRef> { + unsafe { + let ptr = gst_sys::gst_sample_get_caps(self.as_mut_ptr()); + if ptr.is_null() { + None + } else { + Some(CapsRef::from_ptr(ptr)) + } + } } pub fn get_segment(&self) -> Option { @@ -93,6 +119,56 @@ impl SampleRef { } } } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_buffer(&mut self, buffer: Option<&BufferRef>) { + unsafe { + gst_sys::gst_sample_set_buffer( + self.as_mut_ptr(), + buffer + .map(|buffer| buffer.as_mut_ptr()) + .unwrap_or(ptr::null_mut()), + ) + } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_buffer_list(&mut self, buffer_list: Option<&BufferListRef>) { + unsafe { + gst_sys::gst_sample_set_buffer_list( + self.as_mut_ptr(), + buffer_list + .map(|buffer_list| buffer_list.as_mut_ptr()) + .unwrap_or(ptr::null_mut()), + ) + } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_caps(&mut self, caps: Option<&CapsRef>) { + unsafe { + gst_sys::gst_sample_set_caps( + self.as_mut_ptr(), + caps.map(|caps| caps.as_mut_ptr()) + .unwrap_or(ptr::null_mut()), + ) + } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_segment(&mut self, segment: &Option<&Segment>) { + unsafe { gst_sys::gst_sample_set_segment(self.as_mut_ptr(), segment.to_glib_none().0) } + } + + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn set_info(&mut self, info: Option) { + unsafe { + gst_sys::gst_sample_set_info( + self.as_mut_ptr(), + info.map(|i| i.into_ptr()).unwrap_or(ptr::null_mut()), + ); + } + } } impl fmt::Debug for SampleRef { diff --git a/gstreamer/src/sample_serde.rs b/gstreamer/src/sample_serde.rs index 1fe5953ef..54b23f3d8 100644 --- a/gstreamer/src/sample_serde.rs +++ b/gstreamer/src/sample_serde.rs @@ -49,15 +49,18 @@ impl From for Sample { fn from(mut buf_de: SampleDe) -> Self { if buf_de.buffer.is_some() { Sample::new::( - buf_de.buffer.as_ref(), - buf_de.caps.as_ref(), + buf_de.buffer.as_ref().map(|buffer| buffer.as_ref()), + buf_de.caps.as_ref().map(|caps| caps.as_ref()), buf_de.segment.as_ref(), buf_de.info.take(), ) } else { Sample::with_buffer_list::( - buf_de.buffer_list.as_ref(), - buf_de.caps.as_ref(), + buf_de + .buffer_list + .as_ref() + .map(|buffer_list| buffer_list.as_ref()), + buf_de.caps.as_ref().map(|caps| caps.as_ref()), buf_de.segment.as_ref(), buf_de.info.take(), )