mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-27 10:40:34 +00:00
mfvideosrc: Add a new property for ICoreDispatcher setting
Since the commit c29c71ae9d
,
device activation method will be called from an internal thread.
A problem is that, CoreApplication::GetCurrentView()
method will return nullptr if it was called from non-UI thread,
and as a result, currently implemented method for accessing ICoreDispatcher
will not work in any case. There seems to be no robust way for
accessing ICoreDispatcher other then setting it by user.
Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/merge_requests/1466>
This commit is contained in:
parent
42de98fd42
commit
502aea3969
8 changed files with 149 additions and 45 deletions
|
@ -42,6 +42,12 @@ GST_DEBUG_CATEGORY_EXTERN (gst_mf_source_object_debug);
|
|||
|
||||
G_END_DECLS
|
||||
|
||||
enum
|
||||
{
|
||||
PROP_0,
|
||||
PROP_DISPATCHER,
|
||||
};
|
||||
|
||||
struct _GstMFCaptureWinRT
|
||||
{
|
||||
GstMFSourceObject parent;
|
||||
|
@ -61,10 +67,16 @@ struct _GstMFCaptureWinRT
|
|||
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);
|
||||
|
@ -94,6 +106,14 @@ gst_mf_capture_winrt_class_init (GstMFCaptureWinRTClass * klass)
|
|||
|
||||
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);
|
||||
|
@ -150,6 +170,38 @@ gst_mf_capture_winrt_finalize (GObject * object)
|
|||
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)
|
||||
{
|
||||
|
@ -182,7 +234,7 @@ gst_mf_capture_winrt_thread_func (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);
|
||||
|
@ -587,18 +639,39 @@ gst_mf_capture_winrt_set_caps (GstMFSourceObject * object, GstCaps * caps)
|
|||
|
||||
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");
|
||||
|
@ -606,5 +679,7 @@ gst_mf_capture_winrt_new (GstMFSourceType type, gint device_index,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
gst_object_ref_sink (self);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
|
|
@ -32,7 +32,8 @@ G_DECLARE_FINAL_TYPE (GstMFCaptureWinRT, gst_mf_capture_winrt,
|
|||
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
|
||||
|
||||
|
|
|
@ -176,7 +176,8 @@ gst_mf_device_provider_probe (GstDeviceProvider * provider)
|
|||
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;
|
||||
|
||||
|
|
|
@ -310,7 +310,7 @@ gst_mf_source_object_use_winrt_api (void)
|
|||
|
||||
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");
|
||||
|
@ -320,12 +320,12 @@ gst_mf_source_object_new (GstMFSourceType type, gint device_index,
|
|||
#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");
|
||||
|
|
|
@ -106,7 +106,8 @@ gboolean gst_mf_source_object_set_caps (GstMFSourceObject * object,
|
|||
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,
|
||||
|
|
|
@ -80,6 +80,7 @@ struct _GstMFVideoSrc
|
|||
gchar *device_path;
|
||||
gchar *device_name;
|
||||
gint device_index;
|
||||
gpointer dispatcher;
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -88,6 +89,7 @@ enum
|
|||
PROP_DEVICE_PATH,
|
||||
PROP_DEVICE_NAME,
|
||||
PROP_DEVICE_INDEX,
|
||||
PROP_DISPATCHER,
|
||||
};
|
||||
|
||||
#define DEFAULT_DEVICE_PATH NULL
|
||||
|
@ -141,6 +143,15 @@ gst_mf_video_src_class_init (GstMFVideoSrcClass * klass)
|
|||
"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",
|
||||
|
@ -201,6 +212,11 @@ gst_mf_video_src_get_property (GObject * object, guint prop_id, GValue * value,
|
|||
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;
|
||||
|
@ -225,6 +241,11 @@ gst_mf_video_src_set_property (GObject * object, guint prop_id,
|
|||
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;
|
||||
|
@ -239,7 +260,7 @@ gst_mf_video_src_start (GstBaseSrc * src)
|
|||
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;
|
||||
|
|
|
@ -383,14 +383,21 @@ error:
|
|||
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()
|
||||
|
@ -932,35 +939,6 @@ MediaCaptureWrapper::onCaptureFailed(IMediaCapture *capture,
|
|||
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)
|
||||
|
@ -1026,3 +1004,28 @@ MediaCaptureWrapper::enumrateFrameSourceGroup
|
|||
|
||||
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);
|
||||
}
|
|
@ -117,7 +117,7 @@ typedef struct
|
|||
class MediaCaptureWrapper
|
||||
{
|
||||
public:
|
||||
MediaCaptureWrapper();
|
||||
MediaCaptureWrapper(gpointer dispatcher);
|
||||
~MediaCaptureWrapper();
|
||||
|
||||
void RegisterCb(const MediaCaptureWrapperCallbacks &cb,
|
||||
|
@ -163,7 +163,6 @@ private:
|
|||
IMediaFrameArrivedEventArgs *args);
|
||||
HRESULT onCaptureFailed(IMediaCapture *capture,
|
||||
IMediaCaptureFailedEventArgs *args);
|
||||
void findCoreDispatcher();
|
||||
static HRESULT enumrateFrameSourceGroup(std::vector<GstWinRTMediaFrameSourceGroup> &list);
|
||||
|
||||
template <typename CB>
|
||||
|
@ -214,4 +213,7 @@ private:
|
|||
}
|
||||
};
|
||||
|
||||
HRESULT
|
||||
FindCoreDispatcherForCurrentThread(ICoreDispatcher ** dispatcher);
|
||||
|
||||
#endif /* __GST_MEDIA_CAPTURE_WRAPPER_H__ */
|
Loading…
Reference in a new issue