The functionality now resides in
gst_wasapi_util_get_device() and
gst_wasapi_util_get_audio_client().
This is a preparatory patch. It will be used in the following
patch to init/deinit the AudioClient separately from the device.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/2096>
The GstDeviceProvider isn't subclass of GstElement.
(gst-device-monitor-1.0:49356): GLib-GObject-WARNING **: 20:21:18.651:
invalid cast from 'GstWasapiDeviceProvider' to 'GstElement'
When the audio device goes away during playback or capture, we were
going into an infinite loop of AUDCLNT_E_DEVICE_INVALIDATED. Return -1
and post an error message so the ringbuffer thread exits with an error.
This is now handled directly in gstaudiosrc/sink, and we were setting
it in the wrong thread anyway. prepare() is not the same thread as
sink_write() or src_read().
S_FALSE is a valid return value which does not indicate an error.
For example IAudioClient_Stop() returns S_FALSE when it is already stopped.
Use the FAILED macro instead which just checks if an error occured or not.
This fixes spurious warnings when using the wasapisink element.
https://bugzilla.gnome.org/show_bug.cgi?id=796280
Now, when you set loopback=true on wasapisrc, the `device` property
should refer to a sink (render) device for loopback recording.
If the `device` property is not set, the default sink device is used.
This allows us to request ultra-low-latency device periods even in
shared mode. However, this requires good drivers and Windows 10, so
we only enable this when we detect that we are running on Windows 10
at runtime.
You can forcibly disable this feature on Windows 10 by setting
GST_WASAPI_DISABLE_AUDIOCLIENT3=1 in the environment.
So far, we have been completely discarding the values of latency-time
and buffer-time and trying to always open the device in the lowest
latency mode possible. However, sometimes this is a bad idea:
1. When we want to save power/CPU and don't want low latency
2. When the lowest latency setting causes glitches
3. Other audio-driver bugs
Now we will try to follow the user-set values of latency-time and
buffer-time in shared mode, and only latency-time in exclusive mode (we
have no control over the hardware buffer size, and there is no use in
setting GstAudioRingBuffer size to something larger).
The elements will still try to open the devices in the lowest latency
mode possible if you set the "low-latency" property to "true".
https://bugzilla.gnome.org/show_bug.cgi?id=793289
This requires using allocated strings, but it's the best option. For
instance, a call could fail because CoInitialize() wasn't called, or
because some other thing in the stack failed.
https://bugzilla.gnome.org/show_bug.cgi?id=793289
This provides much lower latency compared to opening in shared mode,
but it also means that the device cannot be opened by any other
application. The advantage is that the achievable latency is much
lower.
In shared mode, WASAPI's engine period is 10ms, and so that is the
lowest latency achievable.
In exclusive mode, the limit is the device period itself, which in my
testing with USB DACs, on-board PCI sound-cards, and HDMI cards is
between 2ms and 3.33ms.
We set our audioringbuffer limits to match the device, so the
achievable sink latency is 6-9ms. Further improvements can be made if
needed.
https://bugzilla.gnome.org/show_bug.cgi?id=793289
Currently only does probing and does not handle messages from
endpoints/devices. In the future we want to do proper monitoring which
is well-supported in WASAPI.
https://bugzilla.gnome.org/show_bug.cgi?id=792897
We need to parse the WAVEFORMATEXTENSIBLE structure, figure out what
positions the channels have (if they are positional), and reorder them
as necessary.
https://bugzilla.gnome.org/show_bug.cgi?id=792897
Both the source and the sink elements were broken in a number of ways:
* prepare() was assuming that the format was always S16LE 2ch 44.1KHz.
We now probe the preferred format with GetMixFormat().
* Device initialization was done with the wrong buffer size
(buffer_time is in microseconds, not nanoseconds).
* sink_write() and src_read() were just plain wrong and would never
write or read anything useful.
* Some functions in prepare() were always returning FALSE which meant
trying to use the elements would *always* fail.
* get_caps() and delay() were not implemented at all.
TODO: support for >2 channels
TODO: pro-audio low-latency
TODO: SPDIF and other encoded passthroughs
Three new properties are now implemented: role, mute, and device.
* 'role' designates the stream role of the initialized device, see:
https://msdn.microsoft.com/en-us/library/windows/desktop/dd370842(v=vs.85).aspx
* 'device' is a system-wide GUIDesque string for a specific device.
* 'mute' is a sink property and simply mutes it.
On my Windows 8.1 system, the lowest latency that works is:
wasapisrc buffer-time=20000
wasapisink buffer-time=10000
aka, 20ms and 10ms respectively. These values are close to the lowest
possible with the IAudioClient interface. Further improvements require
porting to IAudioClient2 or IAudioClient3.
https://docs.microsoft.com/en-us/windows-hardware/drivers/audio/low-latency-audio
Original commit message from CVS:
* sys/Makefile.am:
* sys/wasapi/Makefile.am:
* sys/wasapi/gstwasapi.c:
* sys/wasapi/gstwasapisink.c:
* sys/wasapi/gstwasapisink.h:
* sys/wasapi/gstwasapisrc.c:
* sys/wasapi/gstwasapisrc.h:
* sys/wasapi/gstwasapiutil.c:
* sys/wasapi/gstwasapiutil.h:
New plugin for audio capture and playback using Windows Audio Session
API (WASAPI) available with Vista and newer (#520901).
Comes with hardcoded caps and obviously needs lots of love. Haven't
had time to work on this code since it was written, was initially just
a quick experiment to play around with this new API.