From cbe2fc40a473d1587efbb770b76b88a720c22f1f Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Thu, 8 Feb 2018 03:11:10 +0530 Subject: [PATCH] wasapisink: Re-align device period if necessary Sometimes the minimum period advertised by a card results in an unaligned buffer size error during initialization in exclusive mode. In that case, we can fetch the actual buffer size in frames and calculate the period from that. We can't do this pre-emptively because we can't call GetBufferSize till Initialize has been called at least once. https://bugzilla.gnome.org/show_bug.cgi?id=793289 --- sys/wasapi/gstwasapisink.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/sys/wasapi/gstwasapisink.c b/sys/wasapi/gstwasapisink.c index c8cfd729b7..bfb1192c88 100644 --- a/sys/wasapi/gstwasapisink.c +++ b/sys/wasapi/gstwasapisink.c @@ -434,6 +434,9 @@ gst_wasapi_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) GST_INFO_OBJECT (self, "wasapi default period: %" G_GINT64_FORMAT ", min period: %" G_GINT64_FORMAT, default_period, min_period); + bpf = GST_AUDIO_INFO_BPF (&spec->info); + rate = GST_AUDIO_INFO_RATE (&spec->info); + if (self->low_latency) { if (self->sharemode == AUDCLNT_SHAREMODE_SHARED) { device_period = default_period; @@ -458,6 +461,33 @@ gst_wasapi_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) /* This must always be 0 in shared mode */ self->sharemode == AUDCLNT_SHAREMODE_SHARED ? 0 : device_period, self->mix_format, NULL); + + if (hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED && + self->sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE) { + guint32 n_frames; + + GST_WARNING_OBJECT (self, "initialize failed due to unaligned period %i", + (int) device_period); + + /* Calculate a new aligned period. First get the aligned buffer size. */ + hr = IAudioClient_GetBufferSize (self->client, &n_frames); + if (hr != S_OK) { + gchar *msg = gst_wasapi_util_hresult_to_string (hr); + GST_ELEMENT_ERROR (self, RESOURCE, OPEN_WRITE, (NULL), + ("IAudioClient::GetBufferSize() failed: %s", msg)); + g_free (msg); + goto beach; + } + + device_period = (GST_SECOND / 100) * n_frames / rate; + + GST_WARNING_OBJECT (self, "trying to re-initialize with period %i", + (int) device_period); + + hr = IAudioClient_Initialize (self->client, self->sharemode, + AUDCLNT_STREAMFLAGS_EVENTCALLBACK, device_period, + device_period, self->mix_format, NULL); + } if (hr != S_OK) { gchar *msg = gst_wasapi_util_hresult_to_string (hr); GST_ELEMENT_ERROR (self, RESOURCE, OPEN_WRITE, (NULL), @@ -472,9 +502,6 @@ gst_wasapi_sink_prepare (GstAudioSink * asink, GstAudioRingBufferSpec * spec) GST_ERROR_OBJECT (self, "IAudioClient::GetBufferSize failed"); goto beach; } - - bpf = GST_AUDIO_INFO_BPF (&spec->info); - rate = GST_AUDIO_INFO_RATE (&spec->info); GST_INFO_OBJECT (self, "buffer size is %i frames, bpf is %i bytes, " "rate is %i Hz", self->buffer_frame_count, bpf, rate);