[vlc-devel] [PATCH 5/5] wasapi: add an option to handle exclusive mode

Thomas Guillem thomas at gllm.fr
Fri Oct 25 12:38:04 CEST 2019


https://docs.microsoft.com/en-us/windows/win32/coreaudio/exclusive-mode-streams

"Applications that use exclusive-mode streams often do so because they require low latencies in the data paths between the audio endpoint devices and the application threads that access the endpoint buffers."


On Fri, Oct 25, 2019, at 12:18, Rémi Denis-Courmont wrote:
> I don't see how it reduces latency, no. Audio latency is largely bound by the packet/period size, not by exclusive mode.
> 
> Le 25 octobre 2019 10:17:21 GMT+03:00, Thomas Guillem <thomas at gllm.fr> a écrit :
>> 
>> 
>> On Thu, Oct 24, 2019, at 20:55, Rémi Denis-Courmont wrote:
>>> 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.
>> 
>> An other point of exclusive is to reduce the audio latency.
>> 
>> > 
>>> -- 
>>> レミ・デニ-クールモン
>>> http://www.remlab.net/vlc-devel mailing list
>>> To unsubscribe or modify your subscription options:
>>> https://mailman.videolan.org/listinfo/vlc-devel
>> vlc-devel mailing list
>> To unsubscribe or modify your subscription options:
>> https://mailman.videolan.org/listinfo/vlc-devel
> 
> -- 
> Envoyé de mon appareil Android avec Courriel K-9 Mail. Veuillez excuser ma brièveté. 
> _______________________________________________
> vlc-devel mailing list
> To unsubscribe or modify your subscription options:
> https://mailman.videolan.org/listinfo/vlc-devel
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/vlc-devel/attachments/20191025/878fffaf/attachment.html>


More information about the vlc-devel mailing list