From 04e6c1b547ac94942d2d314fb03cd3249c3e2971 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 30 May 2021 20:22:05 +0300 Subject: [PATCH] app: Remove signals bindings from appsrc/appsink for the signals that also have callbacks The callbacks are more flexible and performant. Fixes https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/issues/338 --- gstreamer-app/Gir.toml | 54 ++++++++- gstreamer-app/src/auto/app_sink.rs | 121 ------------------- gstreamer-app/src/auto/app_src.rs | 120 ------------------- tutorials/src/bin/basic-tutorial-8.rs | 164 +++++++++++++------------- 4 files changed, 136 insertions(+), 323 deletions(-) diff --git a/gstreamer-app/Gir.toml b/gstreamer-app/Gir.toml index fb238a820..8ada2494c 100644 --- a/gstreamer-app/Gir.toml +++ b/gstreamer-app/Gir.toml @@ -61,17 +61,35 @@ final_type = true # Action signal ignore = true + [[object.property]] + name = "emit-signals" + # Use callbacks instead + ignore = true + + [[object.function]] + name = "get_emit_signals" + # Use callbacks instead + ignore = true + + [[object.function]] + name = "set_emit_signals" + # Use callbacks instead + ignore = true + [[object.signal]] name = "new-sample" - concurrency = "send" + # Use callbacks instead + ignore = true [[object.signal]] name = "new-preroll" - concurrency = "send" + # Use callbacks instead + ignore = true [[object.signal]] name = "eos" - concurrency = "send" + # Use callbacks instead + ignore = true [[object.function]] name = "set_caps" @@ -124,6 +142,36 @@ final_type = true # Action signal ignore = true + [[object.property]] + name = "emit-signals" + # Use callbacks instead + ignore = true + + [[object.function]] + name = "get_emit_signals" + # Use callbacks instead + ignore = true + + [[object.function]] + name = "set_emit_signals" + # Use callbacks instead + ignore = true + + [[object.signal]] + name = "enough-data" + # Use callbacks instead + ignore = true + + [[object.signal]] + name = "need-data" + # Use callbacks instead + ignore = true + + [[object.signal]] + name = "seek-data" + # Use callbacks instead + ignore = true + [[object.function]] name = "set_latency" # ClockTime diff --git a/gstreamer-app/src/auto/app_sink.rs b/gstreamer-app/src/auto/app_sink.rs index ad336762d..3bbf09409 100644 --- a/gstreamer-app/src/auto/app_sink.rs +++ b/gstreamer-app/src/auto/app_sink.rs @@ -45,12 +45,6 @@ impl AppSink { unsafe { from_glib(ffi::gst_app_sink_get_drop(self.to_glib_none().0)) } } - #[doc(alias = "gst_app_sink_get_emit_signals")] - #[doc(alias = "get_emit_signals")] - pub fn emits_signals(&self) -> bool { - unsafe { from_glib(ffi::gst_app_sink_get_emit_signals(self.to_glib_none().0)) } - } - #[doc(alias = "gst_app_sink_get_max_buffers")] #[doc(alias = "get_max_buffers")] pub fn max_buffers(&self) -> u32 { @@ -115,13 +109,6 @@ impl AppSink { } } - #[doc(alias = "gst_app_sink_set_emit_signals")] - pub fn set_emit_signals(&self, emit: bool) { - unsafe { - ffi::gst_app_sink_set_emit_signals(self.to_glib_none().0, emit.into_glib()); - } - } - #[doc(alias = "gst_app_sink_set_max_buffers")] pub fn set_max_buffers(&self, max: u32) { unsafe { @@ -186,86 +173,6 @@ impl AppSink { } } - #[doc(alias = "eos")] - pub fn connect_eos(&self, f: F) -> SignalHandlerId { - unsafe extern "C" fn eos_trampoline( - this: *mut ffi::GstAppSink, - 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"eos\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - eos_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "new-preroll")] - pub fn connect_new_preroll< - F: Fn(&Self) -> Result + Send + 'static, - >( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn new_preroll_trampoline< - F: Fn(&AppSink) -> Result + Send + 'static, - >( - this: *mut ffi::GstAppSink, - f: glib::ffi::gpointer, - ) -> gst::ffi::GstFlowReturn { - 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-preroll\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - new_preroll_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "new-sample")] - pub fn connect_new_sample< - F: Fn(&Self) -> Result + Send + 'static, - >( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn new_sample_trampoline< - F: Fn(&AppSink) -> Result + Send + 'static, - >( - this: *mut ffi::GstAppSink, - f: glib::ffi::gpointer, - ) -> gst::ffi::GstFlowReturn { - 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-sample\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - new_sample_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - #[doc(alias = "buffer-list")] pub fn connect_buffer_list_notify( &self, @@ -346,34 +253,6 @@ impl AppSink { } } - #[doc(alias = "emit-signals")] - pub fn connect_emit_signals_notify( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn notify_emit_signals_trampoline< - F: Fn(&AppSink) + Send + Sync + 'static, - >( - this: *mut ffi::GstAppSink, - _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::emit-signals\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - notify_emit_signals_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - #[doc(alias = "eos")] pub fn connect_eos_notify( &self, diff --git a/gstreamer-app/src/auto/app_src.rs b/gstreamer-app/src/auto/app_src.rs index 7db91120a..03303241e 100644 --- a/gstreamer-app/src/auto/app_src.rs +++ b/gstreamer-app/src/auto/app_src.rs @@ -47,12 +47,6 @@ impl AppSrc { unsafe { from_glib(ffi::gst_app_src_get_duration(self.to_glib_none().0)) } } - #[doc(alias = "gst_app_src_get_emit_signals")] - #[doc(alias = "get_emit_signals")] - pub fn emits_signals(&self) -> bool { - unsafe { from_glib(ffi::gst_app_src_get_emit_signals(self.to_glib_none().0)) } - } - #[doc(alias = "gst_app_src_get_max_bytes")] #[doc(alias = "get_max_bytes")] pub fn max_bytes(&self) -> u64 { @@ -102,13 +96,6 @@ impl AppSrc { } } - #[doc(alias = "gst_app_src_set_emit_signals")] - pub fn set_emit_signals(&self, emit: bool) { - unsafe { - ffi::gst_app_src_set_emit_signals(self.to_glib_none().0, emit.into_glib()); - } - } - #[doc(alias = "gst_app_src_set_max_bytes")] pub fn set_max_bytes(&self, max: u64) { unsafe { @@ -312,85 +299,6 @@ impl AppSrc { } } - #[doc(alias = "enough-data")] - pub fn connect_enough_data( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn enough_data_trampoline( - this: *mut ffi::GstAppSrc, - 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"enough-data\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - enough_data_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "need-data")] - pub fn connect_need_data( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn need_data_trampoline( - this: *mut ffi::GstAppSrc, - length: libc::c_uint, - f: glib::ffi::gpointer, - ) { - let f: &F = &*(f as *const F); - f(&from_glib_borrow(this), length) - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"need-data\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - need_data_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - - #[doc(alias = "seek-data")] - pub fn connect_seek_data bool + Send + Sync + 'static>( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn seek_data_trampoline< - F: Fn(&AppSrc, u64) -> bool + Send + Sync + 'static, - >( - this: *mut ffi::GstAppSrc, - offset: u64, - f: glib::ffi::gpointer, - ) -> glib::ffi::gboolean { - let f: &F = &*(f as *const F); - f(&from_glib_borrow(this), offset).into_glib() - } - unsafe { - let f: Box_ = Box_::new(f); - connect_raw( - self.as_ptr() as *mut _, - b"seek-data\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - seek_data_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - #[doc(alias = "block")] pub fn connect_block_notify( &self, @@ -499,34 +407,6 @@ impl AppSrc { } } - #[doc(alias = "emit-signals")] - pub fn connect_emit_signals_notify( - &self, - f: F, - ) -> SignalHandlerId { - unsafe extern "C" fn notify_emit_signals_trampoline< - F: Fn(&AppSrc) + Send + Sync + 'static, - >( - this: *mut ffi::GstAppSrc, - _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::emit-signals\0".as_ptr() as *const _, - Some(transmute::<_, unsafe extern "C" fn()>( - notify_emit_signals_trampoline:: as *const (), - )), - Box_::into_raw(f), - ) - } - } - #[doc(alias = "format")] pub fn connect_format_notify( &self, diff --git a/tutorials/src/bin/basic-tutorial-8.rs b/tutorials/src/bin/basic-tutorial-8.rs index 034708087..14e182da1 100644 --- a/tutorials/src/bin/basic-tutorial-8.rs +++ b/tutorials/src/bin/basic-tutorial-8.rs @@ -136,105 +136,111 @@ fn main() { let data: Arc> = Arc::new(Mutex::new(CustomData::new(&appsrc, &appsink))); let data_weak = Arc::downgrade(&data); - appsrc.connect_need_data(move |_, _size| { - let data = match data_weak.upgrade() { - Some(data) => data, - None => return, - }; - let mut d = data.lock().unwrap(); - - if d.source_id.is_none() { - println!("start feeding"); - - let data_weak = Arc::downgrade(&data); - d.source_id = Some(glib::source::idle_add(move || { + let data_weak2 = Arc::downgrade(&data); + appsrc.set_callbacks( + gst_app::AppSrcCallbacks::builder() + .need_data(move |_, _size| { let data = match data_weak.upgrade() { Some(data) => data, - None => return glib::Continue(false), + None => return, }; + let mut d = data.lock().unwrap(); - let (appsrc, buffer) = { - let mut data = data.lock().unwrap(); - let mut buffer = gst::Buffer::with_size(CHUNK_SIZE).unwrap(); - let num_samples = CHUNK_SIZE / 2; /* Each sample is 16 bits */ - let pts = gst::SECOND - .mul_div_floor(data.num_samples, u64::from(SAMPLE_RATE)) - .expect("u64 overflow"); - let duration = gst::SECOND - .mul_div_floor(num_samples as u64, u64::from(SAMPLE_RATE)) - .expect("u64 overflow"); + if d.source_id.is_none() { + println!("start feeding"); - { - let buffer = buffer.get_mut().unwrap(); - { - let mut samples = buffer.map_writable().unwrap(); - let samples = samples.as_mut_slice_of::().unwrap(); + let data_weak = Arc::downgrade(&data); + d.source_id = Some(glib::source::idle_add(move || { + let data = match data_weak.upgrade() { + Some(data) => data, + None => return glib::Continue(false), + }; - // Generate some psychodelic waveforms - data.c += data.d; - data.d -= data.c / 1000.0; - let freq = 1100.0 + 1000.0 * data.d; + let (appsrc, buffer) = { + let mut data = data.lock().unwrap(); + let mut buffer = gst::Buffer::with_size(CHUNK_SIZE).unwrap(); + let num_samples = CHUNK_SIZE / 2; /* Each sample is 16 bits */ + let pts = gst::SECOND + .mul_div_floor(data.num_samples, u64::from(SAMPLE_RATE)) + .expect("u64 overflow"); + let duration = gst::SECOND + .mul_div_floor(num_samples as u64, u64::from(SAMPLE_RATE)) + .expect("u64 overflow"); - for sample in samples.iter_mut() { - data.a += data.b; - data.b -= data.a / freq; - *sample = 500 * (data.a as i16); + { + let buffer = buffer.get_mut().unwrap(); + { + let mut samples = buffer.map_writable().unwrap(); + let samples = samples.as_mut_slice_of::().unwrap(); + + // Generate some psychodelic waveforms + data.c += data.d; + data.d -= data.c / 1000.0; + let freq = 1100.0 + 1000.0 * data.d; + + for sample in samples.iter_mut() { + data.a += data.b; + data.b -= data.a / freq; + *sample = 500 * (data.a as i16); + } + + data.num_samples += num_samples as u64; + } + + buffer.set_pts(pts); + buffer.set_duration(duration); } - data.num_samples += num_samples as u64; - } + (data.appsrc.clone(), buffer) + }; - buffer.set_pts(pts); - buffer.set_duration(duration); - } - - (data.appsrc.clone(), buffer) + glib::Continue(appsrc.push_buffer(buffer).is_ok()) + })); + } + }) + .enough_data(move |_| { + let data = match data_weak2.upgrade() { + Some(data) => data, + None => return, }; - glib::Continue(appsrc.push_buffer(buffer).is_ok()) - })); - } - }); - - let data_weak = Arc::downgrade(&data); - appsrc.connect_enough_data(move |_| { - let data = match data_weak.upgrade() { - Some(data) => data, - None => return, - }; - - let mut data = data.lock().unwrap(); - if let Some(source) = data.source_id.take() { - println!("stop feeding"); - glib::source::source_remove(source); - } - }); + let mut data = data.lock().unwrap(); + if let Some(source) = data.source_id.take() { + println!("stop feeding"); + glib::source::source_remove(source); + } + }) + .build(), + ); // configure appsink - appsink.set_emit_signals(true); appsink.set_caps(Some(&audio_caps)); let data_weak = Arc::downgrade(&data); - appsink.connect_new_sample(move |_| { - let data = match data_weak.upgrade() { - Some(data) => data, - None => return Ok(gst::FlowSuccess::Ok), - }; + appsink.set_callbacks( + gst_app::AppSinkCallbacks::builder() + .new_sample(move |_| { + let data = match data_weak.upgrade() { + Some(data) => data, + None => return Ok(gst::FlowSuccess::Ok), + }; - let appsink = { - let data = data.lock().unwrap(); - data.appsink.clone() - }; + let appsink = { + let data = data.lock().unwrap(); + data.appsink.clone() + }; - if let Ok(_sample) = appsink.pull_sample() { - use std::io::{self, Write}; - // The only thing we do in this example is print a * to indicate a received buffer - print!("*"); - let _ = io::stdout().flush(); - } + if let Ok(_sample) = appsink.pull_sample() { + use std::io::{self, Write}; + // The only thing we do in this example is print a * to indicate a received buffer + print!("*"); + let _ = io::stdout().flush(); + } - Ok(gst::FlowSuccess::Ok) - }); + Ok(gst::FlowSuccess::Ok) + }) + .build(), + ); let main_loop = glib::MainLoop::new(None, false); let main_loop_clone = main_loop.clone();