summaryrefslogtreecommitdiffstats
path: root/audio/out/ao_wasapi.c
diff options
context:
space:
mode:
authorKevin Mitchell <kevmitch@gmail.com>2015-02-22 18:47:50 -0800
committerKevin Mitchell <kevmitch@gmail.com>2015-02-23 14:01:05 -0800
commit446fd5a43a56f15d7ecec5fb65544adeee0be72f (patch)
tree72555a09f6543cd31fc3427be9e594f7669f3078 /audio/out/ao_wasapi.c
parent36011c7f6dbda356d64af3866305a036044333fa (diff)
downloadmpv-446fd5a43a56f15d7ecec5fb65544adeee0be72f.tar.bz2
mpv-446fd5a43a56f15d7ecec5fb65544adeee0be72f.tar.xz
ao_wasapi: move reset into audio thread
This makes things a bit more deterministic. It ensures that the audio thread isn't doing anything between IAudioClient_Stop(), IAudioClient_Reset() and setting the sample_count to 0. Buffer overfilling on resume is still a problem in exclusive mode (see next commit).
Diffstat (limited to 'audio/out/ao_wasapi.c')
-rw-r--r--audio/out/ao_wasapi.c45
1 files changed, 36 insertions, 9 deletions
diff --git a/audio/out/ao_wasapi.c b/audio/out/ao_wasapi.c
index 1b99c4136a..89f51c4295 100644
--- a/audio/out/ao_wasapi.c
+++ b/audio/out/ao_wasapi.c
@@ -113,6 +113,31 @@ exit_label:
return;
}
+static void thread_reset(struct ao *ao)
+{
+ struct wasapi_state *state = (struct wasapi_state *)ao->priv;
+ HRESULT hr;
+ MP_DBG(state, "Thread Reset\n");
+ hr = IAudioClient_Stop(state->pAudioClient);
+ /* we may get S_FALSE if the stream is already stopped */
+ if (hr != S_OK &&
+ hr != S_FALSE) {
+ MP_ERR(state, "IAudioClient_Stop returned: %s (0x%"PRIx32")\n",
+ wasapi_explain_err(hr), (uint32_t) hr);
+ }
+
+ /* we may get S_FALSE if the stream is already reset */
+ hr = IAudioClient_Reset(state->pAudioClient);
+ if (hr != S_OK &&
+ hr != S_FALSE) {
+ MP_ERR(state, "IAudioClient_Reset returned: %s (0x%"PRIx32")\n",
+ wasapi_explain_err(hr), (uint32_t) hr);
+ }
+
+ atomic_store(&state->sample_count, 0);
+ return;
+}
+
static DWORD __stdcall ThreadLoop(void *lpParameter)
{
struct ao *ao = lpParameter;
@@ -126,10 +151,10 @@ static DWORD __stdcall ThreadLoop(void *lpParameter)
DWORD waitstatus;
HANDLE playcontrol[] =
- {state->hUninit, state->hFeed, state->hForceFeed, NULL};
+ {state->hUninit, state->hFeed, state->hForceFeed, state->hReset, NULL};
MP_DBG(ao, "Entering dispatch loop\n");
while (true) { /* watch events */
- waitstatus = MsgWaitForMultipleObjects(3, playcontrol, FALSE, INFINITE,
+ waitstatus = MsgWaitForMultipleObjects(4, playcontrol, FALSE, INFINITE,
QS_POSTMESSAGE | QS_SENDMESSAGE);
switch (waitstatus) {
case WAIT_OBJECT_0: /*shutdown*/
@@ -142,12 +167,15 @@ static DWORD __stdcall ThreadLoop(void *lpParameter)
thread_feed(ao);
SetEvent(state->hFeedDone);
break;
- case (WAIT_OBJECT_0 + 3): /* messages to dispatch (COM marshalling) */
+ case (WAIT_OBJECT_0 + 3): /* reset */
+ thread_reset(ao);
+ break;
+ case (WAIT_OBJECT_0 + 4): /* messages to dispatch (COM marshalling) */
MP_DBG(ao, "Dispatch\n");
wasapi_dispatch();
break;
default:
- MP_ERR(ao, "Unhandled case in thread loop");
+ MP_ERR(ao, "Unhandled case in thread loop\n");
goto exit_label;
}
}
@@ -167,6 +195,7 @@ static void closehandles(struct ao *ao)
if (state->hFeed) CloseHandle(state->hFeed);
if (state->hForceFeed) CloseHandle(state->hForceFeed);
if (state->hFeedDone) CloseHandle(state->hFeedDone);
+ if (state->hReset) CloseHandle(state->hReset);
if (state->threadLoop) CloseHandle(state->threadLoop);
}
@@ -222,8 +251,9 @@ static int init(struct ao *ao)
state->hFeed = CreateEventW(NULL, FALSE, FALSE, NULL); /* for wasapi event mode */
state->hForceFeed = CreateEventW(NULL, FALSE, FALSE, NULL);
state->hFeedDone = CreateEventW(NULL, FALSE, FALSE, NULL);
+ state->hReset = CreateEventW(NULL, FALSE, FALSE, NULL);
if (!state->init_done || !state->hFeed || !state->hUninit ||
- !state->hForceFeed || !state->hFeedDone)
+ !state->hForceFeed || !state->hFeedDone || !state->hReset)
{
MP_ERR(ao, "Error initing events\n");
uninit(ao);
@@ -335,10 +365,7 @@ static int control(struct ao *ao, enum aocontrol cmd, void *arg)
static void audio_reset(struct ao *ao)
{
struct wasapi_state *state = (struct wasapi_state *)ao->priv;
-
- IAudioClient_Stop(state->pAudioClientProxy);
- IAudioClient_Reset(state->pAudioClientProxy);
- atomic_store(&state->sample_count, 0);
+ SetEvent(state->hReset);
}
static void audio_resume(struct ao *ao)