vlc | branch: master | Thomas Guillem <[email protected]> | Mon May 2 15:48:49 2016 +0200| [a53aceb20dd4a0abe9d8147ccd6fe5e363c26717] | committer: Thomas Guillem
wasapi: implement pass-through Inspired by the directsound module > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=a53aceb20dd4a0abe9d8147ccd6fe5e363c26717 --- modules/audio_output/wasapi.c | 60 +++++++++++++++++++++++++++++++++++------ 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/modules/audio_output/wasapi.c b/modules/audio_output/wasapi.c index 2a588e2..63d0e91 100644 --- a/modules/audio_output/wasapi.c +++ b/modules/audio_output/wasapi.c @@ -40,6 +40,9 @@ #include <vlc_plugin.h> #include "audio_output/mmdevice.h" +DEFINE_GUID(_KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL, WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); +static const GUID __KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL = {WAVE_FORMAT_DOLBY_AC3_SPDIF, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; + static BOOL CALLBACK InitFreq(INIT_ONCE *once, void *param, void **context) { (void) once; (void) context; @@ -69,6 +72,7 @@ typedef struct aout_stream_sys vlc_fourcc_t format; /**< Sample format */ unsigned rate; /**< Sample rate */ unsigned bytes_per_frame; + unsigned frame_length; UINT64 written; /**< Frames written to the buffer */ UINT32 frames; /**< Total buffer size (frames) */ } aout_stream_sys_t; @@ -155,7 +159,7 @@ static HRESULT Play(aout_stream_t *s, block_t *block) break; } - const size_t copy = frames * sys->bytes_per_frame; + const size_t copy = frames * sys->bytes_per_frame / sys->frame_length; memcpy(dst, block->p_buffer, copy); hr = IAudioRenderClient_ReleaseBuffer(render, frames, 0); @@ -231,6 +235,29 @@ static const uint32_t chans_in[] = { SPEAKER_FRONT_CENTER, SPEAKER_LOW_FREQUENCY, 0 }; +static void vlc_SpdifToWave(WAVEFORMATEXTENSIBLE *restrict wf, + audio_sample_format_t *restrict audio) +{ + audio->i_format = VLC_CODEC_SPDIFL; + aout_FormatPrepare (audio); + audio->i_bytes_per_frame = AOUT_SPDIF_SIZE; + audio->i_frame_length = A52_FRAME_NB; + + wf->SubFormat = _KSDATAFORMAT_SUBTYPE_IEC61937_DOLBY_DIGITAL; + + wf->Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + wf->Format.nChannels = 2; /* To prevent channel re-ordering */ + wf->Format.nSamplesPerSec = audio->i_rate; + wf->Format.wBitsPerSample = 16; + wf->Format.nBlockAlign = 4; /* wf->Format.wBitsPerSample / 8 * wf->Format.nChannels */ + wf->Format.nAvgBytesPerSec = wf->Format.nSamplesPerSec * wf->Format.nBlockAlign; + wf->Format.cbSize = sizeof (*wf) - sizeof (wf->Format); + + wf->Samples.wValidBitsPerSample = wf->Format.wBitsPerSample; + + wf->dwChannelMask = SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT; +} + static void vlc_ToWave(WAVEFORMATEXTENSIBLE *restrict wf, audio_sample_format_t *restrict audio) { @@ -345,10 +372,6 @@ static unsigned vlc_CheckWaveOrder (const WAVEFORMATEX *restrict wf, static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt, const GUID *sid) { - if (!s->b_force && var_InheritBool(s, "spdif") && AOUT_FMT_SPDIF(fmt)) - /* Fallback to other plugin until pass-through is implemented */ - return E_NOTIMPL; - static INIT_ONCE freq_once = INIT_ONCE_STATIC_INIT; if (!InitOnceExecuteOnce(&freq_once, InitFreq, &freq, NULL)) @@ -371,10 +394,29 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt, /* Configure audio stream */ WAVEFORMATEXTENSIBLE wf; WAVEFORMATEX *pwf; + AUDCLNT_SHAREMODE shared_mode; + + if (AOUT_FMT_SPDIF(fmt) && var_InheritBool(s, "spdif")) + { + vlc_SpdifToWave(&wf, fmt); + shared_mode = AUDCLNT_SHAREMODE_EXCLUSIVE; + } + else + { + vlc_ToWave(&wf, fmt); + shared_mode = AUDCLNT_SHAREMODE_SHARED; + } - vlc_ToWave(&wf, fmt); - hr = IAudioClient_IsFormatSupported(sys->client, AUDCLNT_SHAREMODE_SHARED, + hr = IAudioClient_IsFormatSupported(sys->client, shared_mode, &wf.Format, &pwf); + if (FAILED(hr) && AOUT_FMT_SPDIF(fmt)) + { + /* Device may not support SPDIF: try again with FL32 */ + vlc_ToWave(&wf, fmt); + shared_mode = AUDCLNT_SHAREMODE_SHARED; + hr = IAudioClient_IsFormatSupported(sys->client, shared_mode, + &wf.Format, &pwf); + } if (FAILED(hr)) { msg_Err(s, "cannot negotiate audio format (error 0x%lx)", hr); @@ -391,6 +433,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt, hr = E_INVALIDARG; goto error; } + shared_mode = AUDCLNT_SHAREMODE_SHARED; msg_Dbg(s, "modified format"); } else @@ -400,7 +443,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt, sys->chans_table); sys->format = fmt->i_format; - hr = IAudioClient_Initialize(sys->client, AUDCLNT_SHAREMODE_SHARED, 0, + hr = IAudioClient_Initialize(sys->client, shared_mode, 0, AOUT_MAX_PREPARE_TIME * 10, 0, (hr == S_OK) ? &wf.Format : pwf, sid); CoTaskMemFree(pwf); @@ -429,6 +472,7 @@ static HRESULT Start(aout_stream_t *s, audio_sample_format_t *restrict fmt, sys->rate = fmt->i_rate; sys->bytes_per_frame = fmt->i_bytes_per_frame; + sys->frame_length = fmt->i_frame_length > 0 ? fmt->i_frame_length : 1; sys->written = 0; s->sys = sys; s->time_get = TimeGet; _______________________________________________ vlc-commits mailing list [email protected] https://mailman.videolan.org/listinfo/vlc-commits
