From 309269a93b7f193c5cb77baa9ea9e67b68146b04 Mon Sep 17 00:00:00 2001 From: Guillaume Desmottes Date: Fri, 23 Apr 2021 12:07:52 +0200 Subject: [PATCH] level: make properties thread-safe Part-of: --- gst/level/gstlevel.c | 35 ++++++++++++++++++++++++++++------- gst/level/gstlevel.h | 4 ++-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/gst/level/gstlevel.c b/gst/level/gstlevel.c index 33dbd86c63..968fd4fe72 100644 --- a/gst/level/gstlevel.c +++ b/gst/level/gstlevel.c @@ -203,12 +203,13 @@ gst_level_class_init (GstLevelClass * klass) } static void -configure_passthrough (GstLevel * self) +configure_passthrough (GstLevel * self, gboolean audio_level_meta) { /* can't use passthrough if audio-level-meta is enabled as we need a - * writable buffer to add the meta. */ + * writable buffer to add the meta. + * gst_base_transform_set_passthrough() takes the object lock internally. */ gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (self), - !self->audio_level_meta); + !audio_level_meta); } static void @@ -232,7 +233,7 @@ gst_level_init (GstLevel * filter) filter->process = NULL; gst_base_transform_set_gap_aware (GST_BASE_TRANSFORM (filter), TRUE); - configure_passthrough (filter); + configure_passthrough (filter, filter->audio_level_meta); } static void @@ -263,6 +264,8 @@ gst_level_set_property (GObject * object, guint prop_id, { GstLevel *filter = GST_LEVEL (object); + GST_OBJECT_LOCK (filter); + switch (prop_id) { case PROP_POST_MESSAGES: /* fall-through */ @@ -271,8 +274,6 @@ gst_level_set_property (GObject * object, guint prop_id, break; case PROP_INTERVAL: filter->interval = g_value_get_uint64 (value); - /* Not exactly thread-safe, but property does not advertise that it - * can be changed at runtime anyway */ if (GST_AUDIO_INFO_RATE (&filter->info)) { gst_level_recalc_interval_frames (filter); } @@ -286,12 +287,16 @@ gst_level_set_property (GObject * object, guint prop_id, break; case PROP_AUDIO_LEVEL_META: filter->audio_level_meta = g_value_get_boolean (value); - configure_passthrough (filter); + GST_OBJECT_UNLOCK (filter); + configure_passthrough (filter, g_value_get_boolean (value)); + GST_OBJECT_LOCK (filter); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_OBJECT_UNLOCK (filter); } static void @@ -300,6 +305,8 @@ gst_level_get_property (GObject * object, guint prop_id, { GstLevel *filter = GST_LEVEL (object); + GST_OBJECT_LOCK (filter); + switch (prop_id) { case PROP_POST_MESSAGES: /* fall-through */ @@ -322,6 +329,8 @@ gst_level_get_property (GObject * object, guint prop_id, G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } + + GST_OBJECT_UNLOCK (filter); } @@ -410,6 +419,7 @@ gst_level_calculate_gdouble (gpointer data, guint num, guint channels, } */ +/* called with object lock */ static void gst_level_recalc_interval_frames (GstLevel * level) { @@ -444,6 +454,8 @@ gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out) if (!gst_audio_info_from_caps (&info, in)) return FALSE; + GST_OBJECT_LOCK (filter); + switch (GST_AUDIO_INFO_FORMAT (&info)) { case GST_AUDIO_FORMAT_S8: filter->process = gst_level_calculate_gint8; @@ -492,6 +504,7 @@ gst_level_set_caps (GstBaseTransform * trans, GstCaps * in, GstCaps * out) gst_level_recalc_interval_frames (filter); + GST_OBJECT_UNLOCK (filter); return TRUE; } @@ -628,6 +641,8 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) g_return_val_if_fail (num_int_samples % channels == 0, GST_FLOW_ERROR); + GST_OBJECT_LOCK (filter); + if (GST_BUFFER_FLAG_IS_SET (in, GST_BUFFER_FLAG_DISCONT)) { filter->message_ts = GST_BUFFER_TIMESTAMP (in); filter->num_frames = 0; @@ -720,9 +735,11 @@ gst_level_transform_ip (GstBaseTransform * trans, GstBuffer * in) gst_level_rtp_audio_level_meta (filter, in, -RMSdB); } + GST_OBJECT_UNLOCK (filter); return GST_FLOW_OK; } +/* called with object lock */ static void gst_level_post_message (GstLevel * filter) { @@ -778,7 +795,9 @@ gst_level_post_message (GstLevel * filter) filter->last_peak[i] = 0.0; } + GST_OBJECT_UNLOCK (filter); gst_element_post_message (GST_ELEMENT (filter), m); + GST_OBJECT_LOCK (filter); } filter->num_frames -= frames; @@ -792,7 +811,9 @@ gst_level_sink_event (GstBaseTransform * trans, GstEvent * event) if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { GstLevel *filter = GST_LEVEL (trans); + GST_OBJECT_LOCK (filter); gst_level_post_message (filter); + GST_OBJECT_UNLOCK (filter); } return GST_BASE_TRANSFORM_CLASS (parent_class)->sink_event (trans, event); diff --git a/gst/level/gstlevel.h b/gst/level/gstlevel.h index ff9871c5c9..d205bfa6c2 100644 --- a/gst/level/gstlevel.h +++ b/gst/level/gstlevel.h @@ -56,18 +56,18 @@ typedef struct _GstLevelClass GstLevelClass; struct _GstLevel { GstBaseTransform element; - /* properties */ + /* properties, protected by object lock */ gboolean post_messages; /* whether or not to post messages */ guint64 interval; /* how many nanoseconds between emits */ gdouble decay_peak_ttl; /* time to live for peak in nanoseconds */ gdouble decay_peak_falloff; /* falloff in dB/sec */ + gboolean audio_level_meta; /* whether or not generate GstAudioLevelMeta */ GstAudioInfo info; gint num_frames; /* frame count (1 sample per channel) * since last emit */ gint interval_frames; /* after how many frame to sent a message */ GstClockTime message_ts; /* starttime for next message */ - gboolean audio_level_meta; /* whether or not generate GstAudioLevelMeta */ /* per-channel arrays for intermediate values */ gdouble *CS; /* normalized Cumulative Square */ -- 2.34.1