diff options
Diffstat (limited to 'audio/out/ao_wasapi_utils.c')
-rw-r--r-- | audio/out/ao_wasapi_utils.c | 55 |
1 files changed, 40 insertions, 15 deletions
diff --git a/audio/out/ao_wasapi_utils.c b/audio/out/ao_wasapi_utils.c index 55a16da812..a696040dba 100644 --- a/audio/out/ao_wasapi_utils.c +++ b/audio/out/ao_wasapi_utils.c @@ -299,8 +299,9 @@ static bool set_ao_format(struct ao *ao, WAVEFORMATEX *wf, } #define mp_format_res_str(hres) \ - (SUCCEEDED(hres) ? "ok" : ((hres) == AUDCLNT_E_UNSUPPORTED_FORMAT) \ - ? "unsupported" : mp_HRESULT_to_str(hres)) + (SUCCEEDED(hres) ? ((hres) == S_OK) ? "ok" : "close" \ + : ((hres) == AUDCLNT_E_UNSUPPORTED_FORMAT) \ + ? "unsupported" : mp_HRESULT_to_str(hres)) static bool try_format_exclusive(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat) { @@ -426,32 +427,57 @@ static bool find_formats_shared(struct ao *ao, WAVEFORMATEXTENSIBLE *wformat) { struct wasapi_state *state = ao->priv; - WAVEFORMATEX *closestMatch; - HRESULT hr = IAudioClient_IsFormatSupported(state->pAudioClient, - AUDCLNT_SHAREMODE_SHARED, - &wformat->Format, - &closestMatch); + struct mp_chmap channels; + if (!chmap_from_waveformat(&channels, &wformat->Format)) { + MP_ERR(ao, "Error converting channel map\n"); + return false; + } + + HRESULT hr; + WAVEFORMATEX *mix_format; + hr = IAudioClient_GetMixFormat(state->pAudioClient, &mix_format); + EXIT_ON_ERROR(hr); + + // WASAPI doesn't do any sample rate conversion on its own and + // will typically only accept the mix format samplerate. Although + // it will accept any PCM sample format, everything gets converted + // to the mix format anyway (pretty much always float32), so just + // use that. + WAVEFORMATEXTENSIBLE try_format; + waveformat_copy(&try_format, mix_format); + CoTaskMemFree(mix_format); + + // WASAPI may accept channel maps other than the mix format + // if a surround emulator is enabled. + change_waveformat_channels(&try_format, &channels); + + hr = IAudioClient_IsFormatSupported(state->pAudioClient, + AUDCLNT_SHAREMODE_SHARED, + &try_format.Format, + &mix_format); MP_VERBOSE(ao, "Trying %s (shared) -> %s\n", - waveformat_to_str(&wformat->Format), mp_format_res_str(hr)); + waveformat_to_str(&try_format.Format), mp_format_res_str(hr)); if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT) EXIT_ON_ERROR(hr); switch (hr) { case S_OK: + waveformat_copy(wformat, &try_format.Format); break; case S_FALSE: - waveformat_copy(wformat, closestMatch); - CoTaskMemFree(closestMatch); + waveformat_copy(wformat, mix_format); + CoTaskMemFree(mix_format); MP_VERBOSE(ao, "Closest match is %s\n", waveformat_to_str(&wformat->Format)); break; default: - hr = IAudioClient_GetMixFormat(state->pAudioClient, &closestMatch); + hr = IAudioClient_GetMixFormat(state->pAudioClient, &mix_format); EXIT_ON_ERROR(hr); - waveformat_copy(wformat, closestMatch); + waveformat_copy(wformat, mix_format); + CoTaskMemFree(mix_format); MP_VERBOSE(ao, "Fallback to mix format %s\n", waveformat_to_str(&wformat->Format)); - CoTaskMemFree(closestMatch); + } return true; @@ -525,9 +551,8 @@ static void init_session_display(struct wasapi_state *state) { (void **)&state->pSessionControl); EXIT_ON_ERROR(hr); - wchar_t path[MAX_PATH+12] = {0}; + wchar_t path[MAX_PATH] = {0}; GetModuleFileNameW(NULL, path, MAX_PATH); - wcscat(path, L",-IDI_ICON1"); hr = IAudioSessionControl_SetIconPath(state->pSessionControl, path, NULL); if (FAILED(hr)) { // don't goto exit_label here since SetDisplayName might still work |