Switch from once_cell to std::sync::OnceLock where it makes sense

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1379>
This commit is contained in:
Sebastian Dröge 2024-01-29 17:31:21 +01:00
parent ce5dca918d
commit 193bcbf055
38 changed files with 229 additions and 212 deletions

24
Cargo.lock generated
View file

@ -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",
]

View file

@ -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",

View file

@ -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<Vec<glib::ParamSpec>> = Lazy::new(|| {
static PROPERTIES: std::sync::OnceLock<Vec<glib::ParamSpec>> =
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<gst::subclass::ElementMetadata> = Lazy::new(|| {
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
std::sync::OnceLock::new();
Some(ELEMENT_METADATA.get_or_init(|| {
gst::subclass::ElementMetadata::new(
"Cairo Compositor",
"Compositor/Video",
"Cairo based compositor",
"Sebastian Dröge <sebastian@centricular.com>",
)
});
Some(&*ELEMENT_METADATA)
}))
}
fn pad_templates() -> &'static [gst::PadTemplate] {
static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
static PAD_TEMPLATES: std::sync::OnceLock<Vec<gst::PadTemplate>> =
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<Vec<glib::ParamSpec>> = Lazy::new(|| {
static PROPERTIES: std::sync::OnceLock<Vec<glib::ParamSpec>> =
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.

View file

@ -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<glib::Type> = Lazy::new(|| unsafe {
let t = from_glib(gst::ffi::gst_meta_api_type_register(
static TYPE: std::sync::OnceLock<glib::Type> = 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<MetaInfo> = 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::<CustomMeta>(),
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<MetaInfo> = 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::<CustomMeta>(),
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()
}
}
}

View file

@ -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<gst::DebugCategory> = 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<Vec<PadTemplate>> = Lazy::new(|| {
static PAD_TEMPLATES: std::sync::OnceLock<Vec<PadTemplate>> =
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()
})
}
}

View file

@ -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};

View file

@ -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<gst::DebugCategory> = 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<gst::subclass::ElementMetadata> = Lazy::new(|| {
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
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 <sebastian@centricular.com>",
)
});
Some(&*ELEMENT_METADATA)
}))
}
fn pad_templates() -> &'static [gst::PadTemplate] {
static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
static PAD_TEMPLATES: std::sync::OnceLock<Vec<gst::PadTemplate>> =
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()
})
}
}

View file

@ -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<gst::Caps> = Lazy::new(|| {
static CAPS: std::sync::OnceLock<gst::Caps> = 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> {

View file

@ -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<Vec<glib::ParamSpec>> = Lazy::new(|| {
static PROPERTIES: std::sync::OnceLock<Vec<glib::ParamSpec>> = 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<gst::subclass::ElementMetadata> = Lazy::new(|| {
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
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 <sebastian@centricular.com>",
)
});
Some(&*ELEMENT_METADATA)
}))
}
}

View file

@ -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"

View file

@ -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<CapsFeatures> =
Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_DMABUF]));

View file

@ -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<glib::Quark> =
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<glib::Quark> =
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 _,
);
}

View file

@ -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<glib::Quark> =
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<glib::Quark> =
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 _,
);
}

View file

@ -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"

View file

@ -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<Box<[crate::AudioFormat]>> = Lazy::new(|| unsafe {

View file

@ -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<gst::Caps> =
Lazy::new(|| crate::AudioCapsBuilder::new().build());
static ANY_AUDIO_CAPS: std::sync::OnceLock<gst::Caps> = 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)

View file

@ -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<gst::subclass::ElementMetadata> = Lazy::new(|| {
static ELEMENT_METADATA: std::sync::OnceLock<gst::subclass::ElementMetadata> =
std::sync::OnceLock::new();
Some(ELEMENT_METADATA.get_or_init(|| {
gst::subclass::ElementMetadata::new(
"Test Transform",
"Generic",
"Does nothing",
"Sebastian Dröge <sebastian@centricular.com>",
)
});
Some(&*ELEMENT_METADATA)
}))
}
fn pad_templates() -> &'static [gst::PadTemplate] {
use glib::once_cell::sync::Lazy;
static PAD_TEMPLATES: Lazy<Vec<gst::PadTemplate>> = Lazy::new(|| {
static PAD_TEMPLATES: std::sync::OnceLock<Vec<gst::PadTemplate>> =
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()
})
}
}

View file

@ -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"

View file

@ -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<CapsFeatures> =
Lazy::new(|| CapsFeatures::new([crate::CAPS_FEATURE_MEMORY_GL_MEMORY]));

View file

@ -49,9 +49,10 @@ unsafe extern "C" fn video_renderer_create_video_sink<T: PlayVideoRendererImpl>(
video_renderer: *mut ffi::GstPlayVideoRenderer,
play: *mut ffi::GstPlay,
) -> *mut gst::ffi::GstElement {
use glib::once_cell::sync::Lazy;
static VIDEO_SINK_QUARK: Lazy<glib::Quark> =
Lazy::new(|| glib::Quark::from_str("gstreamer-rs-play-video-sink"));
static VIDEO_SINK_QUARK: std::sync::OnceLock<glib::Quark> = 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<T: PlayVideoRendererImpl>(
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<T: PlayVideoRendererImpl>(
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),
);

View file

@ -49,9 +49,10 @@ unsafe extern "C" fn video_renderer_create_video_sink<T: PlayerVideoRendererImpl
video_renderer: *mut ffi::GstPlayerVideoRenderer,
player: *mut ffi::GstPlayer,
) -> *mut gst::ffi::GstElement {
use glib::once_cell::sync::Lazy;
static VIDEO_SINK_QUARK: Lazy<glib::Quark> =
Lazy::new(|| glib::Quark::from_str("gstreamer-rs-player-video-sink"));
static VIDEO_SINK_QUARK: std::sync::OnceLock<glib::Quark> = 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<T: PlayerVideoRendererImpl
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<T: PlayerVideoRendererImpl
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),
);

View file

@ -224,10 +224,10 @@ unsafe extern "C" fn factory_create_pipeline<T: RTSPMediaFactoryImpl>(
ptr: *mut ffi::GstRTSPMediaFactory,
media: *mut ffi::GstRTSPMedia,
) -> *mut gst::ffi::GstElement {
use glib::once_cell::sync::Lazy;
static PIPELINE_QUARK: std::sync::OnceLock<glib::Quark> = std::sync::OnceLock::new();
static PIPELINE_QUARK: Lazy<glib::Quark> =
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<T: RTSPMediaFactoryImpl>(
// 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 (),

View file

@ -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]

View file

@ -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<gst::DebugCategory> = Lazy::new(|| {

View file

@ -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<glib::Quark> =
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<glib::Quark> =
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<ActionFunction>);
(*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),
);

View file

@ -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"

View file

@ -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")))]

View file

@ -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<Box<[crate::VideoFormat]>> = Lazy::new(|| unsafe {

View file

@ -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"

View file

@ -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<glib::Quark> =
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<glib::Quark> =
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 _,
);
}

View file

@ -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)]

View file

@ -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<glib::Type> = 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<T, F: FnMut(T) -> bool>(

View file

@ -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;

View file

@ -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<crate::Allocator> = 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<crate::Allocator> = std::sync::OnceLock::new();
static TYPE_INFO: TypeInfoWrap = TypeInfoWrap(glib::gobject_ffi::GTypeInfo {
class_size: mem::size_of::<ffi::GstAllocatorClass>() 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::<ffi::GstAllocator>() 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::<ffi::GstAllocatorClass>() 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::<ffi::GstAllocator>() 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,

View file

@ -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<glib::Quark> = std::sync::OnceLock::new();
static TRANSFORM_COPY: Lazy<glib::Quark> = 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"

View file

@ -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<Vec<(u32, String)>> = Lazy::new(|| {
static SORTED_VALUES: std::sync::OnceLock<Vec<(u32, String)>> = 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) {

View file

@ -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<ElementMetadata> = Lazy::new(|| {
static ELEMENT_METADATA: std::sync::OnceLock<ElementMetadata> =
std::sync::OnceLock::new();
Some(ELEMENT_METADATA.get_or_init(|| {
ElementMetadata::new(
"Test Element",
"Generic",
"Does nothing",
"Sebastian Dröge <sebastian@centricular.com>",
)
});
Some(&*ELEMENT_METADATA)
}))
}
fn pad_templates() -> &'static [PadTemplate] {
use glib::once_cell::sync::Lazy;
static PAD_TEMPLATES: Lazy<Vec<PadTemplate>> = Lazy::new(|| {
static PAD_TEMPLATES: std::sync::OnceLock<Vec<PadTemplate>> =
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(

View file

@ -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},