From f107f7306b8cae4423feb8080311b1d1408bd0c1 Mon Sep 17 00:00:00 2001 From: Ilya Konstantinov Date: Sat, 21 Mar 2015 20:34:25 +0200 Subject: [PATCH] osxaudio: Fix lockup in _audio_unit_property_listener _audio_unit_property_listener is called either from a Core Audio thread or as a result of a Core Audio API (e.g. AudioUnitInitialize) from our own thread. In the latter case, osxbuf can be already locked (GStreamer's mutex is not recursive). We introduce the flag cached_caps_valid and use it instead of nullifying cached_caps when we cannot lock on osxbuf. https://bugzilla.gnome.org/show_bug.cgi?id=743758 --- sys/osxaudio/gstosxaudiosink.c | 2 +- sys/osxaudio/gstosxaudiosrc.c | 2 +- sys/osxaudio/gstosxcoreaudio.c | 17 +++++++++++++---- sys/osxaudio/gstosxcoreaudio.h | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/sys/osxaudio/gstosxaudiosink.c b/sys/osxaudio/gstosxaudiosink.c index cfd7913..b0a3431 100644 --- a/sys/osxaudio/gstosxaudiosink.c +++ b/sys/osxaudio/gstosxaudiosink.c @@ -344,7 +344,7 @@ gst_osx_audio_sink_getcaps (GstBaseSink * sink, GstCaps * filter) /* protect against cached_caps going away */ GST_OBJECT_LOCK (buf); - if (osxbuf->core_audio->cached_caps) { + if (osxbuf->core_audio->cached_caps_valid) { GST_LOG_OBJECT (sink, "Returning cached caps"); caps = gst_caps_ref (osxbuf->core_audio->cached_caps); } else if (buf->open) { diff --git a/sys/osxaudio/gstosxaudiosrc.c b/sys/osxaudio/gstosxaudiosrc.c index 692461b..0deda90 100644 --- a/sys/osxaudio/gstosxaudiosrc.c +++ b/sys/osxaudio/gstosxaudiosrc.c @@ -265,7 +265,7 @@ gst_osx_audio_src_get_caps (GstBaseSrc * src, GstCaps * filter) /* protect against cached_caps going away */ GST_OBJECT_LOCK (buf); - if (osxbuf->core_audio->cached_caps) { + if (osxbuf->core_audio->cached_caps_valid) { GST_LOG_OBJECT (src, "Returning cached caps"); caps = gst_caps_ref (osxbuf->core_audio->cached_caps); } else if (buf->open) { diff --git a/sys/osxaudio/gstosxcoreaudio.c b/sys/osxaudio/gstosxcoreaudio.c index 666846c..52ac480 100644 --- a/sys/osxaudio/gstosxcoreaudio.c +++ b/sys/osxaudio/gstosxcoreaudio.c @@ -49,6 +49,7 @@ gst_core_audio_init (GstCoreAudio * core_audio) core_audio->is_src = FALSE; core_audio->audiounit = NULL; core_audio->cached_caps = NULL; + core_audio->cached_caps_valid = FALSE; #ifndef HAVE_IOS core_audio->hog_pid = -1; core_audio->disabled_mixing = FALSE; @@ -83,10 +84,13 @@ _audio_unit_property_listener (void *inRefCon, AudioUnit inUnit, * as needed. * This merely "refreshes" our PREFERRED caps. */ - /* protect against cached_caps going away */ - GST_OBJECT_LOCK (core_audio->osxbuf); - gst_caps_replace (&core_audio->cached_caps, NULL); - GST_OBJECT_UNLOCK (core_audio->osxbuf); + /* This function is called either from a Core Audio thread + * or as a result of a Core Audio API (e.g. AudioUnitInitialize) + * from our own thread. In the latter case, osxbuf can be + * already locked (GStreamer's mutex is not recursive). + * For this reason we use a boolean flag instead of nullifying + * cached_caps. */ + core_audio->cached_caps_valid = FALSE; } break; } @@ -128,6 +132,7 @@ gst_core_audio_close (GstCoreAudio * core_audio) core_audio); /* core_audio->osxbuf is already locked at this point */ + core_audio->cached_caps_valid = FALSE; gst_caps_replace (&core_audio->cached_caps, NULL); AudioComponentInstanceDispose (core_audio->audiounit); @@ -140,6 +145,10 @@ gst_core_audio_open (GstCoreAudio * core_audio) { OSStatus status; + /* core_audio->osxbuf is already locked at this point */ + core_audio->cached_caps_valid = FALSE; + gst_caps_replace (&core_audio->cached_caps, NULL); + if (!gst_core_audio_open_impl (core_audio)) return FALSE; diff --git a/sys/osxaudio/gstosxcoreaudio.h b/sys/osxaudio/gstosxcoreaudio.h index 71be235..fce85d0 100644 --- a/sys/osxaudio/gstosxcoreaudio.h +++ b/sys/osxaudio/gstosxcoreaudio.h @@ -88,6 +88,7 @@ struct _GstCoreAudio gboolean is_src; gboolean is_passthrough; AudioDeviceID device_id; + gboolean cached_caps_valid; /* thread-safe flag */ GstCaps *cached_caps; gint stream_idx; gboolean io_proc_active; -- 2.7.4