[vlc-commits] [Git][videolan/vlc][3.0.x] mmdevice: move MTA initialization to the worker thread

Jean-Baptiste Kempf (@jbk) gitlab at videolan.org
Fri Jun 9 15:55:08 UTC 2023



Jean-Baptiste Kempf pushed to branch 3.0.x at VideoLAN / VLC


Commits:
26fb05e9 by Pierre Lamot at 2023-06-09T15:29:29+00:00
mmdevice: move MTA initialization to the worker thread

MTA was checked in the Open function. As this function is called from libvlc
thread, this implies that a user of libvlc should have its own thread in MTA
which may not be possible for various reasons.

* MuteSet, VolumeSet, Play, DeviceSelect, Close callback don't require MTA
* Flush, Pause and Start callbacks still require MTA, but as these functions are
  called from VLC internal threads this is a lesser issue

(cherry-picked from 2fa81b6f15f268e1aaeaf55d93f5bb628714d8cb)

- - - - -


1 changed file:

- modules/audio_output/mmdevice.c


Changes:

=====================================
modules/audio_output/mmdevice.c
=====================================
@@ -80,6 +80,12 @@ static void LeaveMTA(void)
 static wchar_t default_device[1] = L"";
 static char default_device_b[1] = "";
 
+enum initialisation_status_t {
+    INITIALISATION_PENDING,
+    INITIALISATION_FAILED,
+    INITIALISATION_SUCCEEDED,
+};
+
 struct aout_sys_t
 {
     aout_stream_t *stream; /**< Underlying audio output stream */
@@ -104,6 +110,7 @@ struct aout_sys_t
     CRITICAL_SECTION lock;
     CONDITION_VARIABLE work;
     CONDITION_VARIABLE ready;
+    enum initialisation_status_t initialisation_status;
     vlc_thread_t thread; /**< Thread for audio session control */
 };
 
@@ -858,6 +865,7 @@ static HRESULT MMSession(audio_output_t *aout, IMMDeviceEnumerator *it)
     }
 
     sys->requested_device = NULL;
+    sys->initialisation_status = INITIALISATION_SUCCEEDED;
     WakeConditionVariable(&sys->ready);
 
     if (SUCCEEDED(hr))
@@ -1064,12 +1072,27 @@ static void *MMThread(void *data)
 {
     audio_output_t *aout = data;
     aout_sys_t *sys = aout->sys;
-    IMMDeviceEnumerator *it = sys->it;
 
-    EnterMTA();
+    /* Initialize MMDevice API */
+    if (TryEnterMTA(aout))
+        goto error;
+
+    void *pv;
+    HRESULT hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
+                                  &IID_IMMDeviceEnumerator, &pv);
+    if (FAILED(hr))
+    {
+        msg_Dbg(aout, "cannot create device enumerator (error 0x%lX)", hr);
+        LeaveMTA();
+        goto error;
+    }
+
+    IMMDeviceEnumerator *it = pv;
+    sys->it = it;
+
     IMMDeviceEnumerator_RegisterEndpointNotificationCallback(it,
                                                           &sys->device_events);
-    HRESULT hr = DevicesEnum(it, MMThread_DevicesEnum_Added, aout);
+    hr = DevicesEnum(it, MMThread_DevicesEnum_Added, aout);
     if (FAILED(hr))
         msg_Warn(aout, "cannot enumerate audio endpoints (error 0x%lx)", hr);
 
@@ -1087,6 +1110,13 @@ static void *MMThread(void *data)
     IMMDeviceEnumerator_Release(it);
     LeaveMTA();
     return NULL;
+
+error:
+    EnterCriticalSection(&sys->lock);
+    sys->initialisation_status = INITIALISATION_FAILED;
+    WakeConditionVariable(&sys->ready);
+    LeaveCriticalSection(&sys->lock);
+    return NULL;
 }
 
 /**
@@ -1300,33 +1330,23 @@ static int Open(vlc_object_t *obj)
         sys->requested_device = default_device;
     }
 
-    /* Initialize MMDevice API */
-    if (TryEnterMTA(aout))
-        goto error;
-
-    void *pv;
-    HRESULT hr = CoCreateInstance(&CLSID_MMDeviceEnumerator, NULL, CLSCTX_ALL,
-                                  &IID_IMMDeviceEnumerator, &pv);
-    if (FAILED(hr))
-    {
-        LeaveMTA();
-        msg_Dbg(aout, "cannot create device enumerator (error 0x%lx)", hr);
-        goto error;
-    }
-    sys->it = pv;
-
+    sys->initialisation_status = INITIALISATION_PENDING;
     if (vlc_clone(&sys->thread, MMThread, aout, VLC_THREAD_PRIORITY_LOW))
     {
         IMMDeviceEnumerator_Release(sys->it);
-        LeaveMTA();
         goto error;
     }
 
     EnterCriticalSection(&sys->lock);
-    while (sys->requested_device != NULL)
+    while (sys->initialisation_status == INITIALISATION_PENDING)
         SleepConditionVariableCS(&sys->ready, &sys->lock, INFINITE);
     LeaveCriticalSection(&sys->lock);
-    LeaveMTA(); /* Leave MTA after thread has entered MTA */
+
+    if (sys->initialisation_status == INITIALISATION_FAILED)
+    {
+        vlc_join(sys->thread, NULL);
+        goto error;
+    }
 
     aout->start = Start;
     aout->stop = Stop;



View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/26fb05e95724bd19f9a144c51bc11f79c609f3bc

-- 
View it on GitLab: https://code.videolan.org/videolan/vlc/-/commit/26fb05e95724bd19f9a144c51bc11f79c609f3bc
You're receiving this email because of your account on code.videolan.org.


VideoLAN code repository instance


More information about the vlc-commits mailing list