G_END_DECLS
+enum
+{
+ PROP_0,
+ PROP_DISPATCHER,
+};
+
struct _GstMFCaptureWinRT
{
GstMFSourceObject parent;
GstVideoInfo info;
gboolean flushing;
gboolean got_error;
+
+ gpointer dispatcher;
};
static void gst_mf_capture_winrt_constructed (GObject * object);
static void gst_mf_capture_winrt_finalize (GObject * object);
+static void gst_mf_capture_winrt_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_mf_capture_winrt_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
static gboolean gst_mf_capture_winrt_start (GstMFSourceObject * object);
static gboolean gst_mf_capture_winrt_stop (GstMFSourceObject * object);
gobject_class->constructed = gst_mf_capture_winrt_constructed;
gobject_class->finalize = gst_mf_capture_winrt_finalize;
+ gobject_class->get_property = gst_mf_capture_winrt_get_property;
+ gobject_class->set_property = gst_mf_capture_winrt_set_property;
+
+ g_object_class_install_property (gobject_class, PROP_DISPATCHER,
+ g_param_spec_pointer ("dispatcher", "Dispatcher",
+ "ICoreDispatcher COM object to use",
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_STATIC_STRINGS)));
source_class->start = GST_DEBUG_FUNCPTR (gst_mf_capture_winrt_start);
source_class->stop = GST_DEBUG_FUNCPTR (gst_mf_capture_winrt_stop);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static void
+gst_mf_capture_winrt_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec)
+{
+ GstMFCaptureWinRT *self = GST_MF_CAPTURE_WINRT (object);
+
+ switch (prop_id) {
+ case PROP_DISPATCHER:
+ g_value_set_pointer (value, self->dispatcher);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_mf_capture_winrt_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstMFCaptureWinRT *self = GST_MF_CAPTURE_WINRT (object);
+
+ switch (prop_id) {
+ case PROP_DISPATCHER:
+ self->dispatcher = g_value_get_pointer (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
static gboolean
gst_mf_capture_winrt_main_loop_running_cb (GstMFCaptureWinRT * self)
{
RoInitializeWrapper init_wrapper (RO_INIT_MULTITHREADED);
- self->capture = new MediaCaptureWrapper;
+ self->capture = new MediaCaptureWrapper(self->dispatcher);
callbacks.frame_arrived = gst_mf_capture_winrt_on_frame;
callbacks.failed = gst_mf_capture_winrt_on_failed;
self->capture->RegisterCb (callbacks, self);
GstMFSourceObject *
gst_mf_capture_winrt_new (GstMFSourceType type, gint device_index,
- const gchar * device_name, const gchar * device_path)
+ const gchar * device_name, const gchar * device_path, gpointer dispatcher)
{
GstMFSourceObject *self;
+ ComPtr<ICoreDispatcher> core_dispatcher;
+ /* Multiple COM init is allowed */
+ RoInitializeWrapper init_wrapper (RO_INIT_MULTITHREADED);
/* TODO: Add audio capture support */
g_return_val_if_fail (type == GST_MF_SOURCE_TYPE_VIDEO, NULL);
+ /* If application didn't pass ICoreDispatcher object,
+ * try to get dispatcher object for the current thread */
+ if (!dispatcher) {
+ HRESULT hr;
+
+ hr = FindCoreDispatcherForCurrentThread (&core_dispatcher);
+ if (gst_mf_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 = (GstMFSourceObject *) g_object_new (GST_TYPE_MF_CAPTURE_WINRT,
"source-type", type, "device-index", device_index, "device-name",
- device_name, "device-path", device_path, NULL);
+ device_name, "device-path", device_path, "dispatcher", dispatcher, NULL);
- gst_object_ref_sink (self);
+ /* Reset explicitly to ensure that it happens before
+ * RoInitializeWrapper dtor is called */
+ core_dispatcher.Reset ();
if (!self->opened) {
GST_WARNING_OBJECT (self, "Couldn't open device");
return NULL;
}
+ gst_object_ref_sink (self);
+
return self;
}
GstMFSourceObject * gst_mf_capture_winrt_new (GstMFSourceType type,
gint device_index,
const gchar * device_name,
- const gchar * device_path);
+ const gchar * device_path,
+ gpointer dispatcher);
G_END_DECLS
gchar *device_name = NULL;
gchar *device_path = NULL;
- obj = gst_mf_source_object_new (GST_MF_SOURCE_TYPE_VIDEO, i, NULL, NULL);
+ obj = gst_mf_source_object_new (GST_MF_SOURCE_TYPE_VIDEO,
+ i, NULL, NULL, NULL);
if (!obj)
break;
GstMFSourceObject *
gst_mf_source_object_new (GstMFSourceType type, gint device_index,
- const gchar * device_name, const gchar * device_path)
+ const gchar * device_name, const gchar * device_path, gpointer dispatcher)
{
#if (!GST_MF_WINAPI_APP)
GST_INFO ("Try IMFSourceReader implementation");
#if (!GST_MF_WINAPI_DESKTOP)
GST_INFO ("Try WinRT implementation");
return gst_mf_capture_winrt_new (type,
- device_index, device_name, device_path);
+ device_index, device_name, device_path, dispatcher);
#else
if (gst_mf_source_object_use_winrt_api ()) {
GST_INFO ("Both Desktop and WinRT APIs were enabled, user choice: WinRT");
return gst_mf_capture_winrt_new (type,
- device_index, device_name, device_path);
+ device_index, device_name, device_path, dispatcher);
} else {
GST_INFO
("Both Desktop and WinRT APIs were enabled, default: IMFSourceReader");
GstMFSourceObject * gst_mf_source_object_new (GstMFSourceType type,
gint device_index,
const gchar * device_name,
- const gchar * device_path);
+ const gchar * device_path,
+ gpointer dispatcher);
/* Utility methods */
gint gst_mf_source_object_caps_compare (GstCaps * caps1,
gchar *device_path;
gchar *device_name;
gint device_index;
+ gpointer dispatcher;
};
enum
PROP_DEVICE_PATH,
PROP_DEVICE_NAME,
PROP_DEVICE_INDEX,
+ PROP_DISPATCHER,
};
#define DEFAULT_DEVICE_PATH NULL
"The zero-based device index", -1, G_MAXINT, DEFAULT_DEVICE_INDEX,
G_PARAM_READWRITE | GST_PARAM_MUTABLE_READY |
G_PARAM_STATIC_STRINGS));
+#if GST_MF_WINAPI_APP
+ 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 capture device, device activation should be running "
+ "on UI thread via ICoreDispatcher",
+ GST_PARAM_CONDITIONALLY_AVAILABLE | GST_PARAM_MUTABLE_READY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+#endif
gst_element_class_set_static_metadata (element_class,
"Media Foundation Video Source",
case PROP_DEVICE_INDEX:
g_value_set_int (value, self->device_index);
break;
+#if GST_MF_WINAPI_APP
+ case PROP_DISPATCHER:
+ g_value_set_pointer (value, self->dispatcher);
+ break;
+#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
case PROP_DEVICE_INDEX:
self->device_index = g_value_get_int (value);
break;
+#if GST_MF_WINAPI_APP
+ case PROP_DISPATCHER:
+ self->dispatcher = g_value_get_pointer (value);
+ break;
+#endif
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
GST_DEBUG_OBJECT (self, "Start");
self->source = gst_mf_source_object_new (GST_MF_SOURCE_TYPE_VIDEO,
- self->device_index, self->device_name, self->device_path);
+ self->device_index, self->device_name, self->device_path, NULL);
self->first_pts = GST_CLOCK_TIME_NONE;
self->n_frames = 0;
return hr;
}
-MediaCaptureWrapper::MediaCaptureWrapper()
+MediaCaptureWrapper::MediaCaptureWrapper(gpointer dispatcher)
: user_data_(nullptr)
{
user_cb_.frame_arrived = nullptr;
user_cb_.failed = nullptr;
- /* Store CoreDispatecher if available */
- findCoreDispatcher();
+ if (dispatcher) {
+ ComPtr<IInspectable> inspectable =
+ reinterpret_cast<IInspectable*> (dispatcher);
+ HRESULT hr;
+
+ hr = inspectable.As (&dispatcher_);
+ if (gst_mf_result (hr))
+ GST_INFO("Main UI dispatcher is available");
+ }
}
MediaCaptureWrapper::~MediaCaptureWrapper()
return S_OK;
}
-void
-MediaCaptureWrapper::findCoreDispatcher()
-{
- 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_mf_result(hr))
- return;
-
- ComPtr<ICoreApplicationView> core_app_view;
- hr = core_app->GetCurrentView (&core_app_view);
- if (!gst_mf_result(hr))
- return;
-
- ComPtr<ICoreWindow> core_window;
- hr = core_app_view->get_CoreWindow (&core_window);
- if (!gst_mf_result(hr))
- return;
-
- hr = core_window->get_Dispatcher (&dispatcher_);
- if (!gst_mf_result(hr))
- return;
-
- GST_DEBUG("Main UI dispatcher is available");
-}
-
HRESULT
MediaCaptureWrapper::enumrateFrameSourceGroup
(std::vector<GstWinRTMediaFrameSourceGroup> &groupList)
return S_OK;
}
+
+HRESULT
+FindCoreDispatcherForCurrentThread (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 (FAILED (hr))
+ return hr;
+
+ ComPtr<ICoreApplicationView> core_app_view;
+ hr = core_app->GetCurrentView (&core_app_view);
+ if (FAILED (hr))
+ return hr;
+
+ ComPtr<ICoreWindow> core_window;
+ hr = core_app_view->get_CoreWindow (&core_window);
+ if (FAILED (hr))
+ return hr;
+
+ return core_window->get_Dispatcher (dispatcher);
+}
\ No newline at end of file
class MediaCaptureWrapper
{
public:
- MediaCaptureWrapper();
+ MediaCaptureWrapper(gpointer dispatcher);
~MediaCaptureWrapper();
void RegisterCb(const MediaCaptureWrapperCallbacks &cb,
IMediaFrameArrivedEventArgs *args);
HRESULT onCaptureFailed(IMediaCapture *capture,
IMediaCaptureFailedEventArgs *args);
- void findCoreDispatcher();
static HRESULT enumrateFrameSourceGroup(std::vector<GstWinRTMediaFrameSourceGroup> &list);
template <typename CB>
}
};
+HRESULT
+FindCoreDispatcherForCurrentThread(ICoreDispatcher ** dispatcher);
+
#endif /* __GST_MEDIA_CAPTURE_WRAPPER_H__ */
\ No newline at end of file