wasapi2: Respect ringbuffer buffer/latency time

Decide buffer size based on configured buffer/latency time
if low-latency is disabled, so that ringbuffer can buffer more
than minimum required size.

Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2870
Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/6215>
This commit is contained in:
Seungha Yang 2024-02-19 20:57:26 +09:00 committed by GStreamer Marge Bot
parent fb8131b7da
commit 7ff7ced388

View file

@ -869,13 +869,15 @@ gst_wasapi2_ring_buffer_initialize_audio_client3 (GstWasapi2RingBuffer * self,
static HRESULT
gst_wasapi2_ring_buffer_initialize_audio_client (GstWasapi2RingBuffer * self,
IAudioClient * client_handle, WAVEFORMATEX * mix_format, guint * period,
DWORD extra_flags, GstWasapi2ClientDeviceClass device_class)
DWORD extra_flags, GstWasapi2ClientDeviceClass device_class,
GstAudioRingBufferSpec * spec, gboolean low_latency)
{
GstAudioRingBuffer *ringbuffer = GST_AUDIO_RING_BUFFER_CAST (self);
REFERENCE_TIME default_period, min_period;
DWORD stream_flags =
AUDCLNT_STREAMFLAGS_EVENTCALLBACK | AUDCLNT_STREAMFLAGS_NOPERSIST;
HRESULT hr;
REFERENCE_TIME buf_dur = 0;
stream_flags |= extra_flags;
@ -889,12 +891,29 @@ gst_wasapi2_ring_buffer_initialize_audio_client (GstWasapi2RingBuffer * self,
GST_INFO_OBJECT (self, "wasapi2 default period: %" G_GINT64_FORMAT
", min period: %" G_GINT64_FORMAT, default_period, min_period);
/* https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize
* For a shared-mode stream that uses event-driven buffering,
* the caller must set both hnsPeriodicity and hnsBufferDuration to 0
*
* The above MS documentation does not seem to correct. By setting
* zero hnsBufferDuration, we can use audio engine determined buffer size
* but it seems to cause glitch depending on device. Calculate buffer size
* like wasapi plugin does. Note that MS example code uses non-zero
* buffer duration for event-driven shared-mode case as well.
*/
if (spec && !low_latency) {
/* Ensure that the period (latency_time) used is an integral multiple of
* either the default period or the minimum period */
guint64 factor = (spec->latency_time * 10) / default_period;
REFERENCE_TIME period = default_period * MAX (factor, 1);
buf_dur = spec->buffer_time * 10;
if (buf_dur < 2 * period)
buf_dur = 2 * period;
}
hr = client_handle->Initialize (AUDCLNT_SHAREMODE_SHARED, stream_flags,
/* hnsBufferDuration should be same as hnsPeriodicity
* when AUDCLNT_STREAMFLAGS_EVENTCALLBACK is used.
* And in case of shared mode, hnsPeriodicity should be zero, so
* this value should be zero as well */
0,
buf_dur,
/* This must always be 0 in shared mode */
0, mix_format, nullptr);
} else {
@ -952,7 +971,8 @@ gst_wasapi2_ring_buffer_prepare_loopback_client (GstWasapi2RingBuffer * self)
}
hr = gst_wasapi2_ring_buffer_initialize_audio_client (self, client_handle,
mix_format, &period, 0, GST_WASAPI2_CLIENT_DEVICE_CLASS_RENDER);
mix_format, &period, 0, GST_WASAPI2_CLIENT_DEVICE_CLASS_RENDER,
nullptr, FALSE);
if (!gst_wasapi2_result (hr)) {
GST_ERROR_OBJECT (self, "Failed to initialize audio client");
@ -1077,7 +1097,8 @@ gst_wasapi2_ring_buffer_acquire (GstAudioRingBuffer * buf,
extra_flags = AUDCLNT_STREAMFLAGS_LOOPBACK;
hr = gst_wasapi2_ring_buffer_initialize_audio_client (self, client_handle,
mix_format, &period, extra_flags, self->device_class);
mix_format, &period, extra_flags, self->device_class, spec,
self->low_latency);
}
if (!gst_wasapi2_result (hr)) {