From 3b7e292844f52783cdefe068bb7bc5cd35a8dcdb Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 28 Jun 2017 18:28:19 +0200 Subject: ao_wasapi: remove duplicate code for creating IAudioClient The code accounting for the terrible AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED semantics (which MSDN claims can happen "starting with Windows 7" - so probably on Windows 10 too) duplicated the call for creating the IAudioClient. That's not great, so get rid of it. Let wasapi_thread_init() handle this. It has a retry loop anyway. This redoes device lookup and format negotiation, but potential failures due to race conditions (what if the driver decides to change behavior) shouldn't be worse than before. --- audio/out/ao_wasapi_utils.c | 58 +++++++++++++++++++-------------------------- 1 file changed, 24 insertions(+), 34 deletions(-) diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index f1895eb49e..9751b82fac 100644 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -592,7 +592,7 @@ exit_label: mp_HRESULT_to_str(hr)); } -static HRESULT fix_format(struct ao *ao) +static HRESULT fix_format(struct ao *ao, bool align_hack) { struct wasapi_state *state = ao->priv; @@ -612,13 +612,20 @@ static HRESULT fix_format(struct ao *ao) bufferPeriod = bufferDuration = devicePeriod; } + // handle unsupported buffer size if AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED was + // returned in a previous attempt. hopefully this shouldn't happen because + // of the above integer device period + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd370875%28v=vs.85%29.aspx + if (align_hack) { + bufferDuration = (REFERENCE_TIME) (0.5 + + (10000.0 * 1000 / state->format.Format.nSamplesPerSec + * state->bufferFrameCount)); + if (state->share_mode == AUDCLNT_SHAREMODE_EXCLUSIVE) + bufferPeriod = bufferDuration; + } + ao->format = af_fmt_from_planar(ao->format); - // handle unsupported buffer size hopefully this shouldn't happen because of - // the above integer device period - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd370875%28v=vs.85%29.aspx - int retries=0; -reinit: MP_DBG(state, "IAudioClient::Initialize\n"); hr = IAudioClient_Initialize(state->pAudioClient, state->share_mode, @@ -627,33 +634,6 @@ reinit: bufferPeriod, &(state->format.Format), NULL); - // something about buffer sizes on Win7 - if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) { - if (retries > 0) { - EXIT_ON_ERROR(hr); - } else { - retries ++; - } - MP_VERBOSE(state, "IAudioClient::Initialize negotiation failed with %s," - "used %lld * 100ns\n", - mp_HRESULT_to_str(hr), bufferDuration); - - IAudioClient_GetBufferSize(state->pAudioClient, - &state->bufferFrameCount); - bufferDuration = (REFERENCE_TIME) (0.5 + - (10000.0 * 1000 / state->format.Format.nSamplesPerSec - * state->bufferFrameCount)); - if (state->share_mode == AUDCLNT_SHAREMODE_EXCLUSIVE) - bufferPeriod = bufferDuration; - - - IAudioClient_Release(state->pAudioClient); - state->pAudioClient = NULL; - hr = IMMDeviceActivator_Activate(state->pDevice, - &IID_IAudioClient, CLSCTX_ALL, - NULL, (void **)&state->pAudioClient); - goto reinit; - } EXIT_ON_ERROR(hr); MP_DBG(state, "IAudioClient::Initialize pRenderClient\n"); @@ -940,6 +920,7 @@ HRESULT wasapi_thread_init(struct ao *ao) struct wasapi_state *state = ao->priv; MP_DBG(ao, "Init wasapi thread\n"); int64_t retry_wait = 1; + bool align_hack = false; retry: ; HRESULT hr = load_device(ao->log, &state->pDevice, state->deviceID); EXIT_ON_ERROR(hr); @@ -957,7 +938,16 @@ retry: ; } MP_DBG(ao, "Fixing format\n"); - hr = fix_format(ao); + hr = fix_format(ao, align_hack); + if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED && !align_hack) { + // According to MSDN, we must use this as base after the failure. + IAudioClient_GetBufferSize(state->pAudioClient, + &state->bufferFrameCount); + SAFE_RELEASE(state->pAudioClient); + align_hack = true; + MP_WARN(ao, "This appears to require a weird Windows 7 hack. Retrying.\n"); + goto retry; + } if ((hr == AUDCLNT_E_DEVICE_IN_USE || hr == AUDCLNT_E_DEVICE_INVALIDATED) && retry_wait <= 8) { -- cgit v1.2.3