[vlc-devel] [PATCH 5/5] wasapi: add an option to handle exclusive mode
Rémi Denis-Courmont
remi at remlab.net
Thu Oct 24 20:55:20 CEST 2019
Le torstaina 24. lokakuuta 2019, 15.37.13 EEST Thomas Guillem a écrit :
> cf. WASAPI_EXCLUSIVE_LONGTEXT
> ---
> modules/audio_output/wasapi.c | 174 +++++++++++++++++++++++++++++++++-
> 1 file changed, 170 insertions(+), 4 deletions(-)
>
> diff --git a/modules/audio_output/wasapi.c b/modules/audio_output/wasapi.c
> index daa946f8afc..91defb250fb 100644
> --- a/modules/audio_output/wasapi.c
> +++ b/modules/audio_output/wasapi.c
> @@ -588,6 +588,154 @@ static void Stop(aout_stream_t *s)
> free(sys);
> }
>
> +/*
> + * This function will try to find the closest PCM format that is accepted
> by + * the sound card. Exclusive here means a direct access to the sound
> card. The + * format arguments and the return code of this function behave
> exactly like + * IAudioClient_IsFormatSupported().
> + */
> +static HRESULT GetExclusivePCMFormat(IAudioClient *c, const WAVEFORMATEX
> *pwf, + WAVEFORMATEX **ppwf_closest) +{
> + HRESULT hr;
> + const AUDCLNT_SHAREMODE exclusive = AUDCLNT_SHAREMODE_EXCLUSIVE;
> +
> + *ppwf_closest = NULL;
> +
> + /* First try the input format */
> + hr = IAudioClient_IsFormatSupported(c, exclusive, pwf, NULL);
> +
> + if (hr != AUDCLNT_E_UNSUPPORTED_FORMAT)
> + {
> + assert(hr != S_FALSE); /* S_FALSE reserved for shared mode */
> + return hr;
> + }
> +
> + /* This format come from vlc_ToWave() */
> + assert(pwf->wFormatTag == WAVE_FORMAT_EXTENSIBLE);
> + const WAVEFORMATEXTENSIBLE *pwfe = (void *) pwf;
> + assert(IsEqualIID(&pwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_IEEE_FLOAT)
> + || IsEqualIID(&pwfe->SubFormat, &KSDATAFORMAT_SUBTYPE_PCM));
> +
> + /* Allocate the output closest format */
> + WAVEFORMATEXTENSIBLE *pwfe_closest =
> + CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE));
> + if (!pwfe_closest)
> + return E_FAIL;
> + WAVEFORMATEX *pwf_closest = &pwfe_closest->Format;
> +
> + /* Setup the fallback arrays. There are 3 properties to check: the
> format, + * the samplerate and the channels. There are maximum of 4
> formats to + * check, 3 samplerates, and 2 channels configuration. So,
> that is a + * maximum of 4x3x2=24 checks */
> +
> + /* The format fallback order is dependent of the input format. We don't
> + * want to use a high quality format when it's not needed but we
> prefer to + * use a high quality format instead of a lower one */
> + static const uint16_t bits_pcm8_fallback[] = { 8, 16, 24, 32 };
> + static const uint16_t bits_pcm16_fallback[] = { 16, 24, 32, 8 };
> + static const uint16_t bits_pcm24_fallback[] = { 24, 32, 16, 8 };
> + static const uint16_t bits_pcm32_fallback[] = { 32, 24, 16, 8 };
> +
> + static const size_t bits_fallback_size =
> ARRAY_SIZE(bits_pcm8_fallback); +
> + const uint16_t *bits_fallback;
> + switch (pwf->wBitsPerSample)
> + {
> + case 64: /* fall through */
> + case 32: bits_fallback = bits_pcm32_fallback; break;
> + case 24: bits_fallback = bits_pcm24_fallback; break;
> + case 16: bits_fallback = bits_pcm16_fallback; break;
> + case 8: bits_fallback = bits_pcm8_fallback; break;
> + default: vlc_assert_unreachable();
> + }
> +
> + /* Check the input samplerate, then 48kHz and 44.1khz */
> + const uint32_t samplerate_fallback[] = {
> + pwf->nSamplesPerSec,
> + pwf->nSamplesPerSec == 48000 ? 0 : 48000,
> + pwf->nSamplesPerSec == 44100 ? 0 : 44100,
> + };
> + const size_t samplerate_fallback_size =
> ARRAY_SIZE(samplerate_fallback); +
> + /* Check the input number of channels, then stereo */
> + const uint16_t channels_fallback[] = {
> + pwf->nChannels,
> + pwf->nChannels == 2 ? 0 : 2,
> + };
> + const size_t channels_fallback_size = ARRAY_SIZE(channels_fallback);
Really the only point in exclusive mode is bit exact. If you need to convert,
there is really no point, especially if the sample rate and/or the channel
mappings differ. This is waaaaay needlessly complicated.
--
レミ・デニ-クールモン
http://www.remlab.net/
More information about the vlc-devel
mailing list