Commit ab14ae36 authored by Rémi Denis-Courmont's avatar Rémi Denis-Courmont

wasapi: clock synchronization

This currently assumes that VLC uses QueryPerformanceTimer() in its
implementation of mdate(). This is currently true but... ?
parent cb98770d
...@@ -50,6 +50,7 @@ struct aout_sys_t ...@@ -50,6 +50,7 @@ struct aout_sys_t
{ {
IAudioClient *client; IAudioClient *client;
IAudioRenderClient *render; IAudioRenderClient *render;
IAudioClock *clock;
UINT32 frames; /**< Total buffer size (frames) */ UINT32 frames; /**< Total buffer size (frames) */
HANDLE done; /**< Semaphore for MTA thread */ HANDLE done; /**< Semaphore for MTA thread */
}; };
...@@ -60,8 +61,17 @@ static void Play(audio_output_t *aout, block_t *block) ...@@ -60,8 +61,17 @@ static void Play(audio_output_t *aout, block_t *block)
HRESULT hr; HRESULT hr;
CoInitializeEx(NULL, COINIT_MULTITHREADED); 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; UINT32 frames;
hr = IAudioClient_GetCurrentPadding(sys->client, &frames); hr = IAudioClient_GetCurrentPadding(sys->client, &frames);
...@@ -93,14 +103,17 @@ static void Play(audio_output_t *aout, block_t *block) ...@@ -93,14 +103,17 @@ static void Play(audio_output_t *aout, block_t *block)
msg_Err(aout, "cannot release buffer (error 0x%lx)", hr); msg_Err(aout, "cannot release buffer (error 0x%lx)", hr);
break; break;
} }
IAudioClient_Start(sys->client);
block->p_buffer += copy; block->p_buffer += copy;
block->i_buffer -= copy; block->i_buffer -= copy;
block->i_nb_samples -= frames; block->i_nb_samples -= frames;
if (block->i_nb_samples == 0)
break; /* done */
/* FIXME: implement synchro */ /* Out of buffer space, sleep */
IAudioClient_Start(sys->client); msleep(AOUT_MIN_PREPARE_TIME
Sleep(AOUT_MIN_PREPARE_TIME / 1000); + block->i_nb_samples * CLOCK_FREQ / aout->format.i_rate);
} }
CoUninitialize(); CoUninitialize();
...@@ -112,13 +125,14 @@ static void Pause(audio_output_t *aout, bool paused, mtime_t date) ...@@ -112,13 +125,14 @@ static void Pause(audio_output_t *aout, bool paused, mtime_t date)
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
HRESULT hr; HRESULT hr;
if (!paused)
return;
CoInitializeEx(NULL, COINIT_MULTITHREADED); CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (paused)
hr = IAudioClient_Stop(sys->client); hr = IAudioClient_Stop(sys->client);
else
hr = IAudioClient_Start(sys->client);
if (FAILED(hr)) 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(); CoUninitialize();
(void) date; (void) date;
} }
...@@ -243,6 +257,7 @@ static int Open(vlc_object_t *obj) ...@@ -243,6 +257,7 @@ static int Open(vlc_object_t *obj)
return VLC_ENOMEM; return VLC_ENOMEM;
sys->client = NULL; sys->client = NULL;
sys->render = NULL; sys->render = NULL;
sys->clock = NULL;
sys->done = NULL; sys->done = NULL;
hr = CoInitializeEx(NULL, COINIT_MULTITHREADED); hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
...@@ -343,6 +358,11 @@ static int Open(vlc_object_t *obj) ...@@ -343,6 +358,11 @@ static int Open(vlc_object_t *obj)
goto error; 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); sys->done = CreateSemaphore(NULL, 0, 1, NULL);
if (unlikely(sys->done == NULL)) if (unlikely(sys->done == NULL))
goto error; goto error;
...@@ -361,6 +381,8 @@ static int Open(vlc_object_t *obj) ...@@ -361,6 +381,8 @@ static int Open(vlc_object_t *obj)
error: error:
if (sys->done != NULL) if (sys->done != NULL)
CloseHandle(sys->done); CloseHandle(sys->done);
if (sys->clock != NULL)
IAudioClock_Release(sys->clock);
if (sys->render != NULL) if (sys->render != NULL)
IAudioRenderClient_Release(sys->render); IAudioRenderClient_Release(sys->render);
if (sys->client != NULL) if (sys->client != NULL)
...@@ -376,6 +398,8 @@ static void Close (vlc_object_t *obj) ...@@ -376,6 +398,8 @@ static void Close (vlc_object_t *obj)
aout_sys_t *sys = aout->sys; aout_sys_t *sys = aout->sys;
CoInitializeEx(NULL, COINIT_MULTITHREADED); CoInitializeEx(NULL, COINIT_MULTITHREADED);
IAudioClient_Stop(sys->client); /* should not be needed */
IAudioClock_Release(sys->clock);
IAudioRenderClient_Release(sys->render); IAudioRenderClient_Release(sys->render);
IAudioClient_Release(sys->client); IAudioClient_Release(sys->client);
CoUninitialize(); CoUninitialize();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment