[vlc-devel] [RFC PATH] mmdevice: update device if the previous one failed
Thomas Guillem
thomas at gllm.fr
Thu Sep 15 11:10:09 CEST 2016
s->owner.device need to be updated with the new dev after DeviceSelect is
called.
This fix a crash when trying to load 2 time the same failing device (Once you
got a AUDCLNT_E_DEVICE_INVALIDATED error, you shouldn't use this device again).
closes #17391
== RFC ==
Not really sure about the lock in Start(). sys->dev need to be protected by
sys->lock since it can be modified from the MMThread. I'm affraid
vlc_module_load can take too much time and block callbacks that need this lock
(like vlc_AudioSessionEvents_OnSimpleVolumeChanged)
---
modules/audio_output/mmdevice.c | 18 +++++++++++++-----
1 file changed, 13 insertions(+), 5 deletions(-)
diff --git a/modules/audio_output/mmdevice.c b/modules/audio_output/mmdevice.c
index b48dbb3..170d316 100644
--- a/modules/audio_output/mmdevice.c
+++ b/modules/audio_output/mmdevice.c
@@ -732,7 +732,7 @@ static int DevicesEnum(audio_output_t *aout, IMMDeviceEnumerator *it)
return n;
}
-static int DeviceSelect(audio_output_t *aout, const char *id)
+static int DeviceSelectLocked(audio_output_t *aout, const char *id)
{
aout_sys_t *sys = aout->sys;
wchar_t *device;
@@ -746,14 +746,12 @@ static int DeviceSelect(audio_output_t *aout, const char *id)
else
device = default_device;
- EnterCriticalSection(&sys->lock);
assert(sys->device == NULL);
sys->device = device;
WakeConditionVariable(&sys->work);
while (sys->device != NULL)
SleepConditionVariableCS(&sys->ready, &sys->lock, INFINITE);
- LeaveCriticalSection(&sys->lock);
if (sys->stream != NULL && sys->dev != NULL)
/* Request restart of stream with the new device */
@@ -761,6 +759,14 @@ static int DeviceSelect(audio_output_t *aout, const char *id)
return (sys->dev != NULL) ? 0 : -1;
}
+static int DeviceSelect(audio_output_t *aout, const char *id)
+{
+ EnterCriticalSection(&aout->sys->lock);
+ int ret = DeviceSelectLocked(aout, id);
+ LeaveCriticalSection(&aout->sys->lock);
+ return ret;
+}
+
/*** Initialization / deinitialization **/
static wchar_t *var_InheritWide(vlc_object_t *obj, const char *name)
{
@@ -1080,20 +1086,22 @@ static int Start(audio_output_t *aout, audio_sample_format_t *restrict fmt)
if (unlikely(s == NULL))
return -1;
- s->owner.device = sys->dev;
s->owner.activate = ActivateDevice;
EnterMTA();
+ EnterCriticalSection(&sys->lock);
for (;;)
{
HRESULT hr;
+ s->owner.device = sys->dev;
/* TODO: Do not overload the "aout" configuration item. */
sys->module = vlc_module_load(s, "aout stream", "$aout", false,
aout_stream_Start, s, fmt, &hr);
- if (hr != AUDCLNT_E_DEVICE_INVALIDATED || DeviceSelect(aout, NULL))
+ if (hr != AUDCLNT_E_DEVICE_INVALIDATED || DeviceSelectLocked(aout, NULL))
break;
}
+ LeaveCriticalSection(&sys->lock);
LeaveMTA();
if (sys->module == NULL)
--
2.9.3
More information about the vlc-devel
mailing list