summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeungha Yang <seungha@centricular.com>2020-07-24 21:53:37 +0900
committerGStreamer Merge Bot <gitlab-merge-bot@gstreamer-foundation.org>2020-07-26 12:52:15 +0000
commitb10afc574e72d1f55ba4ce8f5f7572c3df48acf1 (patch)
treee995449cb7862248c038bb79de578208e3c766a4
parent6d960781fc31b3f4226579e8492fee2525d3f304 (diff)
downloadgstreamer-plugins-bad-b10afc574e72d1f55ba4ce8f5f7572c3df48acf1.tar.gz
wasapi2: Add a new property for ICoreDispatcher setting
... so that ensure device activation on UI thread. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1466>
-rw-r--r--sys/wasapi2/gstwasapi2client.cpp110
-rw-r--r--sys/wasapi2/gstwasapi2client.h3
-rw-r--r--sys/wasapi2/gstwasapi2device.c2
-rw-r--r--sys/wasapi2/gstwasapi2sink.c18
-rw-r--r--sys/wasapi2/gstwasapi2src.c18
5 files changed, 112 insertions, 39 deletions
diff --git a/sys/wasapi2/gstwasapi2client.cpp b/sys/wasapi2/gstwasapi2client.cpp
index 07d634341..e2f162783 100644
--- a/sys/wasapi2/gstwasapi2client.cpp
+++ b/sys/wasapi2/gstwasapi2client.cpp
@@ -77,14 +77,22 @@ public:
}
HRESULT
- RuntimeClassInitialize (GstWasapi2Client * listener)
+ RuntimeClassInitialize (GstWasapi2Client * listener, gpointer dispatcher)
{
if (!listener)
return E_INVALIDARG;
listener_ = listener;
- findCoreDispatcher ();
+ if (dispatcher) {
+ ComPtr<IInspectable> inspectable =
+ reinterpret_cast<IInspectable*> (dispatcher);
+ HRESULT hr;
+
+ hr = inspectable.As (&dispatcher_);
+ if (gst_wasapi2_result (hr))
+ GST_INFO("Main UI dispatcher is available");
+ }
return S_OK;
}
@@ -150,36 +158,6 @@ public:
});
}
- /* Try to find ICoreDispatcher of main UI so that active audio
- * interface on main UI thread */
- void findCoreDispatcher(void)
- {
- HRESULT hr;
- HStringReference hstr_core_app =
- HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
- ComPtr<ICoreApplication> core_app;
- ComPtr<ICoreApplicationView> core_app_view;
- ComPtr<ICoreWindow> core_window;
-
- hr = GetActivationFactory (hstr_core_app.Get(), &core_app);
- if (!gst_wasapi2_result (hr))
- return;
-
- hr = core_app->GetCurrentView (&core_app_view);
- if (!gst_wasapi2_result (hr))
- return;
-
- hr = core_app_view->get_CoreWindow (&core_window);
- if (!gst_wasapi2_result (hr))
- return;
-
- hr = core_window->get_Dispatcher (&dispatcher_);
- if (!gst_wasapi2_result (hr))
- return;
-
- GST_DEBUG ("Main UI dispatcher is available");
- }
-
template <typename CB>
HRESULT
runOnUIThread (DWORD timeout, CB && cb)
@@ -242,6 +220,7 @@ struct _GstWasapi2Client
gchar *device_id;
gchar *device_name;
gint device_index;
+ gpointer dispatcher;
IAudioClient3 *audio_client;
IAudioCaptureClient *audio_capture_client;
@@ -284,6 +263,7 @@ enum
PROP_DEVICE_INDEX,
PROP_DEVICE_CLASS,
PROP_LOW_LATENCY,
+ PROP_DISPATCHER,
};
#define DEFAULT_DEVICE_INDEX -1
@@ -356,6 +336,9 @@ gst_wasapi2_client_class_init (GstWasapi2ClientClass * klass)
g_param_spec_boolean ("low-latency", "Low latency",
"Optimize all settings for lowest latency. Always safe to enable.",
DEFAULT_LOW_LATENCY, param_flags));
+ g_object_class_install_property (gobject_class, PROP_DISPATCHER,
+ g_param_spec_pointer ("dispatcher", "Dispatcher",
+ "ICoreDispatcher COM object to use", param_flags));
}
static void
@@ -468,6 +451,9 @@ gst_wasapi2_client_get_property (GObject * object, guint prop_id,
case PROP_LOW_LATENCY:
g_value_set_boolean (value, self->low_latency);
break;
+ case PROP_DISPATCHER:
+ g_value_set_pointer (value, self->dispatcher);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -499,6 +485,9 @@ gst_wasapi2_client_set_property (GObject * object, guint prop_id,
case PROP_LOW_LATENCY:
self->low_latency = g_value_get_boolean (value);
break;
+ case PROP_DISPATCHER:
+ self->dispatcher = g_value_get_pointer (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -604,7 +593,8 @@ gst_wasapi2_client_thread_func_internal (GstWasapi2Client * self)
self->device_class == GST_WASAPI2_CLIENT_DEVICE_CLASS_CAPTURE ? "capture" :
"render", GST_STR_NULL (self->device_id), self->device_index);
- hr = MakeAndInitialize<GstWasapiDeviceActivator> (&activator, self);
+ hr = MakeAndInitialize<GstWasapiDeviceActivator> (&activator,
+ self, self->dispatcher);
if (!gst_wasapi2_result (hr))
goto run_loop;
@@ -1776,15 +1766,65 @@ gst_wasapi2_client_get_volume (GstWasapi2Client * client, gfloat * volume)
return TRUE;
}
+static HRESULT
+find_dispatcher (ICoreDispatcher ** dispatcher)
+{
+ HStringReference hstr_core_app =
+ HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication);
+ HRESULT hr;
+
+ ComPtr<ICoreApplication> core_app;
+ hr = GetActivationFactory (hstr_core_app.Get(), &core_app);
+ if (!gst_wasapi2_result (hr))
+ return hr;
+
+ ComPtr<ICoreApplicationView> core_app_view;
+ hr = core_app->GetCurrentView (&core_app_view);
+ if (!gst_wasapi2_result (hr))
+ return hr;
+
+ ComPtr<ICoreWindow> core_window;
+ hr = core_app_view->get_CoreWindow (&core_window);
+ if (!gst_wasapi2_result (hr))
+ return hr;
+
+ return core_window->get_Dispatcher (dispatcher);
+}
+
GstWasapi2Client *
gst_wasapi2_client_new (GstWasapi2ClientDeviceClass device_class,
- gboolean low_latency, gint device_index, const gchar * device_id)
+ gboolean low_latency, gint device_index, const gchar * device_id,
+ gpointer dispatcher)
{
GstWasapi2Client *self;
+ ComPtr<ICoreDispatcher> core_dispatcher;
+ /* Multiple COM init is allowed */
+ RoInitializeWrapper init_wrapper (RO_INIT_MULTITHREADED);
+
+ /* If application didn't pass ICoreDispatcher object,
+ * try to get dispatcher object for the current thread */
+ if (!dispatcher) {
+ HRESULT hr;
+
+ hr = find_dispatcher (&core_dispatcher);
+ if (gst_wasapi2_result (hr)) {
+ GST_DEBUG ("UI dispatcher is available");
+ dispatcher = core_dispatcher.Get ();
+ } else {
+ GST_DEBUG ("UI dispatcher is unavailable");
+ }
+ } else {
+ GST_DEBUG ("Use user passed UI dispatcher");
+ }
self = (GstWasapi2Client *) g_object_new (GST_TYPE_WASAPI2_CLIENT,
"device-class", device_class, "low-latency", low_latency,
- "device-index", device_index, "device", device_id, NULL);
+ "device-index", device_index, "device", device_id,
+ "dispatcher", dispatcher, NULL);
+
+ /* Reset explicitly to ensure that it happens before
+ * RoInitializeWrapper dtor is called */
+ core_dispatcher.Reset ();
if (!self->audio_client) {
gst_object_unref (self);
diff --git a/sys/wasapi2/gstwasapi2client.h b/sys/wasapi2/gstwasapi2client.h
index adc9125df..7c9bd129c 100644
--- a/sys/wasapi2/gstwasapi2client.h
+++ b/sys/wasapi2/gstwasapi2client.h
@@ -73,7 +73,8 @@ gboolean gst_wasapi2_client_get_volume (GstWasapi2Client * client,
GstWasapi2Client * gst_wasapi2_client_new (GstWasapi2ClientDeviceClass device_class,
gboolean low_latency,
gint device_index,
- const gchar * device_id);
+ const gchar * device_id,
+ gpointer dispatcher);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstWasapi2Client, gst_object_unref)
diff --git a/sys/wasapi2/gstwasapi2device.c b/sys/wasapi2/gstwasapi2device.c
index ac51126ca..3688c2ed4 100644
--- a/sys/wasapi2/gstwasapi2device.c
+++ b/sys/wasapi2/gstwasapi2device.c
@@ -182,7 +182,7 @@ gst_wasapi2_device_provider_probe_internal (GstWasapi2DeviceProvider * self,
gchar *device_id = NULL;
gchar *device_name = NULL;
- client = gst_wasapi2_client_new (client_class, FALSE, i, NULL);
+ client = gst_wasapi2_client_new (client_class, FALSE, i, NULL, NULL);
if (!client)
return;
diff --git a/sys/wasapi2/gstwasapi2sink.c b/sys/wasapi2/gstwasapi2sink.c
index a55767c7a..280f837ba 100644
--- a/sys/wasapi2/gstwasapi2sink.c
+++ b/sys/wasapi2/gstwasapi2sink.c
@@ -69,6 +69,7 @@ enum
PROP_LOW_LATENCY,
PROP_MUTE,
PROP_VOLUME,
+ PROP_DISPATCHER,
};
struct _GstWasapi2Sink
@@ -84,6 +85,7 @@ struct _GstWasapi2Sink
gboolean low_latency;
gboolean mute;
gdouble volume;
+ gpointer dispatcher;
gboolean mute_changed;
gboolean volume_changed;
@@ -157,6 +159,14 @@ gst_wasapi2_sink_class_init (GstWasapi2SinkClass * klass)
GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_DISPATCHER,
+ g_param_spec_pointer ("dispatcher", "Dispatcher",
+ "ICoreDispatcher COM object to use. In order for application to ask "
+ "permission of audio device, device activation should be running "
+ "on UI thread via ICoreDispatcher",
+ GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
gst_element_class_add_static_pad_template (element_class, &sink_template);
gst_element_class_set_static_metadata (element_class, "Wasapi2Sink",
"Sink/Audio/Hardware",
@@ -233,6 +243,9 @@ gst_wasapi2_sink_set_property (GObject * object, guint prop_id,
case PROP_VOLUME:
gst_wasapi2_sink_set_volume (self, g_value_get_double (value));
break;
+ case PROP_DISPATCHER:
+ self->dispatcher = g_value_get_pointer (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -258,6 +271,9 @@ gst_wasapi2_sink_get_property (GObject * object, guint prop_id,
case PROP_VOLUME:
g_value_set_double (value, gst_wasapi2_sink_get_volume (self));
break;
+ case PROP_DISPATCHER:
+ g_value_set_pointer (value, self->dispatcher);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -303,7 +319,7 @@ gst_wasapi2_sink_open_unlocked (GstAudioSink * asink)
self->client =
gst_wasapi2_client_new (GST_WASAPI2_CLIENT_DEVICE_CLASS_RENDER,
- self->low_latency, -1, self->device_id);
+ self->low_latency, -1, self->device_id, self->dispatcher);
return ! !self->client;
}
diff --git a/sys/wasapi2/gstwasapi2src.c b/sys/wasapi2/gstwasapi2src.c
index 7f3bbee8a..f6a0fce76 100644
--- a/sys/wasapi2/gstwasapi2src.c
+++ b/sys/wasapi2/gstwasapi2src.c
@@ -67,6 +67,7 @@ enum
PROP_LOW_LATENCY,
PROP_MUTE,
PROP_VOLUME,
+ PROP_DISPATCHER,
};
struct _GstWasapi2Src
@@ -82,6 +83,7 @@ struct _GstWasapi2Src
gboolean low_latency;
gboolean mute;
gdouble volume;
+ gpointer dispatcher;
gboolean mute_changed;
gboolean volume_changed;
@@ -154,6 +156,14 @@ gst_wasapi2_src_class_init (GstWasapi2SrcClass * klass)
GST_PARAM_MUTABLE_PLAYING | G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
+ g_object_class_install_property (gobject_class, PROP_DISPATCHER,
+ g_param_spec_pointer ("dispatcher", "Dispatcher",
+ "ICoreDispatcher COM object to use. In order for application to ask "
+ "permission of audio device, device activation should be running "
+ "on UI thread via ICoreDispatcher",
+ GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE |
+ G_PARAM_STATIC_STRINGS));
+
gst_element_class_add_static_pad_template (element_class, &src_template);
gst_element_class_set_static_metadata (element_class, "Wasapi2Src",
"Source/Audio/Hardware",
@@ -230,6 +240,9 @@ gst_wasapi2_src_set_property (GObject * object, guint prop_id,
case PROP_VOLUME:
gst_wasapi2_src_set_volume (self, g_value_get_double (value));
break;
+ case PROP_DISPATCHER:
+ self->dispatcher = g_value_get_pointer (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -255,6 +268,9 @@ gst_wasapi2_src_get_property (GObject * object, guint prop_id,
case PROP_VOLUME:
g_value_set_double (value, gst_wasapi2_src_get_volume (self));
break;
+ case PROP_DISPATCHER:
+ g_value_set_pointer (value, self->dispatcher);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -300,7 +316,7 @@ gst_wasapi2_src_open_unlocked (GstAudioSrc * asrc)
self->client =
gst_wasapi2_client_new (GST_WASAPI2_CLIENT_DEVICE_CLASS_CAPTURE,
- self->low_latency, -1, self->device_id);
+ self->low_latency, -1, self->device_id, self->dispatcher);
return ! !self->client;
}