[vlc-commits] wasapi: clock synchronization

Rémi Denis-Courmont git at videolan.org
Tue May 15 22:55:38 CEST 2012


vlc | branch: master | Rémi Denis-Courmont <remi at remlab.net> | Tue May 15 23:45:29 2012 +0300| [ab14ae3615648bd8f7058b814e9f33831ded4844] | committer: Rémi Denis-Courmont

wasapi: clock synchronization

This currently assumes that VLC uses QueryPerformanceTimer() in its
implementation of mdate(). This is currently true but... ?

> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=ab14ae3615648bd8f7058b814e9f33831ded4844
---

 modules/audio_output/wasapi.c |   42 ++++++++++++++++++++++++++++++++--------
 1 files changed, 33 insertions(+), 9 deletions(-)

diff --git a/modules/audio_output/wasapi.c b/modules/audio_output/wasapi.c
index 80bcff6..9865f99 100644
--- a/modules/audio_output/wasapi.c
+++ b/modules/audio_output/wasapi.c
@@ -50,6 +50,7 @@ struct aout_sys_t
 {
     IAudioClient *client;
     IAudioRenderClient *render;
+    IAudioClock *clock;
     UINT32 frames; /**< Total buffer size (frames) */
     HANDLE done; /**< Semaphore for MTA thread */
 };
@@ -60,8 +61,17 @@ static void Play(audio_output_t *aout, block_t *block)
     HRESULT hr;
 
     CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    if (likely(sys->clock != NULL))
+    {
+        UINT64 pos, qpcpos;
+
+        IAudioClock_GetPosition(sys->clock, &pos, &qpcpos);
+        qpcpos = (qpcpos + 5) / 10; /* 100ns -> 1µs */
+        /* NOTE: this assumes mdate() uses QPC() (which it currently does). */
+        aout_TimeReport(aout, qpcpos);
+    }
 
-    while (block->i_nb_samples > 0)
+    for (;;)
     {
         UINT32 frames;
         hr = IAudioClient_GetCurrentPadding(sys->client, &frames);
@@ -93,14 +103,17 @@ static void Play(audio_output_t *aout, block_t *block)
             msg_Err(aout, "cannot release buffer (error 0x%lx)", hr);
             break;
         }
+        IAudioClient_Start(sys->client);
 
         block->p_buffer += copy;
         block->i_buffer -= copy;
         block->i_nb_samples -= frames;
+        if (block->i_nb_samples == 0)
+            break; /* done */
 
-        /* FIXME: implement synchro */
-        IAudioClient_Start(sys->client);
-        Sleep(AOUT_MIN_PREPARE_TIME / 1000);
+        /* Out of buffer space, sleep */
+        msleep(AOUT_MIN_PREPARE_TIME
+             + block->i_nb_samples * CLOCK_FREQ / aout->format.i_rate);
     }
 
     CoUninitialize();
@@ -112,13 +125,14 @@ static void Pause(audio_output_t *aout, bool paused, mtime_t date)
     aout_sys_t *sys = aout->sys;
     HRESULT hr;
 
-    if (!paused)
-        return;
-
     CoInitializeEx(NULL, COINIT_MULTITHREADED);
-    hr = IAudioClient_Stop(sys->client);
+    if (paused)
+        hr = IAudioClient_Stop(sys->client);
+    else
+        hr = IAudioClient_Start(sys->client);
     if (FAILED(hr))
-        msg_Warn(aout, "cannot stop stream (error 0x%lx)", hr);
+        msg_Warn(aout, "cannot %s stream (error 0x%lx)",
+                 paused ? "stop" : "start", hr);
     CoUninitialize();
     (void) date;
 }
@@ -243,6 +257,7 @@ static int Open(vlc_object_t *obj)
         return VLC_ENOMEM;
     sys->client = NULL;
     sys->render = NULL;
+    sys->clock = NULL;
     sys->done = NULL;
 
     hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
@@ -343,6 +358,11 @@ static int Open(vlc_object_t *obj)
         goto error;
     }
 
+    hr = IAudioClient_GetService(sys->client, &IID_IAudioClock,
+                                 (void **)&sys->clock);
+    if (FAILED(hr))
+        msg_Warn(aout, "cannot get audio clock (error 0x%lx)", hr);
+
     sys->done = CreateSemaphore(NULL, 0, 1, NULL);
     if (unlikely(sys->done == NULL))
         goto error;
@@ -361,6 +381,8 @@ static int Open(vlc_object_t *obj)
 error:
     if (sys->done != NULL)
         CloseHandle(sys->done);
+    if (sys->clock != NULL)
+        IAudioClock_Release(sys->clock);
     if (sys->render != NULL)
         IAudioRenderClient_Release(sys->render);
     if (sys->client != NULL)
@@ -376,6 +398,8 @@ static void Close (vlc_object_t *obj)
     aout_sys_t *sys = aout->sys;
 
     CoInitializeEx(NULL, COINIT_MULTITHREADED);
+    IAudioClient_Stop(sys->client); /* should not be needed */
+    IAudioClock_Release(sys->clock);
     IAudioRenderClient_Release(sys->render);
     IAudioClient_Release(sys->client);
     CoUninitialize();



More information about the vlc-commits mailing list