From 8afc283b51902bc8b4aa0c1cdc16f30d74ec1406 Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Thu, 14 May 2020 20:47:06 +0900 Subject: [PATCH] mediafoundation: Refactor GstMFSourceObject implementation * Move CoInitializeEx/CoUninitialize pair into thread function in order to ensure MTA COM thread * Move common code to baseclass Part-of: --- sys/mediafoundation/gstmfcaptureengine.cpp | 123 ++++-------- sys/mediafoundation/gstmfsourceobject.c | 209 +++++++++++++++++++-- sys/mediafoundation/gstmfsourceobject.h | 18 +- sys/mediafoundation/gstmfsourcereader.cpp | 116 ++++-------- 4 files changed, 276 insertions(+), 190 deletions(-) diff --git a/sys/mediafoundation/gstmfcaptureengine.cpp b/sys/mediafoundation/gstmfcaptureengine.cpp index ff008d2793..dc5015701a 100644 --- a/sys/mediafoundation/gstmfcaptureengine.cpp +++ b/sys/mediafoundation/gstmfcaptureengine.cpp @@ -241,11 +241,13 @@ struct _GstMFCaptureEngine gboolean flushing; }; -static void gst_mf_capture_engine_constructed (GObject * object); static void gst_mf_capture_engine_finalize (GObject * object); +static gboolean gst_mf_capture_engine_open (GstMFSourceObject * object, + IMFActivate * activate); static gboolean gst_mf_capture_engine_start (GstMFSourceObject * object); static gboolean gst_mf_capture_engine_stop (GstMFSourceObject * object); +static gboolean gst_mf_capture_engine_close (GstMFSourceObject * object); static GstFlowReturn gst_mf_capture_engine_fill (GstMFSourceObject * object, GstBuffer * buffer); static gboolean gst_mf_capture_engine_unlock (GstMFSourceObject * object); @@ -264,11 +266,12 @@ gst_mf_capture_engine_class_init (GstMFCaptureEngineClass * klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstMFSourceObjectClass *source_class = GST_MF_SOURCE_OBJECT_CLASS (klass); - gobject_class->constructed = gst_mf_capture_engine_constructed; gobject_class->finalize = gst_mf_capture_engine_finalize; + source_class->open = GST_DEBUG_FUNCPTR (gst_mf_capture_engine_open); source_class->start = GST_DEBUG_FUNCPTR (gst_mf_capture_engine_start); source_class->stop = GST_DEBUG_FUNCPTR (gst_mf_capture_engine_stop); + source_class->close = GST_DEBUG_FUNCPTR (gst_mf_capture_engine_close); source_class->fill = GST_DEBUG_FUNCPTR (gst_mf_capture_engine_fill); source_class->unlock = GST_DEBUG_FUNCPTR (gst_mf_capture_engine_unlock); source_class->unlock_stop = @@ -283,8 +286,6 @@ gst_mf_capture_engine_init (GstMFCaptureEngine * self) self->queue = g_queue_new (); g_mutex_init (&self->lock); g_cond_init (&self->cond); - - CoInitializeEx (NULL, COINIT_MULTITHREADED); } static gboolean @@ -373,9 +374,10 @@ gst_mf_stream_media_type_free (GstMFStreamMediaType * media_type) } static gboolean -gst_mf_capture_engine_create (GstMFCaptureEngine * self, +gst_mf_capture_engine_open (GstMFSourceObject * object, IMFActivate * activate) { + GstMFCaptureEngine *self = GST_MF_CAPTURE_ENGINE (object); GList *iter; ComPtr factory; ComPtr engine; @@ -469,63 +471,36 @@ gst_mf_capture_engine_create (GstMFCaptureEngine * self, return TRUE; } -static void -gst_mf_capture_engine_constructed (GObject * object) +static gboolean +gst_mf_capture_engine_close (GstMFSourceObject * object) { - GstMFSourceObject *source = GST_MF_SOURCE_OBJECT (object); GstMFCaptureEngine *self = GST_MF_CAPTURE_ENGINE (object); - GList *activate_list = NULL; - GstMFDeviceActivate *target = NULL; - GList *iter; - if (!gst_mf_source_enum_device_activate (source->soure_type, &activate_list)) { - GST_WARNING_OBJECT (self, "No available video capture device"); - return; - } -#ifndef GST_DISABLE_GST_DEBUG - for (iter = activate_list; iter; iter = g_list_next (iter)) { - GstMFDeviceActivate *activate = (GstMFDeviceActivate *) iter->data; + gst_clear_caps (&self->supported_caps); - GST_DEBUG_OBJECT (self, "device %d, name: \"%s\", path: \"%s\"", - activate->index, GST_STR_NULL (activate->name), - GST_STR_NULL (activate->path)); - } -#endif - - for (iter = activate_list; iter; iter = g_list_next (iter)) { - GstMFDeviceActivate *activate = (GstMFDeviceActivate *) iter->data; - gboolean match; - - if (source->device_path && strlen (source->device_path) > 0) { - match = g_ascii_strcasecmp (activate->path, source->device_path) == 0; - } else if (source->device_name && strlen (source->device_name) > 0) { - match = g_ascii_strcasecmp (activate->name, source->device_name) == 0; - } else if (source->device_index >= 0) { - match = activate->index == source->device_index; - } else { - /* pick the first entry */ - match = TRUE; - } - - if (match) { - target = activate; - break; - } + if (self->media_types) { + g_list_free_full (self->media_types, + (GDestroyNotify) gst_mf_stream_media_type_free); + self->media_types = NULL; } - if (target) - gst_mf_capture_engine_create (self, target->handle); + if (self->callback_obj) { + self->callback_obj->Release (); + self->callback_obj = NULL; + } - if (activate_list) - g_list_free_full (activate_list, - (GDestroyNotify) gst_mf_device_activate_free); -} + if (self->engine) { + self->engine->Release (); + self->engine = NULL; + } -static void -release_mf_buffer (IMFMediaBuffer * buffer) -{ - if (buffer) - buffer->Release (); + if (self->source) { + self->source->Shutdown (); + self->source->Release (); + self->source = NULL; + } + + return TRUE; } static void @@ -533,32 +508,10 @@ gst_mf_capture_engine_finalize (GObject * object) { GstMFCaptureEngine *self = GST_MF_CAPTURE_ENGINE (object); - gst_clear_caps (&self->supported_caps); - - if (self->media_types) - g_list_free_full (self->media_types, - (GDestroyNotify) gst_mf_stream_media_type_free); - - gst_mf_capture_engine_stop (GST_MF_SOURCE_OBJECT (self)); - g_queue_free_full (self->queue, (GDestroyNotify) release_mf_buffer); - - if (self->callback_obj) { - self->callback_obj->Release (); - } - - if (self->engine) - self->engine->Release (); - - if (self->source) { - self->source->Shutdown (); - self->source->Release (); - } - + g_queue_free (self->queue); g_mutex_clear (&self->lock); g_cond_clear (&self->cond); - CoUninitialize (); - G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -712,6 +665,11 @@ gst_mf_capture_engine_stop (GstMFSourceObject * object) } } + while (!g_queue_is_empty (self->queue)) { + IMFMediaBuffer *buffer = (IMFMediaBuffer *) g_queue_pop_head (self->queue); + buffer->Release (); + } + return TRUE; } @@ -866,7 +824,7 @@ GstMFSourceObject * gst_mf_capture_engine_new (GstMFSourceType type, gint device_index, const gchar * device_name, const gchar * device_path) { - GstMFCaptureEngine *self; + GstMFSourceObject *self; gchar *name; gchar *path; @@ -876,7 +834,7 @@ gst_mf_capture_engine_new (GstMFSourceType type, gint device_index, name = device_name ? g_strdup (device_name) : g_strdup (""); path = device_path ? g_strdup (device_path) : g_strdup (""); - self = (GstMFCaptureEngine *) g_object_new (GST_TYPE_MF_CAPTURE_ENGINE, + self = (GstMFSourceObject *) g_object_new (GST_TYPE_MF_CAPTURE_ENGINE, "source-type", type, "device-index", device_index, "device-name", name, "device-path", path, NULL); @@ -884,10 +842,11 @@ gst_mf_capture_engine_new (GstMFSourceType type, gint device_index, g_free (name); g_free (path); - if (!self->source) { - gst_clear_object (&self); + if (!self->opend) { + GST_WARNING_OBJECT (self, "Couldn't open device"); + gst_object_unref (self); return NULL; } - return GST_MF_SOURCE_OBJECT (self); + return self; } diff --git a/sys/mediafoundation/gstmfsourceobject.c b/sys/mediafoundation/gstmfsourceobject.c index 649e595bbe..1a3ca330d5 100644 --- a/sys/mediafoundation/gstmfsourceobject.c +++ b/sys/mediafoundation/gstmfsourceobject.c @@ -58,14 +58,36 @@ gst_mf_source_type_get_type (void) return source_type; } +struct _GstMFSourceObjectPrivate +{ + GstMFSourceType soure_type; + + gchar *device_path; + gchar *device_name; + gint device_index; + + GThread *thread; + GMutex lock; + GCond cond; + GMainContext *context; + GMainLoop *loop; +}; + +static void gst_mf_source_object_constructed (GObject * object); +static void gst_mf_source_object_dispose (GObject * object); static void gst_mf_source_object_finalize (GObject * object); static void gst_mf_source_object_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); static void gst_mf_source_object_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); +static gpointer gst_mf_source_object_thread_func (GstMFSourceObject * self); +static gboolean gst_mf_source_enum_device_activate (GstMFSourceObject * self, + GstMFSourceType source_type, GList ** device_activates); +static void gst_mf_device_activate_free (GstMFDeviceActivate * activate); + #define gst_mf_source_object_parent_class parent_class -G_DEFINE_ABSTRACT_TYPE (GstMFSourceObject, gst_mf_source_object, +G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (GstMFSourceObject, gst_mf_source_object, GST_TYPE_OBJECT); static void @@ -73,6 +95,8 @@ gst_mf_source_object_class_init (GstMFSourceObjectClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->constructed = gst_mf_source_object_constructed; + gobject_class->dispose = gst_mf_source_object_dispose; gobject_class->finalize = gst_mf_source_object_finalize; gobject_class->get_property = gst_mf_source_object_get_property; gobject_class->set_property = gst_mf_source_object_set_property; @@ -99,17 +123,65 @@ gst_mf_source_object_class_init (GstMFSourceObjectClass * klass) static void gst_mf_source_object_init (GstMFSourceObject * self) { - self->device_index = DEFAULT_DEVICE_INDEX; - self->soure_type = DEFAULT_SOURCE_TYPE; + GstMFSourceObjectPrivate *priv; + + self->priv = priv = gst_mf_source_object_get_instance_private (self); + + priv->device_index = DEFAULT_DEVICE_INDEX; + priv->soure_type = DEFAULT_SOURCE_TYPE; + + g_mutex_init (&priv->lock); + g_cond_init (&priv->cond); + + priv->context = g_main_context_new (); + priv->loop = g_main_loop_new (priv->context, FALSE); +} + +static void +gst_mf_source_object_constructed (GObject * object) +{ + GstMFSourceObject *self = GST_MF_SOURCE_OBJECT (object); + GstMFSourceObjectPrivate *priv = self->priv; + + /* Create thread so that ensure COM thread can be MTA thread */ + g_mutex_lock (&priv->lock); + priv->thread = g_thread_new ("GstMFSourceObject", + (GThreadFunc) gst_mf_source_object_thread_func, self); + while (!g_main_loop_is_running (priv->loop)) + g_cond_wait (&priv->cond, &priv->lock); + g_mutex_unlock (&priv->lock); + + G_OBJECT_CLASS (parent_class)->constructed (object); +} + +static void +gst_mf_source_object_dispose (GObject * object) +{ + GstMFSourceObject *self = GST_MF_SOURCE_OBJECT (object); + GstMFSourceObjectPrivate *priv = self->priv; + + if (priv->loop) { + g_main_loop_quit (priv->loop); + g_thread_join (priv->thread); + g_main_loop_unref (priv->loop); + g_main_context_unref (priv->context); + priv->loop = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); } static void gst_mf_source_object_finalize (GObject * object) { GstMFSourceObject *self = GST_MF_SOURCE_OBJECT (object); + GstMFSourceObjectPrivate *priv = self->priv; - g_free (self->device_path); - g_free (self->device_name); + g_mutex_clear (&priv->lock); + g_cond_clear (&priv->cond); + + g_free (priv->device_path); + g_free (priv->device_name); G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -119,19 +191,20 @@ gst_mf_source_object_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstMFSourceObject *self = GST_MF_SOURCE_OBJECT (object); + GstMFSourceObjectPrivate *priv = self->priv; switch (prop_id) { case PROP_DEVICE_PATH: - g_value_set_string (value, self->device_path); + g_value_set_string (value, priv->device_path); break; case PROP_DEVICE_NAME: - g_value_set_string (value, self->device_name); + g_value_set_string (value, priv->device_name); break; case PROP_DEVICE_INDEX: - g_value_set_int (value, self->device_index); + g_value_set_int (value, priv->device_index); break; case PROP_SOURCE_TYPE: - g_value_set_enum (value, self->soure_type); + g_value_set_enum (value, priv->soure_type); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -144,21 +217,22 @@ gst_mf_source_object_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstMFSourceObject *self = GST_MF_SOURCE_OBJECT (object); + GstMFSourceObjectPrivate *priv = self->priv; switch (prop_id) { case PROP_DEVICE_PATH: - g_free (self->device_path); - self->device_path = g_value_dup_string (value); + g_free (priv->device_path); + priv->device_path = g_value_dup_string (value); break; case PROP_DEVICE_NAME: - g_free (self->device_name); - self->device_name = g_value_dup_string (value); + g_free (priv->device_name); + priv->device_name = g_value_dup_string (value); break; case PROP_DEVICE_INDEX: - self->device_index = g_value_get_int (value); + priv->device_index = g_value_get_int (value); break; case PROP_SOURCE_TYPE: - self->soure_type = g_value_get_enum (value); + priv->soure_type = g_value_get_enum (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -166,6 +240,101 @@ gst_mf_source_object_set_property (GObject * object, guint prop_id, } } +static gboolean +gst_mf_source_object_main_loop_running_cb (GstMFSourceObject * self) +{ + GstMFSourceObjectPrivate *priv = self->priv; + + GST_TRACE_OBJECT (self, "Main loop running now"); + + g_mutex_lock (&priv->lock); + g_cond_signal (&priv->cond); + g_mutex_unlock (&priv->lock); + + return G_SOURCE_REMOVE; +} + +static gpointer +gst_mf_source_object_thread_func (GstMFSourceObject * self) +{ + GstMFSourceObjectPrivate *priv = self->priv; + GstMFSourceObjectClass *klass = GST_MF_SOURCE_OBJECT_GET_CLASS (self); + GSource *source; + GList *activate_list = NULL; + GstMFDeviceActivate *target = NULL; + GList *iter; + + g_assert (klass->open != NULL); + g_assert (klass->close != NULL); + + CoInitializeEx (NULL, COINIT_MULTITHREADED); + + g_main_context_push_thread_default (priv->context); + + source = g_idle_source_new (); + g_source_set_callback (source, + (GSourceFunc) gst_mf_source_object_main_loop_running_cb, self, NULL); + g_source_attach (source, priv->context); + g_source_unref (source); + + if (!gst_mf_source_enum_device_activate (self, + priv->soure_type, &activate_list)) { + GST_WARNING_OBJECT (self, "No available video capture device"); + goto run_loop; + } +#ifndef GST_DISABLE_GST_DEBUG + for (iter = activate_list; iter; iter = g_list_next (iter)) { + GstMFDeviceActivate *activate = (GstMFDeviceActivate *) iter->data; + + GST_DEBUG_OBJECT (self, "device %d, name: \"%s\", path: \"%s\"", + activate->index, GST_STR_NULL (activate->name), + GST_STR_NULL (activate->path)); + } +#endif + + for (iter = activate_list; iter; iter = g_list_next (iter)) { + GstMFDeviceActivate *activate = (GstMFDeviceActivate *) iter->data; + gboolean match; + + if (priv->device_path && strlen (priv->device_path) > 0) { + match = g_ascii_strcasecmp (activate->path, priv->device_path) == 0; + } else if (priv->device_name && strlen (priv->device_name) > 0) { + match = g_ascii_strcasecmp (activate->name, priv->device_name) == 0; + } else if (priv->device_index >= 0) { + match = activate->index == priv->device_index; + } else { + /* pick the first entry */ + match = TRUE; + } + + if (match) { + target = activate; + break; + } + } + + if (target) + self->opend = klass->open (self, target->handle); + + if (activate_list) + g_list_free_full (activate_list, + (GDestroyNotify) gst_mf_device_activate_free); + +run_loop: + GST_TRACE_OBJECT (self, "Starting main loop"); + g_main_loop_run (priv->loop); + GST_TRACE_OBJECT (self, "Stopped main loop"); + + klass->stop (self); + klass->close (self); + + g_main_context_pop_thread_default (priv->context); + + CoUninitialize (); + + return NULL; +} + gboolean gst_mf_source_object_start (GstMFSourceObject * object) { @@ -251,9 +420,9 @@ gst_mf_source_object_get_caps (GstMFSourceObject * object) return klass->get_caps (object); } -gboolean -gst_mf_source_enum_device_activate (GstMFSourceType source_type, - GList ** device_sources) +static gboolean +gst_mf_source_enum_device_activate (GstMFSourceObject * self, + GstMFSourceType source_type, GList ** device_sources) { HRESULT hr; GList *ret = NULL; @@ -272,7 +441,7 @@ gst_mf_source_enum_device_activate (GstMFSourceType source_type, &MF_DEVSOURCE_ATTRIBUTE_SOURCE_TYPE_VIDCAP_GUID); break; default: - GST_ERROR ("Unknown source type %d", source_type); + GST_ERROR_OBJECT (self, "Unknown source type %d", source_type); return FALSE; } @@ -332,7 +501,7 @@ done: return ! !ret; } -void +static void gst_mf_device_activate_free (GstMFDeviceActivate * activate) { g_return_if_fail (activate != NULL); diff --git a/sys/mediafoundation/gstmfsourceobject.h b/sys/mediafoundation/gstmfsourceobject.h index 574f422b8b..c6693d024e 100644 --- a/sys/mediafoundation/gstmfsourceobject.h +++ b/sys/mediafoundation/gstmfsourceobject.h @@ -35,6 +35,7 @@ G_BEGIN_DECLS typedef struct _GstMFSourceObject GstMFSourceObject; typedef struct _GstMFSourceObjectClass GstMFSourceObjectClass; +typedef struct _GstMFSourceObjectPrivate GstMFSourceObjectPrivate; typedef enum { @@ -56,21 +57,24 @@ struct _GstMFSourceObject { GstObject parent; - GstMFSourceType soure_type; + gboolean opend; - gchar *device_path; - gchar *device_name; - gint device_index; + GstMFSourceObjectPrivate *priv; }; struct _GstMFSourceObjectClass { GstObjectClass parent_class; + gboolean (*open) (GstMFSourceObject * object, + IMFActivate * activate); + gboolean (*start) (GstMFSourceObject * object); gboolean (*stop) (GstMFSourceObject * object); + gboolean (*close) (GstMFSourceObject * object); + GstFlowReturn (*fill) (GstMFSourceObject * object, GstBuffer * buffer); @@ -101,12 +105,6 @@ GstCaps * gst_mf_source_object_get_caps (GstMFSourceObject * object); gboolean gst_mf_source_object_set_caps (GstMFSourceObject * object, GstCaps * caps); -/* Utils */ -gboolean gst_mf_source_enum_device_activate (GstMFSourceType source_type, - GList ** device_activates); - -void gst_mf_device_activate_free (GstMFDeviceActivate * activate); - G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstMFSourceObject, gst_object_unref) G_END_DECLS diff --git a/sys/mediafoundation/gstmfsourcereader.cpp b/sys/mediafoundation/gstmfsourcereader.cpp index 3798564507..7450707c54 100644 --- a/sys/mediafoundation/gstmfsourcereader.cpp +++ b/sys/mediafoundation/gstmfsourcereader.cpp @@ -67,11 +67,13 @@ struct _GstMFSourceReader gboolean flushing; }; -static void gst_mf_source_reader_constructed (GObject * object); static void gst_mf_source_reader_finalize (GObject * object); +static gboolean gst_mf_source_reader_open (GstMFSourceObject * object, + IMFActivate * activate); static gboolean gst_mf_source_reader_start (GstMFSourceObject * object); static gboolean gst_mf_source_reader_stop (GstMFSourceObject * object); +static gboolean gst_mf_source_reader_close (GstMFSourceObject * object); static GstFlowReturn gst_mf_source_reader_fill (GstMFSourceObject * object, GstBuffer * buffer); static gboolean gst_mf_source_reader_unlock (GstMFSourceObject * object); @@ -90,11 +92,12 @@ gst_mf_source_reader_class_init (GstMFSourceReaderClass * klass) GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstMFSourceObjectClass *source_class = GST_MF_SOURCE_OBJECT_CLASS (klass); - gobject_class->constructed = gst_mf_source_reader_constructed; gobject_class->finalize = gst_mf_source_reader_finalize; + source_class->open = GST_DEBUG_FUNCPTR (gst_mf_source_reader_open); source_class->start = GST_DEBUG_FUNCPTR (gst_mf_source_reader_start); source_class->stop = GST_DEBUG_FUNCPTR (gst_mf_source_reader_stop); + source_class->close = GST_DEBUG_FUNCPTR (gst_mf_source_reader_close); source_class->fill = GST_DEBUG_FUNCPTR (gst_mf_source_reader_fill); source_class->unlock = GST_DEBUG_FUNCPTR (gst_mf_source_reader_unlock); source_class->unlock_stop = @@ -108,8 +111,6 @@ gst_mf_source_reader_init (GstMFSourceReader * self) { self->queue = g_queue_new (); g_mutex_init (&self->lock); - - CoInitializeEx (NULL, COINIT_MULTITHREADED); } static gboolean @@ -185,8 +186,9 @@ gst_mf_stream_media_type_free (GstMFStreamMediaType * media_type) } static gboolean -gst_mf_source_reader_create (GstMFSourceReader * self, IMFActivate * activate) +gst_mf_source_reader_open (GstMFSourceObject * object, IMFActivate * activate) { + GstMFSourceReader *self = GST_MF_SOURCE_READER (object); GList *iter; HRESULT hr; ComPtr reader; @@ -235,63 +237,31 @@ gst_mf_source_reader_create (GstMFSourceReader * self, IMFActivate * activate) return TRUE; } -static void -gst_mf_source_reader_constructed (GObject * object) +static gboolean +gst_mf_source_reader_close (GstMFSourceObject * object) { - GstMFSourceObject *source = GST_MF_SOURCE_OBJECT (object); GstMFSourceReader *self = GST_MF_SOURCE_READER (object); - GList *activate_list = NULL; - GstMFDeviceActivate *target = NULL; - GList *iter; - if (!gst_mf_source_enum_device_activate (source->soure_type, &activate_list)) { - GST_WARNING_OBJECT (self, "No available video capture device"); - return; - } -#ifndef GST_DISABLE_GST_DEBUG - for (iter = activate_list; iter; iter = g_list_next (iter)) { - GstMFDeviceActivate *activate = (GstMFDeviceActivate *) iter->data; + gst_clear_caps (&self->supported_caps); - GST_DEBUG_OBJECT (self, "device %d, name: \"%s\", path: \"%s\"", - activate->index, GST_STR_NULL (activate->name), - GST_STR_NULL (activate->path)); - } -#endif - - for (iter = activate_list; iter; iter = g_list_next (iter)) { - GstMFDeviceActivate *activate = (GstMFDeviceActivate *) iter->data; - gboolean match; - - if (source->device_path && strlen (source->device_path) > 0) { - match = g_ascii_strcasecmp (activate->path, source->device_path) == 0; - } else if (source->device_name && strlen (source->device_name) > 0) { - match = g_ascii_strcasecmp (activate->name, source->device_name) == 0; - } else if (source->device_index >= 0) { - match = activate->index == source->device_index; - } else { - /* pick the first entry */ - match = TRUE; - } - - if (match) { - target = activate; - break; - } + if (self->media_types) { + g_list_free_full (self->media_types, + (GDestroyNotify) gst_mf_stream_media_type_free); + self->media_types = NULL; } - if (target) - gst_mf_source_reader_create (self, target->handle); + if (self->reader) { + self->reader->Release (); + self->reader = NULL; + } - if (activate_list) - g_list_free_full (activate_list, - (GDestroyNotify) gst_mf_device_activate_free); -} + if (self->source) { + self->source->Shutdown (); + self->source->Release (); + self->source = NULL; + } -static void -release_mf_buffer (IMFMediaBuffer * buffer) -{ - if (buffer) - buffer->Release (); + return TRUE; } static void @@ -299,27 +269,9 @@ gst_mf_source_reader_finalize (GObject * object) { GstMFSourceReader *self = GST_MF_SOURCE_READER (object); - gst_clear_caps (&self->supported_caps); - - if (self->media_types) - g_list_free_full (self->media_types, - (GDestroyNotify) gst_mf_stream_media_type_free); - - gst_mf_source_reader_stop (GST_MF_SOURCE_OBJECT (self)); - g_queue_free_full (self->queue, (GDestroyNotify) release_mf_buffer); - - if (self->reader) - self->reader->Release (); - - if (self->source) { - self->source->Shutdown (); - self->source->Release (); - } - + g_queue_free (self->queue); g_mutex_clear (&self->lock); - CoUninitialize (); - G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -357,6 +309,13 @@ gst_mf_source_reader_start (GstMFSourceObject * object) static gboolean gst_mf_source_reader_stop (GstMFSourceObject * object) { + GstMFSourceReader *self = GST_MF_SOURCE_READER (object); + + while (!g_queue_is_empty (self->queue)) { + IMFMediaBuffer *buffer = (IMFMediaBuffer *) g_queue_pop_head (self->queue); + buffer->Release (); + } + return TRUE; } @@ -530,7 +489,7 @@ GstMFSourceObject * gst_mf_source_reader_new (GstMFSourceType type, gint device_index, const gchar * device_name, const gchar * device_path) { - GstMFSourceReader *self; + GstMFSourceObject *self; gchar *name; gchar *path; @@ -540,7 +499,7 @@ gst_mf_source_reader_new (GstMFSourceType type, gint device_index, name = device_name ? g_strdup (device_name) : g_strdup (""); path = device_path ? g_strdup (device_path) : g_strdup (""); - self = (GstMFSourceReader *) g_object_new (GST_TYPE_MF_SOURCE_READER, + self = (GstMFSourceObject *) g_object_new (GST_TYPE_MF_SOURCE_READER, "source-type", type, "device-index", device_index, "device-name", name, "device-path", path, NULL); @@ -548,10 +507,11 @@ gst_mf_source_reader_new (GstMFSourceType type, gint device_index, g_free (name); g_free (path); - if (!self->source) { - gst_clear_object (&self); + if (!self->opend) { + GST_WARNING_OBJECT (self, "Couldn't open device"); + gst_object_unref (self); return NULL; } - return GST_MF_SOURCE_OBJECT (self); + return self; } \ No newline at end of file