diff --git a/Cargo.lock b/Cargo.lock index 31ae313fe..022d530c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -504,6 +504,7 @@ dependencies = [ "memfd", "memmap2", "objc", + "once_cell", "pango", "pangocairo", "raw-window-handle", @@ -843,6 +844,7 @@ dependencies = [ "muldiv", "num-integer", "num-rational", + "once_cell", "option-operations", "paste", "pin-project-lite", @@ -863,6 +865,7 @@ dependencies = [ "gstreamer", "gstreamer-allocators-sys", "libc", + "once_cell", ] [[package]] @@ -919,6 +922,7 @@ dependencies = [ "gstreamer-base", "itertools", "libc", + "once_cell", "serde", "serde_json", "smallvec", @@ -1053,6 +1057,7 @@ dependencies = [ "gstreamer-gl-sys", "gstreamer-video", "libc", + "once_cell", "serde", "serde_json", ] @@ -1428,6 +1433,7 @@ dependencies = [ "gstreamer", "gstreamer-app", "gstreamer-video", + "once_cell", "thiserror", ] @@ -1471,6 +1477,7 @@ dependencies = [ "gstreamer-video-sys", "itertools", "libc", + "once_cell", "serde", "serde_json", "thiserror", @@ -1747,17 +1754,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", -] - [[package]] name = "num-integer" version = "0.1.45" @@ -2526,11 +2522,11 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.0" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44aa20ae986659d6c77d64d808a046996a932aa763913864dc40c359ef7ad5b" +checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" dependencies = [ - "nix", + "rustix", "wayland-client", "xcursor", ] diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 94c772e95..4c73d3ef3 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -42,6 +42,7 @@ uds = { version = "0.4", optional = true } winit = { version = "0.29", optional = true, default-features = false, features = ["rwh_05"] } atomic_refcell = "0.1" data-encoding = "2.0" +once_cell = "1" [target.'cfg(windows)'.dependencies] windows = { version = "0.52", features=["Win32_Graphics_Direct3D11", diff --git a/examples/src/bin/cairo_compositor.rs b/examples/src/bin/cairo_compositor.rs index e6927c565..b4e418d85 100644 --- a/examples/src/bin/cairo_compositor.rs +++ b/examples/src/bin/cairo_compositor.rs @@ -10,7 +10,6 @@ mod examples_common; // Our custom compositor element is defined in this module. mod cairo_compositor { - use glib::once_cell::sync::Lazy; use gst_base::subclass::prelude::*; use gst_video::{prelude::*, subclass::prelude::*}; @@ -57,15 +56,16 @@ mod cairo_compositor { // In this case a single property for configuring the background color of the // composition. fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { + static PROPERTIES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PROPERTIES.get_or_init(|| { vec![glib::ParamSpecUInt::builder("background-color") .nick("Background Color") .blurb("Background color as 0xRRGGBB") .default_value(Settings::default().background_color) .build()] - }); - - &PROPERTIES + }) } // Called by the application whenever the value of a property should be changed. @@ -100,20 +100,24 @@ mod cairo_compositor { // gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry // after initial registration without having to load the plugin in memory. fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static ELEMENT_METADATA: Lazy = Lazy::new(|| { + static ELEMENT_METADATA: std::sync::OnceLock = + std::sync::OnceLock::new(); + + Some(ELEMENT_METADATA.get_or_init(|| { gst::subclass::ElementMetadata::new( "Cairo Compositor", "Compositor/Video", "Cairo based compositor", "Sebastian Dröge ", ) - }); - - Some(&*ELEMENT_METADATA) + })) } fn pad_templates() -> &'static [gst::PadTemplate] { - static PAD_TEMPLATES: Lazy> = Lazy::new(|| { + static PAD_TEMPLATES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PAD_TEMPLATES.get_or_init(|| { // Create pad templates for our sink and source pad. These are later used for // actually creating the pads and beforehand already provide information to // GStreamer about all possible pads that could exist for this type. @@ -148,9 +152,7 @@ mod cairo_compositor { ) .unwrap(), ] - }); - - PAD_TEMPLATES.as_ref() + }) } // Notify via the child proxy interface whenever a new pad is added or removed. @@ -457,7 +459,10 @@ mod cairo_compositor { // In this case there are various properties for defining the position and otherwise // the appearance of the stream corresponding to this pad. fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { + static PROPERTIES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PROPERTIES.get_or_init(|| { vec![ glib::ParamSpecDouble::builder("alpha") .nick("Alpha") @@ -495,9 +500,7 @@ mod cairo_compositor { .default_value(Settings::default().ypos) .build(), ] - }); - - PROPERTIES.as_ref() + }) } // Called by the application whenever the value of a property should be changed. diff --git a/examples/src/bin/custom_meta.rs b/examples/src/bin/custom_meta.rs index 5d2b879d0..456fb95cd 100644 --- a/examples/src/bin/custom_meta.rs +++ b/examples/src/bin/custom_meta.rs @@ -71,7 +71,6 @@ mod custom_meta { mod imp { use std::{mem, ptr}; - use glib::once_cell::sync::Lazy; use glib::translate::*; pub(super) struct CustomMetaParams { @@ -87,8 +86,10 @@ mod custom_meta { // Function to register the meta API and get a type back. pub(super) fn custom_meta_api_get_type() -> glib::Type { - static TYPE: Lazy = Lazy::new(|| unsafe { - let t = from_glib(gst::ffi::gst_meta_api_type_register( + static TYPE: std::sync::OnceLock = std::sync::OnceLock::new(); + + *TYPE.get_or_init(|| unsafe { + let t = glib::Type::from_glib(gst::ffi::gst_meta_api_type_register( b"MyCustomMetaAPI\0".as_ptr() as *const _, // We provide no tags here as our meta is just a label and does // not refer to any specific aspect of the buffer. @@ -98,9 +99,7 @@ mod custom_meta { assert_ne!(t, glib::Type::INVALID); t - }); - - *TYPE + }) } // Initialization function for our meta. This needs to ensure all fields are correctly @@ -157,21 +156,24 @@ mod custom_meta { unsafe impl Send for MetaInfo {} unsafe impl Sync for MetaInfo {} - static META_INFO: Lazy = Lazy::new(|| unsafe { - MetaInfo( - ptr::NonNull::new(gst::ffi::gst_meta_register( - custom_meta_api_get_type().into_glib(), - b"MyCustomMeta\0".as_ptr() as *const _, - mem::size_of::(), - Some(custom_meta_init), - Some(custom_meta_free), - Some(custom_meta_transform), - ) as *mut gst::ffi::GstMetaInfo) - .expect("Failed to register meta API"), - ) - }); + static META_INFO: std::sync::OnceLock = std::sync::OnceLock::new(); - META_INFO.0.as_ptr() + META_INFO + .get_or_init(|| unsafe { + MetaInfo( + ptr::NonNull::new(gst::ffi::gst_meta_register( + custom_meta_api_get_type().into_glib(), + b"MyCustomMeta\0".as_ptr() as *const _, + mem::size_of::(), + Some(custom_meta_init), + Some(custom_meta_free), + Some(custom_meta_transform), + ) as *mut gst::ffi::GstMetaInfo) + .expect("Failed to register meta API"), + ) + }) + .0 + .as_ptr() } } } diff --git a/examples/src/bin/fd_allocator.rs b/examples/src/bin/fd_allocator.rs index 1c2573f3c..76df9c2b0 100644 --- a/examples/src/bin/fd_allocator.rs +++ b/examples/src/bin/fd_allocator.rs @@ -361,11 +361,11 @@ mod video_filter { use std::{mem::ManuallyDrop, os::unix::prelude::FromRawFd}; use anyhow::Error; - use glib::once_cell::sync::Lazy; use gst::{subclass::prelude::*, PadDirection, PadPresence, PadTemplate}; use gst_app::gst_base::subclass::BaseTransformMode; use gst_video::{prelude::*, subclass::prelude::*, VideoFrameRef}; use memmap2::MmapMut; + use once_cell::sync::Lazy; static CAT: Lazy = Lazy::new(|| { gst::DebugCategory::new( @@ -430,7 +430,10 @@ mod video_filter { impl ElementImpl for FdMemoryFadeInVideoFilter { fn pad_templates() -> &'static [PadTemplate] { - static PAD_TEMPLATES: Lazy> = Lazy::new(|| { + static PAD_TEMPLATES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PAD_TEMPLATES.get_or_init(|| { let caps = gst_video::VideoCapsBuilder::new() .format(gst_video::VideoFormat::Bgra) .build(); @@ -440,9 +443,7 @@ mod video_filter { PadTemplate::new("src", PadDirection::Src, PadPresence::Always, &caps) .unwrap(), ] - }); - - PAD_TEMPLATES.as_ref() + }) } } diff --git a/examples/src/bin/glfilter.rs b/examples/src/bin/glfilter.rs index 07213397c..08f8fdd7d 100644 --- a/examples/src/bin/glfilter.rs +++ b/examples/src/bin/glfilter.rs @@ -32,13 +32,13 @@ void main () { mod mirror { use std::sync::Mutex; - use glib::once_cell::sync::Lazy; use gst_base::subclass::BaseTransformMode; use gst_gl::{ prelude::*, subclass::{prelude::*, GLFilterMode}, *, }; + use once_cell::sync::Lazy; use super::{gl, FRAGMENT_SHADER}; diff --git a/examples/src/bin/subclass.rs b/examples/src/bin/subclass.rs index 8e1549376..bf00e35ea 100644 --- a/examples/src/bin/subclass.rs +++ b/examples/src/bin/subclass.rs @@ -17,8 +17,8 @@ mod examples_common; // Our custom FIR filter element is defined in this module mod fir_filter { use byte_slice_cast::*; - use glib::once_cell::sync::Lazy; use gst_base::subclass::prelude::*; + use once_cell::sync::Lazy; // The debug category we use below for our filter pub static CAT: Lazy = Lazy::new(|| { @@ -63,20 +63,24 @@ mod fir_filter { // gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry // after initial registration without having to load the plugin in memory. fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static ELEMENT_METADATA: Lazy = Lazy::new(|| { + static ELEMENT_METADATA: std::sync::OnceLock = + std::sync::OnceLock::new(); + + Some(ELEMENT_METADATA.get_or_init(|| { gst::subclass::ElementMetadata::new( "FIR Filter", "Filter/Effect/Audio", "A FIR audio filter", "Sebastian Dröge ", ) - }); - - Some(&*ELEMENT_METADATA) + })) } fn pad_templates() -> &'static [gst::PadTemplate] { - static PAD_TEMPLATES: Lazy> = Lazy::new(|| { + static PAD_TEMPLATES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PAD_TEMPLATES.get_or_init(|| { // Create pad templates for our sink and source pad. These are later used for // actually creating the pads and beforehand already provide information to // GStreamer about all possible pads that could exist for this type. @@ -107,9 +111,7 @@ mod fir_filter { ) .unwrap(), ] - }); - - PAD_TEMPLATES.as_ref() + }) } } diff --git a/examples/src/bin/subclass_vfuncs/iirfilter/imp.rs b/examples/src/bin/subclass_vfuncs/iirfilter/imp.rs index a62c0aec9..5c6f4dcd6 100644 --- a/examples/src/bin/subclass_vfuncs/iirfilter/imp.rs +++ b/examples/src/bin/subclass_vfuncs/iirfilter/imp.rs @@ -2,8 +2,9 @@ use std::{collections::VecDeque, sync::Mutex}; -use glib::{once_cell::sync::Lazy, prelude::*}; +use glib::prelude::*; use gst_audio::subclass::prelude::*; +use once_cell::sync::Lazy; use byte_slice_cast::*; @@ -152,15 +153,14 @@ impl BaseTransformImpl for IirFilter { impl AudioFilterImpl for IirFilter { fn allowed_caps() -> &'static gst::Caps { - static CAPS: Lazy = Lazy::new(|| { + static CAPS: std::sync::OnceLock = std::sync::OnceLock::new(); + CAPS.get_or_init(|| { // On both of pads we can only handle F32 mono at any sample rate. gst_audio::AudioCapsBuilder::new_interleaved() .format(gst_audio::AUDIO_FORMAT_F32) .channels(1) .build() - }); - - &CAPS + }) } fn setup(&self, info: &gst_audio::AudioInfo) -> Result<(), gst::LoggableError> { diff --git a/examples/src/bin/subclass_vfuncs/lowpass/imp.rs b/examples/src/bin/subclass_vfuncs/lowpass/imp.rs index 91f282940..614cb8e46 100644 --- a/examples/src/bin/subclass_vfuncs/lowpass/imp.rs +++ b/examples/src/bin/subclass_vfuncs/lowpass/imp.rs @@ -2,7 +2,7 @@ use std::sync::Mutex; -use glib::{once_cell::sync::Lazy, prelude::*}; +use glib::prelude::*; use gst::prelude::*; use gst_audio::subclass::prelude::*; @@ -45,7 +45,9 @@ impl ObjectSubclass for Lowpass { // Implementation of glib::Object virtual methods impl ObjectImpl for Lowpass { fn properties() -> &'static [glib::ParamSpec] { - static PROPERTIES: Lazy> = Lazy::new(|| { + static PROPERTIES: std::sync::OnceLock> = std::sync::OnceLock::new(); + + PROPERTIES.get_or_init(|| { vec![glib::ParamSpecFloat::builder("cutoff") .nick("Cutoff") .blurb("Cutoff frequency in Hz") @@ -53,9 +55,7 @@ impl ObjectImpl for Lowpass { .minimum(0.0) .mutable_playing() .build()] - }); - - PROPERTIES.as_ref() + }) } fn set_property(&self, _id: usize, value: &glib::Value, pspec: &glib::ParamSpec) { @@ -84,16 +84,16 @@ impl ElementImpl for Lowpass { // gst-inspect-1.0 and can also be programmatically retrieved from the gst::Registry // after initial registration without having to load the plugin in memory. fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - static ELEMENT_METADATA: Lazy = Lazy::new(|| { + static ELEMENT_METADATA: std::sync::OnceLock = + std::sync::OnceLock::new(); + Some(ELEMENT_METADATA.get_or_init(|| { gst::subclass::ElementMetadata::new( "Lowpass Filter", "Filter/Effect/Audio", "A Lowpass audio filter", "Sebastian Dröge ", ) - }); - - Some(&*ELEMENT_METADATA) + })) } } diff --git a/gstreamer-allocators/Cargo.toml b/gstreamer-allocators/Cargo.toml index 12b26879a..ddcaeaa91 100644 --- a/gstreamer-allocators/Cargo.toml +++ b/gstreamer-allocators/Cargo.toml @@ -18,6 +18,7 @@ libc = "0.2" ffi = { package = "gstreamer-allocators-sys", path = "sys" } glib = { git = "https://github.com/gtk-rs/gtk-rs-core" } gst = { package = "gstreamer", path = "../gstreamer" } +once_cell = "1" [dev-dependencies] gir-format-check = "0.1" diff --git a/gstreamer-allocators/src/caps_features.rs b/gstreamer-allocators/src/caps_features.rs index f4eab3354..ee09a5e2d 100644 --- a/gstreamer-allocators/src/caps_features.rs +++ b/gstreamer-allocators/src/caps_features.rs @@ -1,7 +1,7 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use glib::once_cell::sync::Lazy; use gst::CapsFeatures; +use once_cell::sync::Lazy; pub static CAPS_FEATURES_MEMORY_DMABUF: Lazy = Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_DMABUF])); diff --git a/gstreamer-app/src/app_sink.rs b/gstreamer-app/src/app_sink.rs index 9c28f47f2..58fa707df 100644 --- a/gstreamer-app/src/app_sink.rs +++ b/gstreamer-app/src/app_sink.rs @@ -350,23 +350,23 @@ impl AppSink { #[doc(alias = "gst_app_sink_set_callbacks")] pub fn set_callbacks(&self, callbacks: AppSinkCallbacks) { - #[cfg(not(feature = "v1_18"))] - use glib::once_cell::sync::Lazy; - #[cfg(not(feature = "v1_18"))] - static SET_ONCE_QUARK: Lazy = - Lazy::new(|| glib::Quark::from_str("gstreamer-rs-app-sink-callbacks")); - unsafe { let sink = self.to_glib_none().0; #[cfg(not(feature = "v1_18"))] { + static SET_ONCE_QUARK: std::sync::OnceLock = + std::sync::OnceLock::new(); + + let set_once_quark = SET_ONCE_QUARK + .get_or_init(|| glib::Quark::from_str("gstreamer-rs-app-sink-callbacks")); + // This is not thread-safe before 1.16.3, see // https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570 if gst::version() < (1, 16, 3, 0) { if !glib::gobject_ffi::g_object_get_qdata( sink as *mut _, - SET_ONCE_QUARK.into_glib(), + set_once_quark.into_glib(), ) .is_null() { @@ -375,7 +375,7 @@ impl AppSink { glib::gobject_ffi::g_object_set_qdata( sink as *mut _, - SET_ONCE_QUARK.into_glib(), + set_once_quark.into_glib(), 1 as *mut _, ); } diff --git a/gstreamer-app/src/app_src.rs b/gstreamer-app/src/app_src.rs index 90822573e..f8666b654 100644 --- a/gstreamer-app/src/app_src.rs +++ b/gstreamer-app/src/app_src.rs @@ -223,22 +223,22 @@ impl AppSrc { #[doc(alias = "gst_app_src_set_callbacks")] pub fn set_callbacks(&self, callbacks: AppSrcCallbacks) { - #[cfg(not(feature = "v1_18"))] - use glib::once_cell::sync::Lazy; - #[cfg(not(feature = "v1_18"))] - static SET_ONCE_QUARK: Lazy = - Lazy::new(|| glib::Quark::from_str("gstreamer-rs-app-src-callbacks")); - unsafe { let src = self.to_glib_none().0; #[cfg(not(feature = "v1_18"))] { + static SET_ONCE_QUARK: std::sync::OnceLock = + std::sync::OnceLock::new(); + + let set_once_quark = SET_ONCE_QUARK + .get_or_init(|| glib::Quark::from_str("gstreamer-rs-app-src-callbacks")); + // This is not thread-safe before 1.16.3, see // https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/merge_requests/570 if gst::version() < (1, 16, 3, 0) { if !glib::gobject_ffi::g_object_get_qdata( src as *mut _, - SET_ONCE_QUARK.into_glib(), + set_once_quark.into_glib(), ) .is_null() { @@ -247,7 +247,7 @@ impl AppSrc { glib::gobject_ffi::g_object_set_qdata( src as *mut _, - SET_ONCE_QUARK.into_glib(), + set_once_quark.into_glib(), 1 as *mut _, ); } diff --git a/gstreamer-audio/Cargo.toml b/gstreamer-audio/Cargo.toml index aafb2b3ed..5da9556f7 100644 --- a/gstreamer-audio/Cargo.toml +++ b/gstreamer-audio/Cargo.toml @@ -22,6 +22,7 @@ gst = { package = "gstreamer", path = "../gstreamer" } gst-base = { package = "gstreamer-base", path = "../gstreamer-base" } serde = { version = "1.0", optional = true } smallvec = "1.0" +once_cell = "1" [dev-dependencies] itertools = "0.12" diff --git a/gstreamer-audio/src/audio_format.rs b/gstreamer-audio/src/audio_format.rs index efc3718a6..eb7e337a2 100644 --- a/gstreamer-audio/src/audio_format.rs +++ b/gstreamer-audio/src/audio_format.rs @@ -2,8 +2,8 @@ use std::str; -use glib::once_cell::sync::Lazy; use glib::translate::{from_glib, IntoGlib}; +use once_cell::sync::Lazy; #[cfg(feature = "v1_18")] pub static AUDIO_FORMATS_ALL: Lazy> = Lazy::new(|| unsafe { diff --git a/gstreamer-audio/src/subclass/audio_filter.rs b/gstreamer-audio/src/subclass/audio_filter.rs index 322fe6d33..582d2fac8 100644 --- a/gstreamer-audio/src/subclass/audio_filter.rs +++ b/gstreamer-audio/src/subclass/audio_filter.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use glib::{once_cell::sync::Lazy, translate::*}; +use glib::translate::*; use gst_base::{prelude::*, subclass::prelude::*}; use crate::{AudioFilter, AudioInfo}; @@ -52,10 +52,9 @@ pub trait AudioFilterImplExt: sealed::Sealed + ObjectSubclass { ); if templ.is_null() { - static ANY_AUDIO_CAPS: Lazy = - Lazy::new(|| crate::AudioCapsBuilder::new().build()); + static ANY_AUDIO_CAPS: std::sync::OnceLock = std::sync::OnceLock::new(); - return &ANY_AUDIO_CAPS; + return ANY_AUDIO_CAPS.get_or_init(|| crate::AudioCapsBuilder::new().build()); } &*(&(*templ).caps as *const *mut gst::ffi::GstCaps as *const gst::Caps) diff --git a/gstreamer-base/src/subclass/base_transform.rs b/gstreamer-base/src/subclass/base_transform.rs index b6e6c41df..330e31d1e 100644 --- a/gstreamer-base/src/subclass/base_transform.rs +++ b/gstreamer-base/src/subclass/base_transform.rs @@ -1310,22 +1310,24 @@ mod tests { impl ElementImpl for TestTransform { fn metadata() -> Option<&'static gst::subclass::ElementMetadata> { - use glib::once_cell::sync::Lazy; - static ELEMENT_METADATA: Lazy = Lazy::new(|| { + static ELEMENT_METADATA: std::sync::OnceLock = + std::sync::OnceLock::new(); + + Some(ELEMENT_METADATA.get_or_init(|| { gst::subclass::ElementMetadata::new( "Test Transform", "Generic", "Does nothing", "Sebastian Dröge ", ) - }); - - Some(&*ELEMENT_METADATA) + })) } fn pad_templates() -> &'static [gst::PadTemplate] { - use glib::once_cell::sync::Lazy; - static PAD_TEMPLATES: Lazy> = Lazy::new(|| { + static PAD_TEMPLATES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PAD_TEMPLATES.get_or_init(|| { let caps = gst::Caps::new_any(); vec![ gst::PadTemplate::new( @@ -1343,9 +1345,7 @@ mod tests { ) .unwrap(), ] - }); - - PAD_TEMPLATES.as_ref() + }) } } diff --git a/gstreamer-gl/Cargo.toml b/gstreamer-gl/Cargo.toml index 20757f387..9b97fac6e 100644 --- a/gstreamer-gl/Cargo.toml +++ b/gstreamer-gl/Cargo.toml @@ -24,6 +24,7 @@ gst = { package = "gstreamer", path = "../gstreamer" } gst-base = { package = "gstreamer-base", path = "../gstreamer-base" } gst-video = { package = "gstreamer-video", path = "../gstreamer-video" } serde = { version = "1.0", optional = true } +once_cell = "1" [dev-dependencies] gir-format-check = "0.1" diff --git a/gstreamer-gl/src/caps_features.rs b/gstreamer-gl/src/caps_features.rs index a220b0e72..786d426aa 100644 --- a/gstreamer-gl/src/caps_features.rs +++ b/gstreamer-gl/src/caps_features.rs @@ -1,7 +1,7 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use glib::once_cell::sync::Lazy; use gst::CapsFeatures; +use once_cell::sync::Lazy; pub static CAPS_FEATURES_MEMORY_GL_MEMORY: Lazy = Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_GL_MEMORY])); diff --git a/gstreamer-play/src/subclass/play_video_renderer.rs b/gstreamer-play/src/subclass/play_video_renderer.rs index 7e66111e8..6fbdd613b 100644 --- a/gstreamer-play/src/subclass/play_video_renderer.rs +++ b/gstreamer-play/src/subclass/play_video_renderer.rs @@ -49,9 +49,10 @@ unsafe extern "C" fn video_renderer_create_video_sink( video_renderer: *mut ffi::GstPlayVideoRenderer, play: *mut ffi::GstPlay, ) -> *mut gst::ffi::GstElement { - use glib::once_cell::sync::Lazy; - static VIDEO_SINK_QUARK: Lazy = - Lazy::new(|| glib::Quark::from_str("gstreamer-rs-play-video-sink")); + static VIDEO_SINK_QUARK: std::sync::OnceLock = std::sync::OnceLock::new(); + + let video_sink_quark = + VIDEO_SINK_QUARK.get_or_init(|| glib::Quark::from_str("gstreamer-rs-play-video-sink")); let instance = &*(video_renderer as *mut T::Instance); let imp = instance.imp(); @@ -62,7 +63,7 @@ unsafe extern "C" fn video_renderer_create_video_sink( let old_sink_ptr = glib::gobject_ffi::g_object_get_qdata( video_renderer as *mut _, - VIDEO_SINK_QUARK.into_glib(), + video_sink_quark.into_glib(), ) as *mut gst::ffi::GstElement; if !old_sink_ptr.is_null() && old_sink_ptr != sink_ptr { panic!("Video sink must not change"); @@ -74,7 +75,7 @@ unsafe extern "C" fn video_renderer_create_video_sink( glib::gobject_ffi::g_object_set_qdata_full( video_renderer as *mut _, - VIDEO_SINK_QUARK.into_glib(), + video_sink_quark.into_glib(), glib::gobject_ffi::g_object_ref(sink_ptr as *mut _) as *mut _, Some(unref), ); diff --git a/gstreamer-player/src/subclass/player_video_renderer.rs b/gstreamer-player/src/subclass/player_video_renderer.rs index 8e70225ab..e297593a8 100644 --- a/gstreamer-player/src/subclass/player_video_renderer.rs +++ b/gstreamer-player/src/subclass/player_video_renderer.rs @@ -49,9 +49,10 @@ unsafe extern "C" fn video_renderer_create_video_sink *mut gst::ffi::GstElement { - use glib::once_cell::sync::Lazy; - static VIDEO_SINK_QUARK: Lazy = - Lazy::new(|| glib::Quark::from_str("gstreamer-rs-player-video-sink")); + static VIDEO_SINK_QUARK: std::sync::OnceLock = std::sync::OnceLock::new(); + + let video_sink_quark = + VIDEO_SINK_QUARK.get_or_init(|| glib::Quark::from_str("gstreamer-rs-player-video-sink")); let instance = &*(video_renderer as *mut T::Instance); let imp = instance.imp(); @@ -62,7 +63,7 @@ unsafe extern "C" fn video_renderer_create_video_sink( ptr: *mut ffi::GstRTSPMediaFactory, media: *mut ffi::GstRTSPMedia, ) -> *mut gst::ffi::GstElement { - use glib::once_cell::sync::Lazy; + static PIPELINE_QUARK: std::sync::OnceLock = std::sync::OnceLock::new(); - static PIPELINE_QUARK: Lazy = - Lazy::new(|| glib::Quark::from_str("gstreamer-rs-rtsp-media-pipeline")); + let pipeline_quark = + PIPELINE_QUARK.get_or_init(|| glib::Quark::from_str("gstreamer-rs-rtsp-media-pipeline")); let instance = &*(ptr as *mut T::Instance); let imp = instance.imp(); @@ -239,7 +239,7 @@ unsafe extern "C" fn factory_create_pipeline( // FIXME We somehow need to ensure the pipeline actually stays alive... glib::gobject_ffi::g_object_set_qdata_full( media as *mut _, - PIPELINE_QUARK.into_glib(), + pipeline_quark.into_glib(), pipeline as *mut _, Some(transmute::<_, unsafe extern "C" fn(glib::ffi::gpointer)>( glib::gobject_ffi::g_object_unref as *const (), diff --git a/gstreamer-utils/Cargo.toml b/gstreamer-utils/Cargo.toml index 58dfecf87..c2163fe45 100644 --- a/gstreamer-utils/Cargo.toml +++ b/gstreamer-utils/Cargo.toml @@ -19,6 +19,7 @@ rust-version = "1.70" gst = { package = "gstreamer", path = "../gstreamer", features = ["v1_20"] } gst_app = { package = "gstreamer-app", path = "../gstreamer-app", features = ["v1_20"] } gst_video = { package = "gstreamer-video", path = "../gstreamer-video", features = ["v1_20"] } +once_cell = "1" thiserror = "1" [dev-dependencies] diff --git a/gstreamer-utils/src/streamproducer.rs b/gstreamer-utils/src/streamproducer.rs index f93448be2..f311cc740 100644 --- a/gstreamer-utils/src/streamproducer.rs +++ b/gstreamer-utils/src/streamproducer.rs @@ -4,8 +4,8 @@ use std::{ sync::{atomic, Arc, Mutex, MutexGuard}, }; -use glib::once_cell::sync::Lazy; use gst::{glib, prelude::*}; +use once_cell::sync::Lazy; use thiserror::Error; static CAT: Lazy = Lazy::new(|| { diff --git a/gstreamer-validate/src/action_type.rs b/gstreamer-validate/src/action_type.rs index e7194c886..d7d036245 100644 --- a/gstreamer-validate/src/action_type.rs +++ b/gstreamer-validate/src/action_type.rs @@ -1,11 +1,7 @@ use std::{ffi::c_int, ptr}; -use glib::once_cell::sync::Lazy; use glib::translate::*; -static QUARK_ACTION_TYPE_FUNC: Lazy = - Lazy::new(|| glib::Quark::from_str("rs-action-type-function")); - #[derive(Debug)] #[repr(transparent)] #[doc(alias = "GstValidateActionParameter")] @@ -193,6 +189,12 @@ impl<'a> ActionTypeBuilder<'a> { } pub fn build(self) -> crate::ActionType { + static QUARK_ACTION_TYPE_FUNC: std::sync::OnceLock = + std::sync::OnceLock::new(); + + let quark_action_type_func = + QUARK_ACTION_TYPE_FUNC.get_or_init(|| glib::Quark::from_str("rs-action-type-function")); + unsafe extern "C" fn execute_func_trampoline( scenario: *mut ffi::GstValidateScenario, action: *mut ffi::GstValidateAction, @@ -203,7 +205,7 @@ impl<'a> ActionTypeBuilder<'a> { let func: &ActionFunction = &*(gst::ffi::gst_mini_object_get_qdata( action_type as *mut gst::ffi::GstMiniObject, - QUARK_ACTION_TYPE_FUNC.into_glib(), + QUARK_ACTION_TYPE_FUNC.get().unwrap().into_glib(), ) as *const Box); (*func)(&scenario, action).into_glib() @@ -232,7 +234,7 @@ impl<'a> ActionTypeBuilder<'a> { gst::ffi::gst_mini_object_set_qdata( action_type as *mut gst::ffi::GstMiniObject, - QUARK_ACTION_TYPE_FUNC.into_glib(), + quark_action_type_func.into_glib(), Box::into_raw(Box::new(f)) as *mut _, Some(destroy_notify), ); diff --git a/gstreamer-video/Cargo.toml b/gstreamer-video/Cargo.toml index 37d6ea71f..f4785f589 100644 --- a/gstreamer-video/Cargo.toml +++ b/gstreamer-video/Cargo.toml @@ -23,6 +23,7 @@ gst-base = { package = "gstreamer-base", path = "../gstreamer-base" } futures-channel = "0.3" serde = { version = "1.0", optional = true, features = ["derive"] } thiserror = "1.0.49" +once_cell = "1" [dev-dependencies] itertools = "0.12" diff --git a/gstreamer-video/src/caps_features.rs b/gstreamer-video/src/caps_features.rs index 76b089c2b..6f16ebbeb 100644 --- a/gstreamer-video/src/caps_features.rs +++ b/gstreamer-video/src/caps_features.rs @@ -1,7 +1,7 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use glib::once_cell::sync::Lazy; use gst::CapsFeatures; +use once_cell::sync::Lazy; #[cfg(feature = "v1_16")] #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))] diff --git a/gstreamer-video/src/video_format.rs b/gstreamer-video/src/video_format.rs index 2691f0f7d..a3fdf6b11 100644 --- a/gstreamer-video/src/video_format.rs +++ b/gstreamer-video/src/video_format.rs @@ -2,8 +2,8 @@ use std::str; -use glib::once_cell::sync::Lazy; use glib::translate::{from_glib, FromGlib, IntoGlib}; +use once_cell::sync::Lazy; #[cfg(feature = "v1_18")] pub static VIDEO_FORMATS_ALL: Lazy> = Lazy::new(|| unsafe { diff --git a/gstreamer/Cargo.toml b/gstreamer/Cargo.toml index 776510c18..23968d585 100644 --- a/gstreamer/Cargo.toml +++ b/gstreamer/Cargo.toml @@ -32,6 +32,7 @@ thiserror = "1" smallvec = { version = "1.0", features = ["write"] } itertools = "0.12" pin-project-lite = "0.2" +once_cell = "1" [dev-dependencies] ron = "0.8" diff --git a/gstreamer/src/bus.rs b/gstreamer/src/bus.rs index f4157c78c..400ed22c8 100644 --- a/gstreamer/src/bus.rs +++ b/gstreamer/src/bus.rs @@ -192,23 +192,23 @@ impl Bus { where F: Fn(&Bus, &Message) -> BusSyncReply + Send + Sync + 'static, { - #[cfg(not(feature = "v1_18"))] - use glib::once_cell::sync::Lazy; - #[cfg(not(feature = "v1_18"))] - static SET_ONCE_QUARK: Lazy = - Lazy::new(|| glib::Quark::from_str("gstreamer-rs-sync-handler")); - unsafe { let bus = self.to_glib_none().0; #[cfg(not(feature = "v1_18"))] { + static SET_ONCE_QUARK: std::sync::OnceLock = + std::sync::OnceLock::new(); + + let set_once_quark = SET_ONCE_QUARK + .get_or_init(|| glib::Quark::from_str("gstreamer-rs-sync-handler")); + // This is not thread-safe before 1.16.3, see // https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/merge_requests/416 if crate::version() < (1, 16, 3, 0) { if !glib::gobject_ffi::g_object_get_qdata( bus as *mut _, - SET_ONCE_QUARK.into_glib(), + set_once_quark.into_glib(), ) .is_null() { @@ -217,7 +217,7 @@ impl Bus { glib::gobject_ffi::g_object_set_qdata( bus as *mut _, - SET_ONCE_QUARK.into_glib(), + set_once_quark.into_glib(), 1 as *mut _, ); } diff --git a/gstreamer/src/caps_features.rs b/gstreamer/src/caps_features.rs index ced15b694..546a0f11b 100644 --- a/gstreamer/src/caps_features.rs +++ b/gstreamer/src/caps_features.rs @@ -9,8 +9,8 @@ use std::{ ptr, str, }; -use glib::once_cell::sync::Lazy; use glib::{translate::*, IntoGStr, StaticType}; +use once_cell::sync::Lazy; #[doc(alias = "GstCapsFeatures")] #[repr(transparent)] diff --git a/gstreamer/src/iterator.rs b/gstreamer/src/iterator.rs index 3942efd65..52c13e926 100644 --- a/gstreamer/src/iterator.rs +++ b/gstreamer/src/iterator.rs @@ -356,12 +356,9 @@ unsafe extern "C" fn filter_boxed_unref(boxed: gpointer) { } unsafe extern "C" fn filter_boxed_get_type() -> glib::Type { - use std::sync::Once; + static TYPE: std::sync::OnceLock = std::sync::OnceLock::new(); - static mut TYPE: glib::Type = glib::Type::INVALID; - static ONCE: Once = Once::new(); - - ONCE.call_once(|| { + *TYPE.get_or_init(|| { let iter_type_name = { let mut idx = 0; @@ -376,16 +373,16 @@ unsafe extern "C" fn filter_boxed_get_type() -> glib::Type { } }; - TYPE = from_glib(glib::gobject_ffi::g_boxed_type_register_static( + let t = glib::Type::from_glib(glib::gobject_ffi::g_boxed_type_register_static( iter_type_name.as_ptr(), Some(filter_boxed_ref), Some(filter_boxed_unref), )); - assert!(TYPE.is_valid()); - }); + assert!(t.is_valid()); - TYPE + t + }) } unsafe extern "C" fn find_trampoline bool>( diff --git a/gstreamer/src/log.rs b/gstreamer/src/log.rs index ac11c0115..7986158c7 100644 --- a/gstreamer/src/log.rs +++ b/gstreamer/src/log.rs @@ -2,9 +2,9 @@ use std::{borrow::Cow, ffi::CStr, fmt, ptr}; -use glib::once_cell::sync::Lazy; use glib::{ffi::gpointer, prelude::*, translate::*, IntoGStr, IntoOptionalGStr}; use libc::c_char; +use once_cell::sync::Lazy; use crate::DebugLevel; diff --git a/gstreamer/src/memory_wrapped.rs b/gstreamer/src/memory_wrapped.rs index a24471ba7..f99e80d1b 100644 --- a/gstreamer/src/memory_wrapped.rs +++ b/gstreamer/src/memory_wrapped.rs @@ -1,6 +1,6 @@ // Take a look at the license at the top of the repository in the LICENSE file. -use glib::{once_cell::sync::Lazy, translate::*, StaticType}; +use glib::{translate::*, StaticType}; use std::{alloc, mem, ptr}; @@ -141,49 +141,55 @@ unsafe extern "C" fn instance_init( (*allocator).object.flags |= ffi::GST_ALLOCATOR_FLAG_CUSTOM_ALLOC; } -static RUST_ALLOCATOR: Lazy = Lazy::new(|| unsafe { - struct TypeInfoWrap(glib::gobject_ffi::GTypeInfo); - unsafe impl Send for TypeInfoWrap {} - unsafe impl Sync for TypeInfoWrap {} +fn rust_allocator() -> &'static crate::Allocator { + static RUST_ALLOCATOR: std::sync::OnceLock = std::sync::OnceLock::new(); - static TYPE_INFO: TypeInfoWrap = TypeInfoWrap(glib::gobject_ffi::GTypeInfo { - class_size: mem::size_of::() as u16, - base_init: None, - base_finalize: None, - class_init: Some(class_init), - class_finalize: None, - class_data: ptr::null_mut(), - instance_size: mem::size_of::() as u16, - n_preallocs: 0, - instance_init: Some(instance_init), - value_table: ptr::null(), - }); + RUST_ALLOCATOR.get_or_init(|| unsafe { + struct TypeInfoWrap(glib::gobject_ffi::GTypeInfo); + unsafe impl Send for TypeInfoWrap {} + unsafe impl Sync for TypeInfoWrap {} - let type_name = { - let mut idx = 0; + static TYPE_INFO: TypeInfoWrap = TypeInfoWrap(glib::gobject_ffi::GTypeInfo { + class_size: mem::size_of::() as u16, + base_init: None, + base_finalize: None, + class_init: Some(class_init), + class_finalize: None, + class_data: ptr::null_mut(), + instance_size: mem::size_of::() as u16, + n_preallocs: 0, + instance_init: Some(instance_init), + value_table: ptr::null(), + }); - loop { - let type_name = glib::gformat!("GstRsAllocator-{}", idx); - if glib::gobject_ffi::g_type_from_name(type_name.as_ptr()) - == glib::gobject_ffi::G_TYPE_INVALID - { - break type_name; + let type_name = { + let mut idx = 0; + + loop { + let type_name = glib::gformat!("GstRsAllocator-{}", idx); + if glib::gobject_ffi::g_type_from_name(type_name.as_ptr()) + == glib::gobject_ffi::G_TYPE_INVALID + { + break type_name; + } + idx += 1; } - idx += 1; - } - }; + }; - let t = glib::gobject_ffi::g_type_register_static( - crate::Allocator::static_type().into_glib(), - type_name.as_ptr(), - &TYPE_INFO.0, - 0, - ); + let t = glib::gobject_ffi::g_type_register_static( + crate::Allocator::static_type().into_glib(), + type_name.as_ptr(), + &TYPE_INFO.0, + 0, + ); - assert!(t != glib::gobject_ffi::G_TYPE_INVALID); + assert!(t != glib::gobject_ffi::G_TYPE_INVALID); - from_glib_none(glib::gobject_ffi::g_object_newv(t, 0, ptr::null_mut()) as *mut ffi::GstAllocator) -}); + from_glib_none( + glib::gobject_ffi::g_object_newv(t, 0, ptr::null_mut()) as *mut ffi::GstAllocator + ) + }) +} impl Memory { #[doc(alias = "gst_memory_new_wrapped")] @@ -200,7 +206,7 @@ impl Memory { ffi::gst_memory_init( mem as *mut ffi::GstMemory, ffi::GST_MINI_OBJECT_FLAG_LOCK_READONLY, - RUST_ALLOCATOR.to_glib_none().0, + rust_allocator().to_glib_none().0, ptr::null_mut(), len, 0, @@ -242,7 +248,7 @@ impl Memory { ffi::gst_memory_init( mem as *mut ffi::GstMemory, 0, - RUST_ALLOCATOR.to_glib_none().0, + rust_allocator().to_glib_none().0, ptr::null_mut(), len, 0, diff --git a/gstreamer/src/meta.rs b/gstreamer/src/meta.rs index c15c36e83..1dca4bbc7 100644 --- a/gstreamer/src/meta.rs +++ b/gstreamer/src/meta.rs @@ -237,9 +237,9 @@ impl<'a, T> MetaRef<'a, T> { where T: MetaAPI, { - use glib::once_cell::sync::Lazy; + static TRANSFORM_COPY: std::sync::OnceLock = std::sync::OnceLock::new(); - static TRANSFORM_COPY: Lazy = Lazy::new(|| glib::Quark::from_str("gst-copy")); + let transform_copy = TRANSFORM_COPY.get_or_init(|| glib::Quark::from_str("gst-copy")); let (offset, size) = self.buffer.byte_range_into_offset_len(range)?; @@ -262,7 +262,7 @@ impl<'a, T> MetaRef<'a, T> { buffer.as_mut_ptr(), mut_override(self.upcast_ref().as_ptr()), mut_override(self.buffer.as_ptr()), - TRANSFORM_COPY.into_glib(), + transform_copy.into_glib(), &mut copy_data as *mut _ as *mut _, ), "Failed to copy meta" diff --git a/gstreamer/src/serde_macros.rs b/gstreamer/src/serde_macros.rs index 577c7b7b8..580709571 100644 --- a/gstreamer/src/serde_macros.rs +++ b/gstreamer/src/serde_macros.rs @@ -43,12 +43,12 @@ macro_rules! bitflags_serialize_impl { where S: serde::Serializer, { - use glib::once_cell::sync::Lazy; - let mut handled = Self::empty(); let mut res = String::new(); - static SORTED_VALUES: Lazy> = Lazy::new(|| { + static SORTED_VALUES: std::sync::OnceLock> = std::sync::OnceLock::new(); + + let sorted_values = SORTED_VALUES.get_or_init(|| { let class = FlagsClass::with_type(<$type>::static_type()).unwrap(); let mut sorted_values: Vec<(u32, String)> = class.values().iter() @@ -62,7 +62,7 @@ macro_rules! bitflags_serialize_impl { sorted_values }); - for (bits, nick) in SORTED_VALUES.iter() { + for (bits, nick) in sorted_values.iter() { // not all values defined in the class are always also defined // in the bitflags struct, see RTPBufferFlags for example if let Some(value) = Self::from_bits(*bits) { diff --git a/gstreamer/src/subclass/element.rs b/gstreamer/src/subclass/element.rs index 47b1737ac..02c3e7c4b 100644 --- a/gstreamer/src/subclass/element.rs +++ b/gstreamer/src/subclass/element.rs @@ -666,22 +666,24 @@ mod tests { impl ElementImpl for TestElement { fn metadata() -> Option<&'static ElementMetadata> { - use glib::once_cell::sync::Lazy; - static ELEMENT_METADATA: Lazy = Lazy::new(|| { + static ELEMENT_METADATA: std::sync::OnceLock = + std::sync::OnceLock::new(); + + Some(ELEMENT_METADATA.get_or_init(|| { ElementMetadata::new( "Test Element", "Generic", "Does nothing", "Sebastian Dröge ", ) - }); - - Some(&*ELEMENT_METADATA) + })) } fn pad_templates() -> &'static [PadTemplate] { - use glib::once_cell::sync::Lazy; - static PAD_TEMPLATES: Lazy> = Lazy::new(|| { + static PAD_TEMPLATES: std::sync::OnceLock> = + std::sync::OnceLock::new(); + + PAD_TEMPLATES.get_or_init(|| { let caps = crate::Caps::new_any(); vec![ PadTemplate::new( @@ -699,9 +701,7 @@ mod tests { ) .unwrap(), ] - }); - - PAD_TEMPLATES.as_ref() + }) } fn change_state( diff --git a/gstreamer/src/value_serde.rs b/gstreamer/src/value_serde.rs index b09897eee..ce186924c 100644 --- a/gstreamer/src/value_serde.rs +++ b/gstreamer/src/value_serde.rs @@ -4,9 +4,9 @@ use std::{fmt, mem}; -use glib::once_cell::sync::Lazy; use glib::{Date, StaticType, ToValue}; use num_rational::Rational32; +use once_cell::sync::Lazy; use serde::{ de, de::{Deserialize, Deserializer, SeqAccess, Visitor},