equalizer: Make changes to band properties and the number of bands threadsafe

This commit is contained in:
Sebastian Dröge 2009-11-05 10:45:59 +01:00
parent 025e26f73a
commit 64e00f172c
3 changed files with 44 additions and 25 deletions

View file

@ -34,6 +34,9 @@
GST_DEBUG_CATEGORY (equalizer_debug); GST_DEBUG_CATEGORY (equalizer_debug);
#define GST_CAT_DEFAULT equalizer_debug #define GST_CAT_DEFAULT equalizer_debug
#define BANDS_LOCK(equ) g_mutex_lock(equ->bands_lock)
#define BANDS_UNLOCK(equ) g_mutex_unlock(equ->bands_lock)
static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface, static void gst_iir_equalizer_child_proxy_interface_init (gpointer g_iface,
gpointer iface_data); gpointer iface_data);
@ -157,6 +160,8 @@ gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec) const GValue * value, GParamSpec * pspec)
{ {
GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object); GstIirEqualizerBand *band = GST_IIR_EQUALIZER_BAND (object);
GstIirEqualizer *equ =
GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band)));
switch (prop_id) { switch (prop_id) {
case PROP_GAIN:{ case PROP_GAIN:{
@ -165,13 +170,10 @@ gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
gain = g_value_get_double (value); gain = g_value_get_double (value);
GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain); GST_DEBUG_OBJECT (band, "gain = %lf -> %lf", band->gain, gain);
if (gain != band->gain) { if (gain != band->gain) {
GstIirEqualizer *equ = BANDS_LOCK (equ);
GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band)));
equ->need_new_coefficients = TRUE; equ->need_new_coefficients = TRUE;
band->gain = gain; band->gain = gain;
BANDS_UNLOCK (equ);
gst_object_unref (equ);
GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain); GST_DEBUG_OBJECT (band, "changed gain = %lf ", band->gain);
} }
break; break;
@ -182,12 +184,10 @@ gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
freq = g_value_get_double (value); freq = g_value_get_double (value);
GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq); GST_DEBUG_OBJECT (band, "freq = %lf -> %lf", band->freq, freq);
if (freq != band->freq) { if (freq != band->freq) {
GstIirEqualizer *equ = BANDS_LOCK (equ);
GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band)));
equ->need_new_coefficients = TRUE; equ->need_new_coefficients = TRUE;
band->freq = freq; band->freq = freq;
gst_object_unref (equ); BANDS_UNLOCK (equ);
GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq); GST_DEBUG_OBJECT (band, "changed freq = %lf ", band->freq);
} }
break; break;
@ -198,12 +198,10 @@ gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
width = g_value_get_double (value); width = g_value_get_double (value);
GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width); GST_DEBUG_OBJECT (band, "width = %lf -> %lf", band->width, width);
if (width != band->width) { if (width != band->width) {
GstIirEqualizer *equ = BANDS_LOCK (equ);
GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band)));
equ->need_new_coefficients = TRUE; equ->need_new_coefficients = TRUE;
band->width = width; band->width = width;
gst_object_unref (equ); BANDS_UNLOCK (equ);
GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width); GST_DEBUG_OBJECT (band, "changed width = %lf ", band->width);
} }
break; break;
@ -214,12 +212,10 @@ gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
type = g_value_get_enum (value); type = g_value_get_enum (value);
GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type); GST_DEBUG_OBJECT (band, "type = %d -> %d", band->type, type);
if (type != band->type) { if (type != band->type) {
GstIirEqualizer *equ = BANDS_LOCK (equ);
GST_IIR_EQUALIZER (gst_object_get_parent (GST_OBJECT (band)));
equ->need_new_coefficients = TRUE; equ->need_new_coefficients = TRUE;
band->type = type; band->type = type;
gst_object_unref (equ); BANDS_UNLOCK (equ);
GST_DEBUG_OBJECT (band, "changed type = %d ", band->type); GST_DEBUG_OBJECT (band, "changed type = %d ", band->type);
} }
break; break;
@ -228,6 +224,8 @@ gst_iir_equalizer_band_set_property (GObject * object, guint prop_id,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
gst_object_unref (equ);
} }
static void static void
@ -329,11 +327,19 @@ gst_iir_equalizer_child_proxy_get_child_by_index (GstChildProxy * child_proxy,
guint index) guint index)
{ {
GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy); GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy);
GstObject *ret;
g_return_val_if_fail (index < equ->freq_band_count, NULL); BANDS_LOCK (equ);
if (G_UNLIKELY (index >= equ->freq_band_count)) {
BANDS_UNLOCK (equ);
g_return_val_if_fail (index < equ->freq_band_count, NULL);
}
GST_LOG ("return child[%d] '%s'", index, GST_OBJECT_NAME (equ->bands[index])); ret = gst_object_ref (equ->bands[index]);
return (gst_object_ref (equ->bands[index])); BANDS_UNLOCK (equ);
GST_LOG ("return child[%d] '%s'", index, ret);
return ret;
} }
static guint static guint
@ -342,7 +348,7 @@ gst_iir_equalizer_child_proxy_get_children_count (GstChildProxy * child_proxy)
GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy); GstIirEqualizer *equ = GST_IIR_EQUALIZER (child_proxy);
GST_LOG ("we have %d children", equ->freq_band_count); GST_LOG ("we have %d children", equ->freq_band_count);
return (equ->freq_band_count); return equ->freq_band_count;
} }
static void static void
@ -386,6 +392,7 @@ gst_iir_equalizer_class_init (GstIirEqualizerClass * klass)
static void static void
gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class) gst_iir_equalizer_init (GstIirEqualizer * eq, GstIirEqualizerClass * g_class)
{ {
eq->bands_lock = g_mutex_new ();
eq->need_new_coefficients = TRUE; eq->need_new_coefficients = TRUE;
} }
@ -405,6 +412,8 @@ gst_iir_equalizer_finalize (GObject * object)
g_free (equ->bands); g_free (equ->bands);
g_free (equ->history); g_free (equ->history);
g_mutex_free (equ->bands_lock);
G_OBJECT_CLASS (parent_class)->finalize (object); G_OBJECT_CLASS (parent_class)->finalize (object);
} }
@ -583,6 +592,7 @@ setup_high_shelf_filter (GstIirEqualizer * equ, GstIirEqualizerBand * band)
} }
} }
/* Must be called with bands_lock and transform lock! */
static void static void
set_passthrough (GstIirEqualizer * equ) set_passthrough (GstIirEqualizer * equ)
{ {
@ -597,6 +607,7 @@ set_passthrough (GstIirEqualizer * equ)
GST_DEBUG ("Passthrough mode: %d\n", passthrough); GST_DEBUG ("Passthrough mode: %d\n", passthrough);
} }
/* Must be called with bands_lock and transform lock! */
static void static void
update_coefficients (GstIirEqualizer * equ) update_coefficients (GstIirEqualizer * equ)
{ {
@ -614,6 +625,7 @@ update_coefficients (GstIirEqualizer * equ)
equ->need_new_coefficients = FALSE; equ->need_new_coefficients = FALSE;
} }
/* Must be called with transform lock! */
static void static void
alloc_history (GstIirEqualizer * equ) alloc_history (GstIirEqualizer * equ)
{ {
@ -634,6 +646,13 @@ gst_iir_equalizer_compute_frequencies (GstIirEqualizer * equ, guint new_count)
if (equ->freq_band_count == new_count) if (equ->freq_band_count == new_count)
return; return;
BANDS_LOCK (equ);
if (G_UNLIKELY (equ->freq_band_count == new_count)) {
BANDS_UNLOCK (equ);
return;
}
old_count = equ->freq_band_count; old_count = equ->freq_band_count;
equ->freq_band_count = new_count; equ->freq_band_count = new_count;
GST_DEBUG ("bands %u -> %u", old_count, new_count); GST_DEBUG ("bands %u -> %u", old_count, new_count);
@ -692,6 +711,7 @@ gst_iir_equalizer_compute_frequencies (GstIirEqualizer * equ, guint new_count)
equ->bands[new_count - 1]->type = BAND_TYPE_HIGH_SHELF; equ->bands[new_count - 1]->type = BAND_TYPE_HIGH_SHELF;
equ->need_new_coefficients = TRUE; equ->need_new_coefficients = TRUE;
BANDS_UNLOCK (equ);
} }
/* start of code that is type specific */ /* start of code that is type specific */
@ -809,10 +829,12 @@ gst_iir_equalizer_transform_ip (GstBaseTransform * btrans, GstBuffer * buf)
if (G_UNLIKELY (filter->format.channels < 1 || equ->process == NULL)) if (G_UNLIKELY (filter->format.channels < 1 || equ->process == NULL))
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
BANDS_LOCK (equ);
if (equ->need_new_coefficients) { if (equ->need_new_coefficients) {
update_coefficients (equ); update_coefficients (equ);
set_passthrough (equ); set_passthrough (equ);
} }
BANDS_UNLOCK (equ);
if (gst_base_transform_is_passthrough (btrans)) if (gst_base_transform_is_passthrough (btrans))
return GST_FLOW_OK; return GST_FLOW_OK;

View file

@ -52,6 +52,7 @@ struct _GstIirEqualizer
/*< private >*/ /*< private >*/
GMutex *bands_lock;
GstIirEqualizerBand **bands; GstIirEqualizerBand **bands;
/* properties */ /* properties */

View file

@ -142,8 +142,6 @@ gst_iir_equalizer_nbands_set_property (GObject * object, guint prop_id,
{ {
GstIirEqualizer *equ = GST_IIR_EQUALIZER (object); GstIirEqualizer *equ = GST_IIR_EQUALIZER (object);
GST_BASE_TRANSFORM_LOCK (equ);
GST_OBJECT_LOCK (equ);
switch (prop_id) { switch (prop_id) {
case PROP_NUM_BANDS: case PROP_NUM_BANDS:
gst_iir_equalizer_compute_frequencies (equ, g_value_get_uint (value)); gst_iir_equalizer_compute_frequencies (equ, g_value_get_uint (value));
@ -152,8 +150,6 @@ gst_iir_equalizer_nbands_set_property (GObject * object, guint prop_id,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break; break;
} }
GST_OBJECT_UNLOCK (equ);
GST_BASE_TRANSFORM_UNLOCK (equ);
} }
static void static void