osxaudio: Fix deadlock and property change notification in device selection code

After creating the ringbuffer we have to set the device on the ringbuffer as
it defaults to kAudioDeviceUnknown. At this point it can't have changed to
anything else yet and we don't have to notify about changes to the sink/src
"device" property. It's also not a good idea because GstAudioBaseSrc has the
object lock taken while the ringbuffer is created, which might cause a
deadlock if something calls back into the element from "notify::device".

Once the base class is done with the NULL_TO_READY state change, it has opened
the device via the ringbuffer and this might have chosen a different device.
Especially if we initially used kAudioDeviceUnknown. Also notify about this
property change as initially intended by this code.
This commit is contained in:
Sebastian Dröge 2014-12-22 10:23:01 +01:00
parent 2a1459c88f
commit e7b10a107d
2 changed files with 19 additions and 11 deletions

View file

@ -274,13 +274,14 @@ gst_osx_audio_sink_change_state (GstElement * element,
case GST_STATE_CHANGE_NULL_TO_READY:
/* Device has been selected, AudioUnit set up, so initialize volume */
gst_osx_audio_sink_set_volume (osxsink);
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
/* The device is open now, so fix our device_id if it changed */
ringbuffer =
GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SINK (osxsink)->ringbuffer);
osxsink->device_id = ringbuffer->core_audio->device_id;
if (ringbuffer->core_audio->device_id != osxsink->device_id) {
osxsink->device_id = ringbuffer->core_audio->device_id;
g_object_notify (G_OBJECT (osxsink), "device");
}
break;
default:
@ -520,10 +521,12 @@ gst_osx_audio_sink_create_ringbuffer (GstAudioBaseSink * sink)
GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsink);
ringbuffer->core_audio->is_src = FALSE;
if (ringbuffer->core_audio->device_id != osxsink->device_id) {
/* By default the coreaudio instance created by the ringbuffer
* has device_id==kAudioDeviceUnknown. The user might have
* selected a different one here
*/
if (ringbuffer->core_audio->device_id != osxsink->device_id)
ringbuffer->core_audio->device_id = osxsink->device_id;
g_object_notify (G_OBJECT (osxsink), "device");
}
return GST_AUDIO_RING_BUFFER (ringbuffer);
}

View file

@ -229,11 +229,14 @@ gst_osx_audio_src_change_state (GstElement * element, GstStateChange transition)
goto out;
switch (transition) {
case GST_STATE_CHANGE_READY_TO_PAUSED:
case GST_STATE_CHANGE_NULL_TO_READY:
/* The device is open now, so fix our device_id if it changed */
ringbuffer =
GST_OSX_AUDIO_RING_BUFFER (GST_AUDIO_BASE_SRC (osxsrc)->ringbuffer);
osxsrc->device_id = ringbuffer->core_audio->device_id;
if (ringbuffer->core_audio->device_id != osxsrc->device_id) {
osxsrc->device_id = ringbuffer->core_audio->device_id;
g_object_notify (G_OBJECT (osxsrc), "device");
}
break;
default:
@ -369,10 +372,12 @@ gst_osx_audio_src_create_ringbuffer (GstAudioBaseSrc * src)
GST_OSX_AUDIO_ELEMENT_GET_INTERFACE (osxsrc);
ringbuffer->core_audio->is_src = TRUE;
if (ringbuffer->core_audio->device_id != osxsrc->device_id) {
/* By default the coreaudio instance created by the ringbuffer
* has device_id==kAudioDeviceUnknown. The user might have
* selected a different one here
*/
if (ringbuffer->core_audio->device_id != osxsrc->device_id)
ringbuffer->core_audio->device_id = osxsrc->device_id;
g_object_notify (G_OBJECT (osxsrc), "device");
}
return GST_AUDIO_RING_BUFFER (ringbuffer);
}