[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