wasapi2: Fix for device open failure on old OS

To open automatic stream routing aware device,
at least Windows10 Anniversary Update is required.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1545>
This commit is contained in:
Seungha Yang 2022-01-20 05:59:36 +09:00
parent b0816c4157
commit 77225c79f9
4 changed files with 92 additions and 14 deletions

View file

@ -164,7 +164,7 @@ public:
HRESULT async_hr = S_OK; HRESULT async_hr = S_OK;
async_hr = ActivateAudioInterfaceAsync (device_id.c_str (), async_hr = ActivateAudioInterfaceAsync (device_id.c_str (),
__uuidof(IAudioClient3), nullptr, this, &async_op); __uuidof(IAudioClient), nullptr, this, &async_op);
/* for debugging */ /* for debugging */
gst_wasapi2_result (async_hr); gst_wasapi2_result (async_hr);
@ -590,6 +590,10 @@ gst_wasapi2_client_activate_async (GstWasapi2Client * self,
* Note that default device is much preferred * Note that default device is much preferred
* See https://docs.microsoft.com/en-us/windows/win32/coreaudio/automatic-stream-routing * See https://docs.microsoft.com/en-us/windows/win32/coreaudio/automatic-stream-routing
*/ */
/* DEVINTERFACE_AUDIO_CAPTURE and DEVINTERFACE_AUDIO_RENDER are available
* as of Windows 10 */
if (gst_wasapi2_can_automatic_stream_routing ()) {
if (self->device_id && if (self->device_id &&
g_ascii_strcasecmp (self->device_id, default_device_id.c_str ()) == 0) { g_ascii_strcasecmp (self->device_id, default_device_id.c_str ()) == 0) {
GST_DEBUG_OBJECT (self, "Default device was requested"); GST_DEBUG_OBJECT (self, "Default device was requested");
@ -602,6 +606,7 @@ gst_wasapi2_client_activate_async (GstWasapi2Client * self,
GST_DEBUG_OBJECT (self, "device-index == zero means default device"); GST_DEBUG_OBJECT (self, "device-index == zero means default device");
use_default_device = TRUE; use_default_device = TRUE;
} }
}
if (use_default_device) { if (use_default_device) {
target_device_id_wstring = default_device_id_wstring; target_device_id_wstring = default_device_id_wstring;
@ -652,8 +657,13 @@ gst_wasapi2_client_activate_async (GstWasapi2Client * self,
GST_DEBUG_OBJECT (self, "Available device count: %d", count); GST_DEBUG_OBJECT (self, "Available device count: %d", count);
if (gst_wasapi2_can_automatic_stream_routing ()) {
/* zero is for default device */ /* zero is for default device */
device_index = 1; device_index = 1;
} else {
device_index = 0;
}
for (unsigned int i = 0; i < count; i++) { for (unsigned int i = 0; i < count; i++) {
/* *INDENT-OFF* */ /* *INDENT-OFF* */
ComPtr<IDeviceInformation> device_info; ComPtr<IDeviceInformation> device_info;
@ -713,6 +723,15 @@ gst_wasapi2_client_activate_async (GstWasapi2Client * self,
GST_DEBUG_OBJECT (self, "device [%d] id: %s, name: %s", GST_DEBUG_OBJECT (self, "device [%d] id: %s, name: %s",
device_index, cur_device_id.c_str (), cur_device_name.c_str ()); device_index, cur_device_id.c_str (), cur_device_name.c_str ());
if (self->device_index < 0 && !self->device_id) {
GST_INFO_OBJECT (self, "Select the first device, device id %s",
cur_device_id.c_str ());
target_device_id_wstring = id.GetRawBuffer (nullptr);
target_device_id = cur_device_id;
target_device_name = cur_device_name;
break;
}
if (self->device_id && if (self->device_id &&
g_ascii_strcasecmp (self->device_id, cur_device_id.c_str ()) == 0) { g_ascii_strcasecmp (self->device_id, cur_device_id.c_str ()) == 0) {
GST_INFO_OBJECT (self, GST_INFO_OBJECT (self,

View file

@ -26,6 +26,7 @@
#include "gstwasapi2util.h" #include "gstwasapi2util.h"
#include <audioclient.h> #include <audioclient.h>
#include <mmdeviceapi.h> #include <mmdeviceapi.h>
#include <winternl.h>
GST_DEBUG_CATEGORY_EXTERN (gst_wasapi2_debug); GST_DEBUG_CATEGORY_EXTERN (gst_wasapi2_debug);
#define GST_CAT_DEFAULT gst_wasapi2_debug #define GST_CAT_DEFAULT gst_wasapi2_debug
@ -443,3 +444,49 @@ gst_wasapi2_util_parse_waveformatex (WAVEFORMATEX * format,
return TRUE; return TRUE;
} }
gboolean
gst_wasapi2_can_automatic_stream_routing (void)
{
#ifdef GST_WASAPI2_WINAPI_ONLY_APP
/* Assume we are on very recent OS */
return TRUE;
#else
static gboolean ret = FALSE;
static gsize version_once = 0;
if (g_once_init_enter (&version_once)) {
OSVERSIONINFOEXW osverinfo;
typedef NTSTATUS (WINAPI fRtlGetVersion) (PRTL_OSVERSIONINFOEXW);
fRtlGetVersion *RtlGetVersion = NULL;
HMODULE hmodule = NULL;
memset (&osverinfo, 0, sizeof (OSVERSIONINFOEXW));
osverinfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFOEXW);
hmodule = LoadLibraryW (L"ntdll.dll");
if (hmodule)
RtlGetVersion =
(fRtlGetVersion *) GetProcAddress (hmodule, "RtlGetVersion");
if (RtlGetVersion) {
RtlGetVersion (&osverinfo);
/* automatic stream routing requires Windows 10
* Anniversary Update (version 1607, build number 14393.0) */
if (osverinfo.dwMajorVersion > 10 ||
(osverinfo.dwMajorVersion == 10 && osverinfo.dwBuildNumber >= 14393))
ret = TRUE;
}
if (hmodule)
FreeLibrary (hmodule);
g_once_init_leave (&version_once, 1);
}
GST_INFO ("Automatic stream routing support: %d", ret);
return ret;
#endif
}

View file

@ -63,6 +63,8 @@ gboolean gst_wasapi2_util_parse_waveformatex (WAVEFORMATEX * format,
gchar * gst_wasapi2_util_get_error_message (HRESULT hr); gchar * gst_wasapi2_util_get_error_message (HRESULT hr);
gboolean gst_wasapi2_can_automatic_stream_routing (void);
G_END_DECLS G_END_DECLS
#endif /* __GST_WASAPI_UTIL_H__ */ #endif /* __GST_WASAPI_UTIL_H__ */

View file

@ -83,6 +83,16 @@ if not winapi_app
endif endif
endif endif
winapi_desktop = cxx.compiles('''#include <winapifamily.h>
#if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
#error "not win32"
#endif''',
name: 'building for WINAPI_PARTITION_DESKTOP')
if winapi_app and not winapi_desktop
extra_args += ['-DGST_WASAPI2_WINAPI_ONLY_APP']
endif
win10_sdk = cxx.compiles('''#include <windows.h> win10_sdk = cxx.compiles('''#include <windows.h>
#ifndef WDK_NTDDI_VERSION #ifndef WDK_NTDDI_VERSION
#error "unknown Windows SDK version" #error "unknown Windows SDK version"