From 0920914b892b0b28567bdc5ced7e96a66ae945ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sun, 12 Jun 2022 13:58:44 +0200 Subject: [PATCH 1/3] plugin: Add context handler base class In order to bridge work with GL between GTK and GStreamer reliably, we need to create and check context capabilities ahead of time. We also need to be able to query context at any time during playback. Also we should avoid changing importers on context queries, this can lead to all sort of problems. To be able to achieve all of above, introduce new context handler base class that works separately of importers. --- lib/gst/plugin/gstclappercontexthandler.c | 86 +++++++++++++++++++++++ lib/gst/plugin/gstclappercontexthandler.h | 62 ++++++++++++++++ lib/gst/plugin/meson.build | 1 + 3 files changed, 149 insertions(+) create mode 100644 lib/gst/plugin/gstclappercontexthandler.c create mode 100644 lib/gst/plugin/gstclappercontexthandler.h diff --git a/lib/gst/plugin/gstclappercontexthandler.c b/lib/gst/plugin/gstclappercontexthandler.c new file mode 100644 index 00000000..990abfc4 --- /dev/null +++ b/lib/gst/plugin/gstclappercontexthandler.c @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2022 Rafał Dzięgiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstclappercontexthandler.h" + +#define parent_class gst_clapper_context_handler_parent_class +G_DEFINE_TYPE (GstClapperContextHandler, gst_clapper_context_handler, GST_TYPE_OBJECT); + +static gboolean +_default_handle_context_query (GstClapperContextHandler *self, + GstBaseSink *bsink, GstQuery *query) +{ + GST_FIXME_OBJECT (self, "Need to handle context query"); + + return FALSE; +} + +static void +gst_clapper_context_handler_init (GstClapperContextHandler *self) +{ +} + +static void +gst_clapper_context_handler_finalize (GObject *object) +{ + GstClapperContextHandler *self = GST_CLAPPER_CONTEXT_HANDLER_CAST (object); + + GST_TRACE_OBJECT (self, "Finalize"); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +gst_clapper_context_handler_class_init (GstClapperContextHandlerClass *klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstClapperContextHandlerClass *handler_class = (GstClapperContextHandlerClass *) klass; + + gobject_class->finalize = gst_clapper_context_handler_finalize; + + handler_class->handle_context_query = _default_handle_context_query; +} + +gboolean +gst_clapper_context_handler_handle_context_query (GstClapperContextHandler *self, + GstBaseSink *bsink, GstQuery *query) +{ + GstClapperContextHandlerClass *handler_class = GST_CLAPPER_CONTEXT_HANDLER_GET_CLASS (self); + + return handler_class->handle_context_query (self, bsink, query); +} + +GstClapperContextHandler * +gst_clapper_context_handler_obtain_with_type (GPtrArray *context_handlers, GType type) +{ + guint i; + + for (i = 0; i < context_handlers->len; i++) { + GstClapperContextHandler *handler = g_ptr_array_index (context_handlers, i); + + if (G_TYPE_CHECK_INSTANCE_TYPE (handler, type)) + return gst_object_ref (handler); + } + + return NULL; +} diff --git a/lib/gst/plugin/gstclappercontexthandler.h b/lib/gst/plugin/gstclappercontexthandler.h new file mode 100644 index 00000000..1231badf --- /dev/null +++ b/lib/gst/plugin/gstclappercontexthandler.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2022 Rafał Dzięgiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CLAPPER_CONTEXT_HANDLER (gst_clapper_context_handler_get_type()) +#define GST_IS_CLAPPER_CONTEXT_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_CONTEXT_HANDLER)) +#define GST_IS_CLAPPER_CONTEXT_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_CONTEXT_HANDLER)) +#define GST_CLAPPER_CONTEXT_HANDLER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_CONTEXT_HANDLER, GstClapperContextHandlerClass)) +#define GST_CLAPPER_CONTEXT_HANDLER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_CONTEXT_HANDLER, GstClapperContextHandler)) +#define GST_CLAPPER_CONTEXT_HANDLER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_CONTEXT_HANDLER, GstClapperContextHandlerClass)) +#define GST_CLAPPER_CONTEXT_HANDLER_CAST(obj) ((GstClapperContextHandler *)(obj)) + +typedef struct _GstClapperContextHandler GstClapperContextHandler; +typedef struct _GstClapperContextHandlerClass GstClapperContextHandlerClass; + +#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC +G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperContextHandler, gst_object_unref) +#endif + +struct _GstClapperContextHandler +{ + GstObject parent; +}; + +struct _GstClapperContextHandlerClass +{ + GstObjectClass parent_class; + + gboolean (* handle_context_query) (GstClapperContextHandler *handler, + GstBaseSink *bsink, + GstQuery *query); +}; + +GType gst_clapper_context_handler_get_type (void); + +gboolean gst_clapper_context_handler_handle_context_query (GstClapperContextHandler *handler, GstBaseSink *bsink, GstQuery *query); + +GstClapperContextHandler * gst_clapper_context_handler_obtain_with_type (GPtrArray *context_handlers, GType type); + +G_END_DECLS diff --git a/lib/gst/plugin/meson.build b/lib/gst/plugin/meson.build index 3a1553d6..48cc4b86 100644 --- a/lib/gst/plugin/meson.build +++ b/lib/gst/plugin/meson.build @@ -41,6 +41,7 @@ gst_clapper_plugin_sources = [ 'gstclapperpaintable.c', 'gstgtkutils.c', 'gstplugin.c', + 'gstclappercontexthandler.c', 'gstclapperimporter.c', 'gstclapperimporterloader.c', ] From 04a028d6897fcf9ef4dff8d7b7d5276d53c86769 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sun, 12 Jun 2022 14:03:36 +0200 Subject: [PATCH 2/3] plugin: Rework code to use new GL context handler Create a GL context handler subclass of recently added context handler base class and rework code to use it. This simplifies a lot of things, like: switching of importers at runtime, handling context queries, sharing data between importers, etc. --- lib/gst/plugin/gstclapperimporter.c | 48 +- lib/gst/plugin/gstclapperimporter.h | 22 +- lib/gst/plugin/gstclapperimporterloader.c | 160 ++-- lib/gst/plugin/gstclapperimporterloader.h | 7 +- lib/gst/plugin/gstclappersink.c | 19 +- .../gl/gstclapperglcontexthandler.c} | 767 ++++++++---------- .../handlers/gl/gstclapperglcontexthandler.h | 64 ++ lib/gst/plugin/handlers/gl/meson.build | 83 ++ lib/gst/plugin/handlers/meson.build | 1 + .../importers/gstclapperglbaseimporter.h | 85 -- .../plugin/importers/gstclapperglimporter.c | 76 +- .../plugin/importers/gstclapperglimporter.h | 9 +- .../plugin/importers/gstclappergluploader.c | 99 +-- .../plugin/importers/gstclappergluploader.h | 15 +- .../plugin/importers/gstclapperrawimporter.c | 12 +- lib/gst/plugin/importers/meson.build | 92 +-- lib/gst/plugin/meson.build | 1 + 17 files changed, 713 insertions(+), 847 deletions(-) rename lib/gst/plugin/{importers/gstclapperglbaseimporter.c => handlers/gl/gstclapperglcontexthandler.c} (59%) create mode 100644 lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.h create mode 100644 lib/gst/plugin/handlers/gl/meson.build create mode 100644 lib/gst/plugin/handlers/meson.build delete mode 100644 lib/gst/plugin/importers/gstclapperglbaseimporter.h diff --git a/lib/gst/plugin/gstclapperimporter.c b/lib/gst/plugin/gstclapperimporter.c index 6caf333f..7921341e 100644 --- a/lib/gst/plugin/gstclapperimporter.c +++ b/lib/gst/plugin/gstclapperimporter.c @@ -89,6 +89,14 @@ _default_create_pool (GstClapperImporter *self, GstStructure **config) return NULL; } +static void +_default_add_allocation_metas (GstClapperImporter *importer, GstQuery *query) +{ + /* Importer base class handles GstVideoOverlayCompositionMeta */ + gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL); + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); +} + static GdkTexture * _default_generate_texture (GstClapperImporter *self, GstBuffer *buffer, GstVideoInfo *v_info) @@ -144,6 +152,7 @@ gst_clapper_importer_class_init (GstClapperImporterClass *klass) gobject_class->finalize = gst_clapper_importer_finalize; importer_class->create_pool = _default_create_pool; + importer_class->add_allocation_metas = _default_add_allocation_metas; importer_class->generate_texture = _default_generate_texture; } @@ -295,30 +304,6 @@ gst_clapper_importer_prepare_overlays_locked (GstClapperImporter *self) GST_LOG_OBJECT (self, "Prepared overlays: %u", self->pending_overlays->len); } -gboolean -gst_clapper_importer_prepare (GstClapperImporter *self) -{ - GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self); - - if (importer_class->prepare) { - if (!importer_class->prepare (self)) - return FALSE; - } - - GST_DEBUG_OBJECT (self, "Importer prepared"); - - return TRUE; -} - -void -gst_clapper_importer_share_data (GstClapperImporter *self, GstClapperImporter *dest) -{ - GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self); - - if (importer_class->share_data) - importer_class->share_data (self, dest); -} - void gst_clapper_importer_set_caps (GstClapperImporter *self, GstCaps *caps) { @@ -362,20 +347,7 @@ gst_clapper_importer_add_allocation_metas (GstClapperImporter *self, GstQuery *q { GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self); - if (importer_class->add_allocation_metas) - importer_class->add_allocation_metas (self, query); -} - -gboolean -gst_clapper_importer_handle_context_query (GstClapperImporter *self, - GstBaseSink *bsink, GstQuery *query) -{ - GstClapperImporterClass *importer_class = GST_CLAPPER_IMPORTER_GET_CLASS (self); - - if (!importer_class->handle_context_query) - return FALSE; - - return importer_class->handle_context_query (self, bsink, query); + importer_class->add_allocation_metas (self, query); } void diff --git a/lib/gst/plugin/gstclapperimporter.h b/lib/gst/plugin/gstclapperimporter.h index 8ba21e74..b3b11e98 100644 --- a/lib/gst/plugin/gstclapperimporter.h +++ b/lib/gst/plugin/gstclapperimporter.h @@ -33,11 +33,11 @@ G_BEGIN_DECLS #define GST_CLAPPER_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_IMPORTER, GstClapperImporterClass)) #define GST_CLAPPER_IMPORTER_CAST(obj) ((GstClapperImporter *)(obj)) -#define GST_CLAPPER_IMPORTER_DEFINE(camel,lower,type) \ -G_DEFINE_TYPE (camel, lower, type) \ -G_MODULE_EXPORT GstClapperImporter *make_importer (void); \ -G_MODULE_EXPORT GstCaps *make_caps (gboolean is_template, \ - GstRank *rank, GStrv *context_types); +#define GST_CLAPPER_IMPORTER_DEFINE(camel,lower,type) \ +G_DEFINE_TYPE (camel, lower, type) \ +G_MODULE_EXPORT GstClapperImporter *make_importer (GPtrArray *context_handlers); \ +G_MODULE_EXPORT GstCaps *make_caps (gboolean is_template, \ + GstRank *rank, GPtrArray *context_handlers); typedef struct _GstClapperImporter GstClapperImporter; typedef struct _GstClapperImporterClass GstClapperImporterClass; @@ -65,18 +65,9 @@ struct _GstClapperImporterClass { GstObjectClass parent_class; - gboolean (* prepare) (GstClapperImporter *importer); - - void (* share_data) (GstClapperImporter *src, - GstClapperImporter *dest); - void (* set_caps) (GstClapperImporter *importer, GstCaps *caps); - gboolean (* handle_context_query) (GstClapperImporter *importer, - GstBaseSink *bsink, - GstQuery *query); - GstBufferPool * (* create_pool) (GstClapperImporter *importer, GstStructure **config); @@ -90,9 +81,6 @@ struct _GstClapperImporterClass GType gst_clapper_importer_get_type (void); -gboolean gst_clapper_importer_prepare (GstClapperImporter *importer); -void gst_clapper_importer_share_data (GstClapperImporter *importer, GstClapperImporter *dest); -gboolean gst_clapper_importer_handle_context_query (GstClapperImporter *importer, GstBaseSink *bsink, GstQuery *query); GstBufferPool * gst_clapper_importer_create_pool (GstClapperImporter *importer, GstStructure **config); void gst_clapper_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query); diff --git a/lib/gst/plugin/gstclapperimporterloader.c b/lib/gst/plugin/gstclapperimporterloader.c index 91bd4845..eb5d73e2 100644 --- a/lib/gst/plugin/gstclapperimporterloader.c +++ b/lib/gst/plugin/gstclapperimporterloader.c @@ -25,6 +25,7 @@ #include "gstclapperimporterloader.h" #include "gstclapperimporter.h" +#include "gstclappercontexthandler.h" #define GST_CAT_DEFAULT gst_clapper_importer_loader_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -32,15 +33,14 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define parent_class gst_clapper_importer_loader_parent_class G_DEFINE_TYPE (GstClapperImporterLoader, gst_clapper_importer_loader, GST_TYPE_OBJECT); -typedef GstClapperImporter* (* MakeImporter) (void); -typedef GstCaps* (* MakeCaps) (gboolean is_template, GstRank *rank, GStrv *context_types); +typedef GstClapperImporter* (* MakeImporter) (GPtrArray *context_handlers); +typedef GstCaps* (* MakeCaps) (gboolean is_template, GstRank *rank, GPtrArray *context_handlers); typedef struct { GModule *module; GstCaps *caps; GstRank rank; - GStrv context_types; } GstClapperImporterData; static void @@ -49,16 +49,17 @@ gst_clapper_importer_data_free (GstClapperImporterData *data) GST_TRACE ("Freeing importer data: %" GST_PTR_FORMAT, data); gst_clear_caps (&data->caps); - g_strfreev (data->context_types); g_free (data); } static GstClapperImporterData * -_obtain_importer_data (GModule *module, gboolean is_template) +_obtain_importer_data (GModule *module, gboolean is_template, GPtrArray *context_handlers) { MakeCaps make_caps; GstClapperImporterData *data; + GST_DEBUG ("Found importer: %s", g_module_name (module)); + if (!g_module_symbol (module, "make_caps", (gpointer *) &make_caps) || make_caps == NULL) { GST_WARNING ("Make caps function missing in importer"); @@ -67,26 +68,30 @@ _obtain_importer_data (GModule *module, gboolean is_template) data = g_new0 (GstClapperImporterData, 1); data->module = module; - data->caps = make_caps (is_template, &data->rank, &data->context_types); + data->caps = make_caps (is_template, &data->rank, context_handlers); GST_TRACE ("Created importer data: %" GST_PTR_FORMAT, data); if (G_UNLIKELY (!data->caps)) { - GST_ERROR ("Invalid importer without caps: %s", - g_module_name (data->module)); + if (!is_template) { + GST_ERROR ("Invalid importer without caps: %s", + g_module_name (data->module)); + } else { + /* When importer cannot be actually used, due to e.g. unsupported HW */ + GST_DEBUG ("No actual caps returned from importer"); + } gst_clapper_importer_data_free (data); return NULL; } - GST_DEBUG ("Found importer: %s, caps: %" GST_PTR_FORMAT, - g_module_name (data->module), data->caps); + GST_DEBUG ("Importer caps: %" GST_PTR_FORMAT, data->caps); return data; } static GstClapperImporter * -_obtain_importer_internal (GModule *module) +_obtain_importer_internal (GModule *module, GPtrArray *context_handlers) { MakeImporter make_importer; GstClapperImporter *importer; @@ -97,7 +102,7 @@ _obtain_importer_internal (GModule *module) return NULL; } - importer = make_importer (); + importer = make_importer (context_handlers); GST_TRACE ("Created importer: %" GST_PTR_FORMAT, importer); return importer; @@ -183,13 +188,14 @@ _sort_importers_cb (gconstpointer a, gconstpointer b) } static GPtrArray * -_obtain_available_importers (gboolean is_template) +_obtain_importers (gboolean is_template, GPtrArray *context_handlers) { const GPtrArray *modules; GPtrArray *importers; guint i; - GST_DEBUG ("Checking available importers"); + GST_DEBUG ("Checking %s importers", + (is_template) ? "available" : "usable"); modules = gst_clapper_importer_loader_get_available_modules (); importers = g_ptr_array_new_with_free_func ( @@ -199,13 +205,14 @@ _obtain_available_importers (gboolean is_template) GModule *module = g_ptr_array_index (modules, i); GstClapperImporterData *data; - if ((data = _obtain_importer_data (module, is_template))) + if ((data = _obtain_importer_data (module, is_template, context_handlers))) g_ptr_array_add (importers, data); } g_ptr_array_sort (importers, (GCompareFunc) _sort_importers_cb); - GST_DEBUG ("Found %i available importers", importers->len); + GST_DEBUG ("Found %i %s importers", importers->len, + (is_template) ? "available" : "usable"); return importers; } @@ -244,7 +251,7 @@ gst_clapper_importer_loader_make_sink_pad_template (void) GST_DEBUG ("Making sink pad template"); - importers = _obtain_available_importers (TRUE); + importers = _obtain_importers (TRUE, NULL); caps = _make_caps_for_importers (importers); g_ptr_array_unref (importers); @@ -265,6 +272,22 @@ gst_clapper_importer_loader_make_actual_caps (GstClapperImporterLoader *self) return _make_caps_for_importers (self->importers); } +gboolean +gst_clapper_importer_loader_handle_context_query (GstClapperImporterLoader *self, + GstBaseSink *bsink, GstQuery *query) +{ + guint i; + + for (i = 0; i < self->context_handlers->len; i++) { + GstClapperContextHandler *handler = g_ptr_array_index (self->context_handlers, i); + + if (gst_clapper_context_handler_handle_context_query (handler, bsink, query)) + return TRUE; + } + + return FALSE; +} + static const GstClapperImporterData * _get_importer_data_for_caps (const GPtrArray *importers, const GstCaps *caps) { @@ -282,89 +305,41 @@ _get_importer_data_for_caps (const GPtrArray *importers, const GstCaps *caps) return NULL; } -static const GstClapperImporterData * -_get_importer_data_for_context_type (const GPtrArray *importers, const gchar *context_type) -{ - guint i; - - for (i = 0; i < importers->len; i++) { - GstClapperImporterData *data = g_ptr_array_index (importers, i); - guint j; - - if (!data->context_types) - continue; - - for (j = 0; data->context_types[j]; j++) { - if (strcmp (context_type, data->context_types[j])) - continue; - - return data; - } - } - - return NULL; -} - -static gboolean -_find_importer_internal (GstClapperImporterLoader *self, - GstCaps *caps, GstQuery *query, GstClapperImporter **importer) +gboolean +gst_clapper_importer_loader_find_importer_for_caps (GstClapperImporterLoader *self, + GstCaps *caps, GstClapperImporter **importer) { const GstClapperImporterData *data = NULL; GstClapperImporter *found_importer = NULL; GST_OBJECT_LOCK (self); - if (caps) { - GST_DEBUG_OBJECT (self, "Requested importer for caps: %" GST_PTR_FORMAT, caps); - data = _get_importer_data_for_caps (self->importers, caps); - } else if (query) { - const gchar *context_type; - - gst_query_parse_context_type (query, &context_type); - - GST_DEBUG_OBJECT (self, "Requested importer for context: %s", context_type); - data = _get_importer_data_for_context_type (self->importers, context_type); - } + GST_DEBUG_OBJECT (self, "Requested importer for caps: %" GST_PTR_FORMAT, caps); + data = _get_importer_data_for_caps (self->importers, caps); GST_LOG_OBJECT (self, "Old importer path: %s, new path: %s", (self->last_module) ? g_module_name (self->last_module) : NULL, (data) ? g_module_name (data->module) : NULL); - if (!data) { - /* In case of missing importer for context query, leave the old one. - * We should allow some queries to go through unresponded */ - if (query) - GST_DEBUG_OBJECT (self, "No importer for query, leaving old one"); - else - gst_clear_object (importer); - + if (G_UNLIKELY (!data)) { + gst_clear_object (importer); goto finish; } if (*importer && (self->last_module == data->module)) { GST_DEBUG_OBJECT (self, "No importer change"); - if (caps) - gst_clapper_importer_set_caps (*importer, caps); - + gst_clapper_importer_set_caps (*importer, caps); goto finish; } - found_importer = _obtain_importer_internal (data->module); - - if (*importer && found_importer) - gst_clapper_importer_share_data (*importer, found_importer); - + found_importer = _obtain_importer_internal (data->module, self->context_handlers); gst_clear_object (importer); - if (!found_importer || !gst_clapper_importer_prepare (found_importer)) { - gst_clear_object (&found_importer); - + if (!found_importer) goto finish; - } - if (caps) - gst_clapper_importer_set_caps (found_importer, caps); + gst_clapper_importer_set_caps (found_importer, caps); *importer = found_importer; @@ -378,33 +353,12 @@ finish: return (*importer != NULL); } -gboolean -gst_clapper_importer_loader_find_importer_for_caps (GstClapperImporterLoader *self, - GstCaps *caps, GstClapperImporter **importer) -{ - return _find_importer_internal (self, caps, NULL, importer); -} - -gboolean -gst_clapper_importer_loader_find_importer_for_context_query (GstClapperImporterLoader *self, - GstQuery *query, GstClapperImporter **importer) -{ - return _find_importer_internal (self, NULL, query, importer); -} - static void gst_clapper_importer_loader_init (GstClapperImporterLoader *self) { -} - -static void -gst_clapper_importer_loader_constructed (GObject *object) -{ - GstClapperImporterLoader *self = GST_CLAPPER_IMPORTER_LOADER_CAST (object); - - self->importers = _obtain_available_importers (FALSE); - - GST_CALL_PARENT (G_OBJECT_CLASS, constructed, (object)); + self->context_handlers = g_ptr_array_new_with_free_func ( + (GDestroyNotify) gst_object_unref); + self->importers = _obtain_importers (FALSE, self->context_handlers); } static void @@ -414,7 +368,10 @@ gst_clapper_importer_loader_finalize (GObject *object) GST_TRACE ("Finalize"); - g_ptr_array_unref (self->importers); + if (self->importers) + g_ptr_array_unref (self->importers); + + g_ptr_array_unref (self->context_handlers); GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } @@ -424,6 +381,5 @@ gst_clapper_importer_loader_class_init (GstClapperImporterLoaderClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; - gobject_class->constructed = gst_clapper_importer_loader_constructed; gobject_class->finalize = gst_clapper_importer_loader_finalize; } diff --git a/lib/gst/plugin/gstclapperimporterloader.h b/lib/gst/plugin/gstclapperimporterloader.h index fd91fb81..b80c375a 100644 --- a/lib/gst/plugin/gstclapperimporterloader.h +++ b/lib/gst/plugin/gstclapperimporterloader.h @@ -20,6 +20,7 @@ #pragma once #include +#include #include "gstclapperimporter.h" @@ -35,7 +36,9 @@ struct _GstClapperImporterLoader GstObject parent; GModule *last_module; + GPtrArray *importers; + GPtrArray *context_handlers; }; GstClapperImporterLoader * gst_clapper_importer_loader_new (void); @@ -44,8 +47,8 @@ GstPadTemplate * gst_clapper_importer_loader_make_sink_pad_template GstCaps * gst_clapper_importer_loader_make_actual_caps (GstClapperImporterLoader *loader); +gboolean gst_clapper_importer_loader_handle_context_query (GstClapperImporterLoader *loader, GstBaseSink *bsink, GstQuery *query); + gboolean gst_clapper_importer_loader_find_importer_for_caps (GstClapperImporterLoader *loader, GstCaps *caps, GstClapperImporter **importer); -gboolean gst_clapper_importer_loader_find_importer_for_context_query (GstClapperImporterLoader *loader, GstQuery *query, GstClapperImporter **importer); - G_END_DECLS diff --git a/lib/gst/plugin/gstclappersink.c b/lib/gst/plugin/gstclappersink.c index 22e6bd76..c9a35f31 100644 --- a/lib/gst/plugin/gstclappersink.c +++ b/lib/gst/plugin/gstclappersink.c @@ -480,25 +480,12 @@ gst_clapper_sink_query (GstBaseSink *bsink, GstQuery *query) GstClapperSink *self = GST_CLAPPER_SINK_CAST (bsink); gboolean res = FALSE; - GST_CLAPPER_SINK_LOCK (self); - if (GST_QUERY_TYPE (query) == GST_QUERY_CONTEXT) { - gboolean is_inactive; - - GST_OBJECT_LOCK (self); - is_inactive = (GST_STATE (self) < GST_STATE_PAUSED); - GST_OBJECT_UNLOCK (self); - - /* Some random context query in the middle of playback - * should not trigger importer replacement */ - if (is_inactive) - gst_clapper_importer_loader_find_importer_for_context_query (self->loader, query, &self->importer); - if (self->importer) - res = gst_clapper_importer_handle_context_query (self->importer, bsink, query); + GST_CLAPPER_SINK_LOCK (self); + res = gst_clapper_importer_loader_handle_context_query (self->loader, bsink, query); + GST_CLAPPER_SINK_UNLOCK (self); } - GST_CLAPPER_SINK_UNLOCK (self); - if (res) return TRUE; diff --git a/lib/gst/plugin/importers/gstclapperglbaseimporter.c b/lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.c similarity index 59% rename from lib/gst/plugin/importers/gstclapperglbaseimporter.c rename to lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.c index c17c64e9..5e864895 100644 --- a/lib/gst/plugin/importers/gstclapperglbaseimporter.c +++ b/lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.c @@ -21,43 +21,41 @@ #include "config.h" #endif -#include "gstclapperglbaseimporter.h" +#include "gstclapperglcontexthandler.h" #include "gst/plugin/gstgdkformats.h" #include "gst/plugin/gstgtkutils.h" -#include - -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND #include #include #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 #include #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX #include #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL || GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL || GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL #include #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 #include #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS #include #endif -#define GST_CAT_DEFAULT gst_clapper_gl_base_importer_debug +#define GST_CAT_DEFAULT gst_clapper_gl_context_handler_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); -#define parent_class gst_clapper_gl_base_importer_parent_class -G_DEFINE_TYPE (GstClapperGLBaseImporter, gst_clapper_gl_base_importer, GST_TYPE_CLAPPER_IMPORTER); +#define parent_class gst_clapper_gl_context_handler_parent_class +G_DEFINE_TYPE (GstClapperGLContextHandler, gst_clapper_gl_context_handler, GST_TYPE_OBJECT); static GstGLContext * -wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platform) +_wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platform) { GstGLAPI gst_gl_api = GST_GL_API_NONE; @@ -85,372 +83,6 @@ wrap_current_gl (GstGLDisplay *display, GdkGLAPI gdk_gl_api, GstGLPlatform platf return NULL; } -static gboolean -retrieve_gl_context_on_main (GstClapperGLBaseImporter *self) -{ - GstClapperGLBaseImporterClass *gl_bi_class = GST_CLAPPER_GL_BASE_IMPORTER_GET_CLASS (self); - GdkDisplay *gdk_display; - GdkGLContext *gdk_context; - GError *error = NULL; - GdkGLAPI gdk_gl_api; - GstGLPlatform platform = GST_GL_PLATFORM_NONE; - gint gl_major = 0, gl_minor = 0; - - if (!gtk_init_check ()) { - GST_ERROR_OBJECT (self, "Could not ensure GTK initialization"); - return FALSE; - } - - /* Make sure we are clean here, otherwise data sharing - * between GL-based importers may lead to leaks */ - gst_clear_object (&self->wrapped_context); - g_clear_object (&self->gdk_context); - gst_clear_object (&self->gst_display); - - gdk_display = gdk_display_get_default (); - - if (G_UNLIKELY (!gdk_display)) { - GST_ERROR_OBJECT (self, "Could not retrieve Gdk display"); - return FALSE; - } - - if (!(gdk_context = gdk_display_create_gl_context (gdk_display, &error))) { - GST_ERROR_OBJECT (self, "Error creating Gdk GL context: %s", - error ? error->message : "No error set by Gdk"); - g_clear_error (&error); - - return FALSE; - } - - if (!gl_bi_class->gdk_context_realize (self, gdk_context)) { - GST_ERROR_OBJECT (self, "Could not realize Gdk context: %" GST_PTR_FORMAT, - gdk_context); - g_object_unref (gdk_context); - - return FALSE; - } - gdk_gl_api = gdk_gl_context_get_api (gdk_context); - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - - self->gdk_context = gdk_context; - -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND - if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { - struct wl_display *wayland_display = - gdk_wayland_display_get_wl_display (gdk_display); - self->gst_display = (GstGLDisplay *) - gst_gl_display_wayland_new_with_display (wayland_display); - } -#endif - -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 - if (GDK_IS_X11_DISPLAY (gdk_display)) { - gpointer display_ptr; -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL - display_ptr = gdk_x11_display_get_egl_display (gdk_display); - if (display_ptr) { - self->gst_display = (GstGLDisplay *) - gst_gl_display_egl_new_with_egl_display (display_ptr); - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX - if (!self->gst_display) { - display_ptr = gdk_x11_display_get_xdisplay (gdk_display); - self->gst_display = (GstGLDisplay *) - gst_gl_display_x11_new_with_display (display_ptr); - } - } -#endif -#endif - -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 - if (GDK_IS_WIN32_DISPLAY (gdk_display)) { -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL - gpointer display_ptr = gdk_win32_display_get_egl_display (gdk_display); - if (display_ptr) { - self->gst_display = (GstGLDisplay *) - gst_gl_display_egl_new_with_egl_display (display_ptr); - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_WGL - if (!self->gst_display) { - self->gst_display = - gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_WIN32); - } - } -#endif -#endif - -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS - if (GDK_IS_MACOS_DISPLAY (gdk_display)) { - self->gst_display = - gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_COCOA); - } -#endif - - /* Fallback to generic display */ - if (G_UNLIKELY (!self->gst_display)) { - GST_WARNING_OBJECT (self, "Unknown Gdk display!"); - self->gst_display = gst_gl_display_new (); - } - -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND - if (GST_IS_GL_DISPLAY_WAYLAND (self->gst_display)) { - platform = GST_GL_PLATFORM_EGL; - GST_INFO_OBJECT (self, "Using EGL on Wayland"); - goto have_display; - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL - if (GST_IS_GL_DISPLAY_EGL (self->gst_display) - && GDK_IS_X11_DISPLAY (gdk_display)) { - platform = GST_GL_PLATFORM_EGL; - GST_INFO_OBJECT (self, "Using EGL on x11"); - goto have_display; - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX - if (GST_IS_GL_DISPLAY_X11 (self->gst_display)) { - platform = GST_GL_PLATFORM_GLX; - GST_INFO_OBJECT (self, "Using GLX on x11"); - goto have_display; - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL - if (GST_IS_GL_DISPLAY_EGL (self->gst_display) - && GDK_IS_WIN32_DISPLAY (gdk_display)) { - platform = GST_GL_PLATFORM_EGL; - GST_INFO_OBJECT (self, "Using EGL on Win32"); - goto have_display; - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_WGL - if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_WIN32) { - platform = GST_GL_PLATFORM_WGL; - GST_INFO_OBJECT (self, "Using WGL on Win32"); - goto have_display; - } -#endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS - if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_COCOA) { - platform = GST_GL_PLATFORM_CGL; - GST_INFO_OBJECT (self, "Using CGL on macOS"); - goto have_display; - } -#endif - - g_clear_object (&self->gdk_context); - gst_clear_object (&self->gst_display); - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - GST_ERROR_OBJECT (self, "Unsupported GL platform"); - return FALSE; - -have_display: - gdk_gl_context_make_current (self->gdk_context); - - self->wrapped_context = wrap_current_gl (self->gst_display, gdk_gl_api, platform); - if (!self->wrapped_context) { - GST_ERROR ("Could not retrieve Gdk OpenGL context"); - gdk_gl_context_clear_current (); - - g_clear_object (&self->gdk_context); - gst_clear_object (&self->gst_display); - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - return FALSE; - } - - GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, self->wrapped_context); - gst_gl_context_activate (self->wrapped_context, TRUE); - - if (!gst_gl_context_fill_info (self->wrapped_context, &error)) { - GST_ERROR ("Failed to fill Gdk context info: %s", error->message); - g_clear_error (&error); - - gst_gl_context_activate (self->wrapped_context, FALSE); - - gst_clear_object (&self->wrapped_context); - g_clear_object (&self->gdk_context); - gst_clear_object (&self->gst_display); - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - return FALSE; - } - - gst_gl_context_get_gl_version (self->wrapped_context, &gl_major, &gl_minor); - GST_INFO ("Using OpenGL%s %i.%i", (gdk_gl_api == GDK_GL_API_GLES) ? " ES" : "", - gl_major, gl_minor); - - /* Deactivate in both places */ - gst_gl_context_activate (self->wrapped_context, FALSE); - gdk_gl_context_clear_current (); - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - return TRUE; -} - -static gboolean -retrieve_gst_context (GstClapperGLBaseImporter *self) -{ - GstGLDisplay *gst_display = NULL; - GstGLContext *gst_context = NULL; - GError *error = NULL; - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - - gst_display = gst_object_ref (self->gst_display); - - /* GstGLDisplay operations require display object lock to be held */ - GST_OBJECT_LOCK (gst_display); - - if (!self->gst_context) { - GST_TRACE_OBJECT (self, "Creating new GstGLContext"); - - if (!gst_gl_display_create_context (gst_display, self->wrapped_context, - &self->gst_context, &error)) { - GST_WARNING ("Could not create OpenGL context: %s", - error ? error->message : "Unknown"); - g_clear_error (&error); - - GST_OBJECT_UNLOCK (gst_display); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - return FALSE; - } - } - - gst_context = gst_object_ref (self->gst_context); - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - gst_gl_display_add_context (gst_display, gst_context); - - GST_OBJECT_UNLOCK (gst_display); - - gst_object_unref (gst_display); - gst_object_unref (gst_context); - - return TRUE; -} - -static gboolean -gst_clapper_gl_base_importer_prepare (GstClapperImporter *importer) -{ - GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); - gboolean need_invoke; - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - need_invoke = (!self->gdk_context || !self->gst_display || !self->wrapped_context); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - if (need_invoke) { - if (!(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) - retrieve_gl_context_on_main, self))) - return FALSE; - } - - if (!retrieve_gst_context (self)) - return FALSE; - - if (!GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare) - return TRUE; - - return GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare (importer); -} - -static void -gst_clapper_gl_base_importer_share_data (GstClapperImporter *importer, GstClapperImporter *dest_importer) -{ - GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER (importer); - - if (GST_IS_CLAPPER_GL_BASE_IMPORTER (dest_importer)) { - GstClapperGLBaseImporter *dest = GST_CLAPPER_GL_BASE_IMPORTER (dest_importer); - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (dest); - - /* Successfully prepared GL importer should have all three */ - if (self->gdk_context && self->gst_display && self->wrapped_context) { - g_clear_object (&dest->gdk_context); - dest->gdk_context = g_object_ref (self->gdk_context); - - gst_clear_object (&dest->gst_display); - dest->gst_display = gst_object_ref (self->gst_display); - - gst_clear_object (&dest->wrapped_context); - dest->wrapped_context = gst_object_ref (self->wrapped_context); - } - - /* This context is not required, we can create it ourselves - * using gst_display and wrapped_context */ - if (self->gst_context) { - gst_clear_object (&dest->gst_context); - dest->gst_context = gst_object_ref (self->gst_context); - } - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (dest); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - } - - if (GST_CLAPPER_IMPORTER_CLASS (parent_class)->share_data) - GST_CLAPPER_IMPORTER_CLASS (parent_class)->share_data (importer, dest_importer); -} - -static gboolean -gst_clapper_gl_base_importer_handle_context_query (GstClapperImporter *importer, - GstBaseSink *bsink, GstQuery *query) -{ - GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); - gboolean res; - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - res = gst_gl_handle_context_query (GST_ELEMENT_CAST (bsink), query, - self->gst_display, self->gst_context, self->wrapped_context); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - return res; -} - -static GstBufferPool * -gst_clapper_gl_base_importer_create_pool (GstClapperImporter *importer, GstStructure **config) -{ - GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); - GstBufferPool *pool; - - GST_DEBUG_OBJECT (self, "Creating new GL buffer pool"); - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - pool = gst_gl_buffer_pool_new (self->gst_context); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - - *config = gst_buffer_pool_get_config (pool); - - gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_VIDEO_META); - gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); - - return pool; -} - -static void -gst_clapper_gl_base_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query) -{ - GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); - - gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL); - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - if (self->gst_context->gl_vtable->FenceSync) - gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); -} - static gboolean _realize_gdk_context_with_api (GdkGLContext *gdk_context, GdkGLAPI api, gint maj, gint min) { @@ -473,7 +105,7 @@ _realize_gdk_context_with_api (GdkGLContext *gdk_context, GdkGLAPI api, gint maj } static gboolean -gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self, GdkGLContext *gdk_context) +_gl_context_handler_context_realize (GstClapperGLContextHandler *self, GdkGLContext *gdk_context) { GdkGLAPI preferred_api = GDK_GL_API_GL; GdkDisplay *gdk_display; @@ -501,15 +133,15 @@ gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self /* Apple decoder uses rectangle texture-target, which GLES does not support. * For Linux we prefer EGL + GLES in order to get direct HW colorspace conversion. * Windows will try EGL + GLES setup first and auto fallback to WGL. */ -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) preferred_api = GDK_GL_API_GLES; #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL if (GDK_IS_X11_DISPLAY (gdk_display) && gdk_x11_display_get_egl_display (gdk_display)) preferred_api = GDK_GL_API_GLES; #endif -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL if (GDK_IS_WIN32_DISPLAY (gdk_display) && gdk_win32_display_get_egl_display (gdk_display)) preferred_api = GDK_GL_API_GLES; #endif @@ -518,7 +150,7 @@ gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self * "scrambled" image on Linux with Intel GPUs that are mostly used together with * x86 CPUs at the expense of using slightly slower non-direct DMABuf import. * See: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1236 */ -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND || GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND || GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL #if !defined(HAVE_GST_PATCHES) && (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64)) preferred_api = GDK_GL_API_GL; #endif @@ -547,16 +179,289 @@ gst_clapper_gl_base_importer_gdk_context_realize (GstClapperGLBaseImporter *self return success; } -static void -gst_clapper_gl_base_importer_init (GstClapperGLBaseImporter *self) +static gboolean +_retrieve_gl_context_on_main (GstClapperGLContextHandler *self) { - g_mutex_init (&self->lock); + GdkDisplay *gdk_display; + GdkGLContext *gdk_context; + GError *error = NULL; + GdkGLAPI gdk_gl_api; + GstGLPlatform platform = GST_GL_PLATFORM_NONE; + gint gl_major = 0, gl_minor = 0; + + if (!gtk_init_check ()) { + GST_ERROR_OBJECT (self, "Could not ensure GTK initialization"); + return FALSE; + } + + gdk_display = gdk_display_get_default (); + + if (G_UNLIKELY (!gdk_display)) { + GST_ERROR_OBJECT (self, "Could not retrieve Gdk display"); + return FALSE; + } + + if (!(gdk_context = gdk_display_create_gl_context (gdk_display, &error))) { + GST_ERROR_OBJECT (self, "Error creating Gdk GL context: %s", + error ? error->message : "No error set by Gdk"); + g_clear_error (&error); + + return FALSE; + } + + if (!_gl_context_handler_context_realize (self, gdk_context)) { + GST_ERROR_OBJECT (self, "Could not realize Gdk context: %" GST_PTR_FORMAT, + gdk_context); + g_object_unref (gdk_context); + + return FALSE; + } + gdk_gl_api = gdk_gl_context_get_api (gdk_context); + + GST_OBJECT_LOCK (self); + + self->gdk_context = gdk_context; + +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND + if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) { + struct wl_display *wayland_display = + gdk_wayland_display_get_wl_display (gdk_display); + self->gst_display = (GstGLDisplay *) + gst_gl_display_wayland_new_with_display (wayland_display); + } +#endif + +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 + if (GDK_IS_X11_DISPLAY (gdk_display)) { + gpointer display_ptr; +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL + display_ptr = gdk_x11_display_get_egl_display (gdk_display); + if (display_ptr) { + self->gst_display = (GstGLDisplay *) + gst_gl_display_egl_new_with_egl_display (display_ptr); + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX + if (!self->gst_display) { + display_ptr = gdk_x11_display_get_xdisplay (gdk_display); + self->gst_display = (GstGLDisplay *) + gst_gl_display_x11_new_with_display (display_ptr); + } + } +#endif +#endif + +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 + if (GDK_IS_WIN32_DISPLAY (gdk_display)) { +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL + gpointer display_ptr = gdk_win32_display_get_egl_display (gdk_display); + if (display_ptr) { + self->gst_display = (GstGLDisplay *) + gst_gl_display_egl_new_with_egl_display (display_ptr); + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_WGL + if (!self->gst_display) { + self->gst_display = + gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_WIN32); + } + } +#endif +#endif + +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS + if (GDK_IS_MACOS_DISPLAY (gdk_display)) { + self->gst_display = + gst_gl_display_new_with_type (GST_GL_DISPLAY_TYPE_COCOA); + } +#endif + + /* Fallback to generic display */ + if (G_UNLIKELY (!self->gst_display)) { + GST_WARNING_OBJECT (self, "Unknown Gdk display!"); + self->gst_display = gst_gl_display_new (); + } + +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND + if (GST_IS_GL_DISPLAY_WAYLAND (self->gst_display)) { + platform = GST_GL_PLATFORM_EGL; + GST_INFO_OBJECT (self, "Using EGL on Wayland"); + goto have_display; + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL + if (GST_IS_GL_DISPLAY_EGL (self->gst_display) + && GDK_IS_X11_DISPLAY (gdk_display)) { + platform = GST_GL_PLATFORM_EGL; + GST_INFO_OBJECT (self, "Using EGL on x11"); + goto have_display; + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX + if (GST_IS_GL_DISPLAY_X11 (self->gst_display)) { + platform = GST_GL_PLATFORM_GLX; + GST_INFO_OBJECT (self, "Using GLX on x11"); + goto have_display; + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL + if (GST_IS_GL_DISPLAY_EGL (self->gst_display) + && GDK_IS_WIN32_DISPLAY (gdk_display)) { + platform = GST_GL_PLATFORM_EGL; + GST_INFO_OBJECT (self, "Using EGL on Win32"); + goto have_display; + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_WGL + if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_WIN32) { + platform = GST_GL_PLATFORM_WGL; + GST_INFO_OBJECT (self, "Using WGL on Win32"); + goto have_display; + } +#endif +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS + if (gst_gl_display_get_handle_type (self->gst_display) == GST_GL_DISPLAY_TYPE_COCOA) { + platform = GST_GL_PLATFORM_CGL; + GST_INFO_OBJECT (self, "Using CGL on macOS"); + goto have_display; + } +#endif + + g_clear_object (&self->gdk_context); + gst_clear_object (&self->gst_display); + + GST_OBJECT_UNLOCK (self); + + GST_ERROR_OBJECT (self, "Unsupported GL platform"); + return FALSE; + +have_display: + gdk_gl_context_make_current (self->gdk_context); + + self->wrapped_context = _wrap_current_gl (self->gst_display, gdk_gl_api, platform); + if (!self->wrapped_context) { + GST_ERROR ("Could not retrieve Gdk OpenGL context"); + gdk_gl_context_clear_current (); + + g_clear_object (&self->gdk_context); + gst_clear_object (&self->gst_display); + + GST_OBJECT_UNLOCK (self); + + return FALSE; + } + + GST_INFO ("Retrieved Gdk OpenGL context %" GST_PTR_FORMAT, self->wrapped_context); + gst_gl_context_activate (self->wrapped_context, TRUE); + + if (!gst_gl_context_fill_info (self->wrapped_context, &error)) { + GST_ERROR ("Failed to fill Gdk context info: %s", error->message); + g_clear_error (&error); + + gst_gl_context_activate (self->wrapped_context, FALSE); + + gst_clear_object (&self->wrapped_context); + g_clear_object (&self->gdk_context); + gst_clear_object (&self->gst_display); + + GST_OBJECT_UNLOCK (self); + + return FALSE; + } + + gst_gl_context_get_gl_version (self->wrapped_context, &gl_major, &gl_minor); + GST_INFO ("Using OpenGL%s %i.%i", (gdk_gl_api == GDK_GL_API_GLES) ? " ES" : "", + gl_major, gl_minor); + + /* Deactivate in both places */ + gst_gl_context_activate (self->wrapped_context, FALSE); + gdk_gl_context_clear_current (); + + GST_OBJECT_UNLOCK (self); + + return TRUE; +} + +static gboolean +_retrieve_gst_context (GstClapperGLContextHandler *self) +{ + GstGLDisplay *gst_display = NULL; + GstGLContext *gst_context = NULL; + GError *error = NULL; + + GST_OBJECT_LOCK (self); + + gst_display = gst_object_ref (self->gst_display); + GST_TRACE_OBJECT (self, "Creating new GstGLContext"); + + /* GstGLDisplay operations require display object lock to be held */ + GST_OBJECT_LOCK (gst_display); + + if (!gst_gl_display_create_context (gst_display, self->wrapped_context, + &self->gst_context, &error)) { + GST_WARNING ("Could not create OpenGL context: %s", + error ? error->message : "Unknown"); + g_clear_error (&error); + + GST_OBJECT_UNLOCK (gst_display); + GST_OBJECT_UNLOCK (self); + + return FALSE; + } + + gst_context = gst_object_ref (self->gst_context); + + GST_OBJECT_UNLOCK (self); + + gst_gl_display_add_context (gst_display, gst_context); + + GST_OBJECT_UNLOCK (gst_display); + + gst_object_unref (gst_display); + gst_object_unref (gst_context); + + return TRUE; +} + +static gboolean +gst_clapper_gl_context_handler_handle_context_query (GstClapperContextHandler *handler, + GstBaseSink *bsink, GstQuery *query) +{ + GstClapperGLContextHandler *self = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (handler); + gboolean res; + + GST_OBJECT_LOCK (self); + res = gst_gl_handle_context_query (GST_ELEMENT_CAST (bsink), query, + self->gst_display, self->gst_context, self->wrapped_context); + GST_OBJECT_UNLOCK (self); + + return res; } static void -gst_clapper_gl_base_importer_finalize (GObject *object) +gst_clapper_gl_context_handler_init (GstClapperGLContextHandler *self) { - GstClapperGLBaseImporter *self = GST_CLAPPER_GL_BASE_IMPORTER_CAST (object); +} + +static void +gst_clapper_gl_context_handler_constructed (GObject *object) +{ + GstClapperGLContextHandler *self = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (object); + + if (! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) + _retrieve_gl_context_on_main, self)) { + _retrieve_gst_context (self); + } + + GST_CALL_PARENT (G_OBJECT_CLASS, constructed, (object)); +} + +static void +gst_clapper_gl_context_handler_finalize (GObject *object) +{ + GstClapperGLContextHandler *self = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (object); + + GST_TRACE ("Finalize"); g_clear_object (&self->gdk_context); @@ -564,70 +469,74 @@ gst_clapper_gl_base_importer_finalize (GObject *object) gst_clear_object (&self->wrapped_context); gst_clear_object (&self->gst_context); - g_mutex_clear (&self->lock); - GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } static void -gst_clapper_gl_base_importer_class_init (GstClapperGLBaseImporterClass *klass) +gst_clapper_gl_context_handler_class_init (GstClapperGLContextHandlerClass *klass) { GObjectClass *gobject_class = (GObjectClass *) klass; - GstClapperImporterClass *importer_class = (GstClapperImporterClass *) klass; - GstClapperGLBaseImporterClass *gl_bi_class = (GstClapperGLBaseImporterClass *) klass; + GstClapperContextHandlerClass *handler_class = (GstClapperContextHandlerClass *) klass; - GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglbaseimporter", 0, - "Clapper GL Base Importer"); + GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglcontexthandler", 0, + "Clapper GL Context Handler"); - gobject_class->finalize = gst_clapper_gl_base_importer_finalize; + gobject_class->constructed = gst_clapper_gl_context_handler_constructed; + gobject_class->finalize = gst_clapper_gl_context_handler_finalize; - importer_class->prepare = gst_clapper_gl_base_importer_prepare; - importer_class->share_data = gst_clapper_gl_base_importer_share_data; - importer_class->handle_context_query = gst_clapper_gl_base_importer_handle_context_query; - importer_class->create_pool = gst_clapper_gl_base_importer_create_pool; - importer_class->add_allocation_metas = gst_clapper_gl_base_importer_add_allocation_metas; + handler_class->handle_context_query = gst_clapper_gl_context_handler_handle_context_query; +} - gl_bi_class->gdk_context_realize = gst_clapper_gl_base_importer_gdk_context_realize; +void +gst_clapper_gl_context_handler_add_handler (GPtrArray *context_handlers) +{ + guint i; + gboolean found = FALSE; + + for (i = 0; i < context_handlers->len; i++) { + GstClapperContextHandler *handler = g_ptr_array_index (context_handlers, i); + + if ((found = GST_IS_CLAPPER_GL_CONTEXT_HANDLER (handler))) + break; + } + + if (!found) { + GstClapperGLContextHandler *handler = g_object_new ( + GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER, NULL); + + g_ptr_array_add (context_handlers, handler); + GST_DEBUG ("Added GL context handler to handlers array"); + } } GstCaps * -gst_clapper_gl_base_importer_make_supported_gdk_gl_caps (void) +gst_clapper_gl_context_handler_make_gdk_gl_caps (const gchar *features, gboolean only_2d) { GstCaps *caps, *tmp; - tmp = gst_caps_from_string ( - GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_GL_MEMORY, - "{ " GST_GDK_GL_TEXTURE_FORMATS " }") ", " - "texture-target = (string) { " GST_GL_TEXTURE_TARGET_2D_STR " }"); + if (only_2d) { + tmp = gst_caps_from_string (GST_VIDEO_CAPS_MAKE ( + "{ " GST_GDK_GL_TEXTURE_FORMATS " }") ", " + "texture-target = (string) { " GST_GL_TEXTURE_TARGET_2D_STR " }"); + } else { + tmp = gst_caps_from_string (GST_VIDEO_CAPS_MAKE ( + "{ " GST_GDK_GL_TEXTURE_FORMATS " }")); + } caps = gst_caps_copy (tmp); + + gst_caps_set_features_simple (tmp, gst_caps_features_new ( + features, NULL)); gst_caps_set_features_simple (caps, gst_caps_features_new ( - GST_CAPS_FEATURE_MEMORY_GL_MEMORY, - GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL)); + features, GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION, NULL)); gst_caps_append (caps, tmp); return caps; } -GStrv -gst_clapper_gl_base_importer_make_gl_context_types (void) -{ - GStrv context_types; - GStrvBuilder *builder = g_strv_builder_new (); - - g_strv_builder_add (builder, GST_GL_DISPLAY_CONTEXT_TYPE); - g_strv_builder_add (builder, "gst.gl.app_context"); - g_strv_builder_add (builder, "gst.gl.local_context"); - - context_types = g_strv_builder_end (builder); - g_strv_builder_unref (builder); - - return context_types; -} - GdkTexture * -gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self, +gst_clapper_gl_context_handler_make_gl_texture (GstClapperGLContextHandler *self, GstBuffer *buffer, GstVideoInfo *v_info) { GdkTexture *texture; @@ -639,7 +548,7 @@ gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self, return NULL; } - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); + GST_OBJECT_LOCK (self); /* Must have context active here for both sync meta * and Gdk texture format auto-detection to work */ @@ -666,7 +575,7 @@ gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self, gst_gl_context_activate (self->wrapped_context, FALSE); gdk_gl_context_clear_current (); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); + GST_OBJECT_UNLOCK (self); gst_video_frame_unmap (&frame); diff --git a/lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.h b/lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.h new file mode 100644 index 00000000..9bfc7dd8 --- /dev/null +++ b/lib/gst/plugin/handlers/gl/gstclapperglcontexthandler.h @@ -0,0 +1,64 @@ +/* + * Copyright (C) 2022 Rafał Dzięgiel + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#pragma once + +#include +#include +#include +#include + +#include + +#include "gst/plugin/gstclappercontexthandler.h" + +G_BEGIN_DECLS + +#define GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER (gst_clapper_gl_context_handler_get_type()) +G_DECLARE_FINAL_TYPE (GstClapperGLContextHandler, gst_clapper_gl_context_handler, GST, CLAPPER_GL_CONTEXT_HANDLER, GstClapperContextHandler) + +#define GST_CLAPPER_GL_CONTEXT_HANDLER_CAST(obj) ((GstClapperGLContextHandler *)(obj)) + +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WAYLAND (GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND)) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 (GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11)) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 && GST_GL_HAVE_PLATFORM_GLX) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 && GST_GL_HAVE_PLATFORM_EGL) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 (GST_GL_HAVE_WINDOW_WIN32 && defined (GDK_WINDOWING_WIN32)) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_WGL (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_WGL) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32_EGL (GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_EGL) +#define GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_MACOS (GST_GL_HAVE_WINDOW_COCOA && defined (GDK_WINDOWING_MACOS) && GST_GL_HAVE_PLATFORM_CGL) + +struct _GstClapperGLContextHandler +{ + GstClapperContextHandler parent; + + GdkGLContext *gdk_context; + + GstGLDisplay *gst_display; + GstGLContext *wrapped_context; + GstGLContext *gst_context; +}; + +void gst_clapper_gl_context_handler_add_handler (GPtrArray *context_handlers); + +GstCaps * gst_clapper_gl_context_handler_make_gdk_gl_caps (const gchar *features, gboolean only_2d); + +GdkTexture * gst_clapper_gl_context_handler_make_gl_texture (GstClapperGLContextHandler *handler, GstBuffer *buffer, GstVideoInfo *v_info); + +G_END_DECLS diff --git a/lib/gst/plugin/handlers/gl/meson.build b/lib/gst/plugin/handlers/gl/meson.build new file mode 100644 index 00000000..1a8409e4 --- /dev/null +++ b/lib/gst/plugin/handlers/gl/meson.build @@ -0,0 +1,83 @@ +gst_clapper_gl_ch_dep = dependency('', required: false) + +build_gl_ch = ( + not get_option('glimporter').disabled() + or not get_option('gluploader').disabled() +) +gl_support_required = ( + get_option('glimporter').enabled() + or get_option('gluploader').enabled() +) + +gst_plugin_gl_ch_deps = [gst_clapper_sink_dep, gstgl_dep, gstglproto_dep] +have_gtk_gl_windowing = false + +if gst_gl_have_window_x11 and (gst_gl_have_platform_egl or gst_gl_have_platform_glx) + gtk_x11_dep = dependency('gtk4-x11', required: false) + if gtk_x11_dep.found() + gst_plugin_gl_ch_deps += gtk_x11_dep + if gst_gl_have_platform_glx + gst_plugin_gl_ch_deps += gstglx11_dep + endif + have_gtk_gl_windowing = true + endif +endif + +if gst_gl_have_window_wayland and gst_gl_have_platform_egl + gtk_wayland_dep = dependency('gtk4-wayland', required: false) + if gtk_wayland_dep.found() + gst_plugin_gl_ch_deps += [gtk_wayland_dep, gstglwayland_dep] + have_gtk_gl_windowing = true + endif +endif + +if gst_gl_have_window_win32 and (gst_gl_have_platform_egl or gst_gl_have_platform_wgl) + gtk_win32_dep = dependency('gtk4-win32', required: false) + if gtk_win32_dep.found() + gst_plugin_gl_ch_deps += gtk_win32_dep + have_gtk_gl_windowing = true + endif +endif + +if gst_gl_have_window_cocoa and gst_gl_have_platform_cgl + gtk_macos_dep = dependency('gtk4-macos', required: false) + if gtk_macos_dep.found() + gst_plugin_gl_ch_deps += gtk_macos_dep + have_gtk_gl_windowing = true + endif +endif + +if not have_gtk_gl_windowing + if gl_support_required + error('GL-based importer was enabled, but support for current GL windowing is missing') + endif + build_gl_ch = false +endif + +if gst_gl_have_platform_egl + gst_plugin_gl_ch_deps += gstglegl_dep +endif + +foreach dep : gst_plugin_gl_ch_deps + if not dep.found() + if gl_support_required + error('GL-based importer was enabled, but required dependencies were not found') + endif + build_gl_ch = false + endif +endforeach + +if build_gl_ch + gst_clapper_gl_ch_dep = declare_dependency( + link_with: library('gstclapperglcontexthandler', + 'gstclapperglcontexthandler.c', + c_args: gst_clapper_plugin_args, + include_directories: configinc, + dependencies: gst_plugin_gl_ch_deps, + version: libversion, + install: true, + ), + include_directories: configinc, + dependencies: gst_plugin_gl_ch_deps, + ) +endif diff --git a/lib/gst/plugin/handlers/meson.build b/lib/gst/plugin/handlers/meson.build new file mode 100644 index 00000000..18ec273a --- /dev/null +++ b/lib/gst/plugin/handlers/meson.build @@ -0,0 +1 @@ +subdir('gl') diff --git a/lib/gst/plugin/importers/gstclapperglbaseimporter.h b/lib/gst/plugin/importers/gstclapperglbaseimporter.h deleted file mode 100644 index ee44e9e1..00000000 --- a/lib/gst/plugin/importers/gstclapperglbaseimporter.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2022 Rafał Dzięgiel - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#pragma once - -#include - -#include "gst/plugin/gstclapperimporter.h" - -G_BEGIN_DECLS - -#define GST_TYPE_CLAPPER_GL_BASE_IMPORTER (gst_clapper_gl_base_importer_get_type()) -#define GST_IS_CLAPPER_GL_BASE_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORTER)) -#define GST_IS_CLAPPER_GL_BASE_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CLAPPER_GL_BASE_IMPORTER)) -#define GST_CLAPPER_GL_BASE_IMPORTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORTER, GstClapperGLBaseImporterClass)) -#define GST_CLAPPER_GL_BASE_IMPORTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_CLAPPER_GL_BASE_IMPORTER, GstClapperGLBaseImporter)) -#define GST_CLAPPER_GL_BASE_IMPORTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_CLAPPER_GL_BASE_IMPORTER, GstClapperGLBaseImporterClass)) -#define GST_CLAPPER_GL_BASE_IMPORTER_CAST(obj) ((GstClapperGLBaseImporter *)(obj)) - -#define GST_CLAPPER_GL_BASE_IMPORTER_GET_LOCK(obj) (&GST_CLAPPER_GL_BASE_IMPORTER_CAST(obj)->lock) -#define GST_CLAPPER_GL_BASE_IMPORTER_LOCK(obj) g_mutex_lock (GST_CLAPPER_GL_BASE_IMPORTER_GET_LOCK(obj)) -#define GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_GL_BASE_IMPORTER_GET_LOCK(obj)) - -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WAYLAND (GST_GL_HAVE_WINDOW_WAYLAND && defined (GDK_WINDOWING_WAYLAND)) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 (GST_GL_HAVE_WINDOW_X11 && defined (GDK_WINDOWING_X11)) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 && GST_GL_HAVE_PLATFORM_GLX) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 && GST_GL_HAVE_PLATFORM_EGL) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 (GST_GL_HAVE_WINDOW_WIN32 && defined (GDK_WINDOWING_WIN32)) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_WGL (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_WGL) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32_EGL (GST_CLAPPER_GL_BASE_IMPORTER_HAVE_WIN32 && GST_GL_HAVE_PLATFORM_EGL) -#define GST_CLAPPER_GL_BASE_IMPORTER_HAVE_MACOS (GST_GL_HAVE_WINDOW_COCOA && defined (GDK_WINDOWING_MACOS) && GST_GL_HAVE_PLATFORM_CGL) - -typedef struct _GstClapperGLBaseImporter GstClapperGLBaseImporter; -typedef struct _GstClapperGLBaseImporterClass GstClapperGLBaseImporterClass; - -#ifdef G_DEFINE_AUTOPTR_CLEANUP_FUNC -G_DEFINE_AUTOPTR_CLEANUP_FUNC (GstClapperGLBaseImporter, gst_object_unref) -#endif - -struct _GstClapperGLBaseImporter -{ - GstClapperImporter parent; - - GMutex lock; - - GdkGLContext *gdk_context; - - GstGLDisplay *gst_display; - GstGLContext *wrapped_context; - GstGLContext *gst_context; -}; - -struct _GstClapperGLBaseImporterClass -{ - GstClapperImporterClass parent_class; - - gboolean (* gdk_context_realize) (GstClapperGLBaseImporter *gl_bi, - GdkGLContext *gdk_context); -}; - -GType gst_clapper_gl_base_importer_get_type (void); - -GstCaps * gst_clapper_gl_base_importer_make_supported_gdk_gl_caps (void); - -GStrv gst_clapper_gl_base_importer_make_gl_context_types (void); - -GdkTexture * gst_clapper_gl_base_importer_make_gl_texture (GstClapperGLBaseImporter *self, GstBuffer *buffer, GstVideoInfo *v_info); - -G_END_DECLS diff --git a/lib/gst/plugin/importers/gstclapperglimporter.c b/lib/gst/plugin/importers/gstclapperglimporter.c index f919a734..d80289f4 100644 --- a/lib/gst/plugin/importers/gstclapperglimporter.c +++ b/lib/gst/plugin/importers/gstclapperglimporter.c @@ -27,15 +27,45 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define parent_class gst_clapper_gl_importer_parent_class -GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLImporter, gst_clapper_gl_importer, GST_TYPE_CLAPPER_GL_BASE_IMPORTER); +GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLImporter, gst_clapper_gl_importer, GST_TYPE_CLAPPER_IMPORTER); + +static GstBufferPool * +gst_clapper_gl_importer_create_pool (GstClapperImporter *importer, GstStructure **config) +{ + GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (importer); + GstBufferPool *pool; + + GST_DEBUG_OBJECT (self, "Creating new GL buffer pool"); + + pool = gst_gl_buffer_pool_new (self->gl_handler->gst_context); + *config = gst_buffer_pool_get_config (pool); + + gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_VIDEO_META); + gst_buffer_pool_config_add_option (*config, GST_BUFFER_POOL_OPTION_GL_SYNC_META); + + return pool; +} + +static void +gst_clapper_gl_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query) +{ + GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (importer); + + /* We can support GL sync meta */ + if (self->gl_handler->gst_context->gl_vtable->FenceSync) + gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL); + + /* Also add base importer class supported meta */ + GST_CLAPPER_IMPORTER_CLASS (parent_class)->add_allocation_metas (importer, query); +} static GdkTexture * gst_clapper_gl_importer_generate_texture (GstClapperImporter *importer, GstBuffer *buffer, GstVideoInfo *v_info) { - GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); + GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (importer); - return gst_clapper_gl_base_importer_make_gl_texture (gl_bi, buffer, v_info); + return gst_clapper_gl_context_handler_make_gl_texture (self->gl_handler, buffer, v_info); } static void @@ -43,28 +73,58 @@ gst_clapper_gl_importer_init (GstClapperGLImporter *self) { } +static void +gst_clapper_gl_importer_finalize (GObject *object) +{ + GstClapperGLImporter *self = GST_CLAPPER_GL_IMPORTER_CAST (object); + + gst_clear_object (&self->gl_handler); + + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + static void gst_clapper_gl_importer_class_init (GstClapperGLImporterClass *klass) { + GObjectClass *gobject_class = (GObjectClass *) klass; GstClapperImporterClass *importer_class = (GstClapperImporterClass *) klass; GST_DEBUG_CATEGORY_INIT (GST_CAT_DEFAULT, "clapperglimporter", 0, "Clapper GL Importer"); + gobject_class->finalize = gst_clapper_gl_importer_finalize; + + importer_class->create_pool = gst_clapper_gl_importer_create_pool; + importer_class->add_allocation_metas = gst_clapper_gl_importer_add_allocation_metas; importer_class->generate_texture = gst_clapper_gl_importer_generate_texture; } GstClapperImporter * -make_importer (void) +make_importer (GPtrArray *context_handlers) { - return g_object_new (GST_TYPE_CLAPPER_GL_IMPORTER, NULL); + GstClapperGLImporter *self; + GstClapperContextHandler *handler; + + handler = gst_clapper_context_handler_obtain_with_type (context_handlers, + GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER); + + if (G_UNLIKELY (!handler)) + return NULL; + + self = g_object_new (GST_TYPE_CLAPPER_GL_IMPORTER, NULL); + self->gl_handler = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (handler); + + return GST_CLAPPER_IMPORTER_CAST (self); } GstCaps * -make_caps (gboolean is_template, GstRank *rank, GStrv *context_types) +make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers) { *rank = GST_RANK_SECONDARY; - *context_types = gst_clapper_gl_base_importer_make_gl_context_types (); - return gst_clapper_gl_base_importer_make_supported_gdk_gl_caps (); + if (!is_template && context_handlers) + gst_clapper_gl_context_handler_add_handler (context_handlers); + + return gst_clapper_gl_context_handler_make_gdk_gl_caps ( + GST_CAPS_FEATURE_MEMORY_GL_MEMORY, TRUE); } diff --git a/lib/gst/plugin/importers/gstclapperglimporter.h b/lib/gst/plugin/importers/gstclapperglimporter.h index 7c9cb3d3..93282516 100644 --- a/lib/gst/plugin/importers/gstclapperglimporter.h +++ b/lib/gst/plugin/importers/gstclapperglimporter.h @@ -19,18 +19,21 @@ #pragma once -#include "gstclapperglbaseimporter.h" +#include "gst/plugin/gstclapperimporter.h" +#include "gst/plugin/handlers/gl/gstclapperglcontexthandler.h" G_BEGIN_DECLS #define GST_TYPE_CLAPPER_GL_IMPORTER (gst_clapper_gl_importer_get_type()) -G_DECLARE_FINAL_TYPE (GstClapperGLImporter, gst_clapper_gl_importer, GST, CLAPPER_GL_IMPORTER, GstClapperGLBaseImporter) +G_DECLARE_FINAL_TYPE (GstClapperGLImporter, gst_clapper_gl_importer, GST, CLAPPER_GL_IMPORTER, GstClapperImporter) #define GST_CLAPPER_GL_IMPORTER_CAST(obj) ((GstClapperGLImporter *)(obj)) struct _GstClapperGLImporter { - GstClapperGLBaseImporter parent; + GstClapperImporter parent; + + GstClapperGLContextHandler *gl_handler; }; G_END_DECLS diff --git a/lib/gst/plugin/importers/gstclappergluploader.c b/lib/gst/plugin/importers/gstclappergluploader.c index 3f779349..b03e6f77 100644 --- a/lib/gst/plugin/importers/gstclappergluploader.c +++ b/lib/gst/plugin/importers/gstclappergluploader.c @@ -24,7 +24,7 @@ #include "gstclappergluploader.h" #include "gst/plugin/gstgtkutils.h" -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11 +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 #include #endif @@ -32,30 +32,33 @@ GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); #define parent_class gst_clapper_gl_uploader_parent_class -GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLUploader, gst_clapper_gl_uploader, GST_TYPE_CLAPPER_GL_BASE_IMPORTER); +GST_CLAPPER_IMPORTER_DEFINE (GstClapperGLUploader, gst_clapper_gl_uploader, GST_TYPE_CLAPPER_IMPORTER); static void _update_elements_caps_locked (GstClapperGLUploader *self, GstCaps *upload_sink_caps) { - GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (self); + GstGLContext *gst_context; GstCaps *upload_src_caps, *color_sink_caps, *color_src_caps, *gdk_sink_caps; + gst_context = self->gl_handler->gst_context; + GST_INFO_OBJECT (self, "Input caps: %" GST_PTR_FORMAT, upload_sink_caps); - upload_src_caps = gst_gl_upload_transform_caps (self->upload, gl_bi->gst_context, + upload_src_caps = gst_gl_upload_transform_caps (self->upload, gst_context, GST_PAD_SINK, upload_sink_caps, NULL); upload_src_caps = gst_caps_fixate (upload_src_caps); GST_INFO_OBJECT (self, "GLUpload caps: %" GST_PTR_FORMAT, upload_src_caps); gst_gl_upload_set_caps (self->upload, upload_sink_caps, upload_src_caps); - gdk_sink_caps = gst_clapper_gl_base_importer_make_supported_gdk_gl_caps (); - color_sink_caps = gst_gl_color_convert_transform_caps (gl_bi->gst_context, + gdk_sink_caps = gst_clapper_gl_context_handler_make_gdk_gl_caps ( + GST_CAPS_FEATURE_MEMORY_GL_MEMORY, TRUE); + color_sink_caps = gst_gl_color_convert_transform_caps (gst_context, GST_PAD_SRC, upload_src_caps, gdk_sink_caps); gst_caps_unref (gdk_sink_caps); /* Second caps arg is transfer-full */ - color_src_caps = gst_gl_color_convert_fixate_caps (gl_bi->gst_context, + color_src_caps = gst_gl_color_convert_fixate_caps (gst_context, GST_PAD_SINK, upload_src_caps, color_sink_caps); GST_INFO_OBJECT (self, "GLColorConvert caps: %" GST_PTR_FORMAT, color_src_caps); @@ -72,9 +75,9 @@ gst_clapper_gl_uploader_set_caps (GstClapperImporter *importer, GstCaps *caps) { GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer); - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); + GST_CLAPPER_GL_UPLOADER_LOCK (self); _update_elements_caps_locked (self, caps); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); + GST_CLAPPER_GL_UPLOADER_UNLOCK (self); } static void @@ -92,28 +95,6 @@ _uploader_reconfigure_locked (GstClapperGLUploader *self) } } -static gboolean -gst_clapper_gl_uploader_prepare (GstClapperImporter *importer) -{ - gboolean res = GST_CLAPPER_IMPORTER_CLASS (parent_class)->prepare (importer); - - if (res) { - GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer); - GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); - - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); - - if (!self->upload) - self->upload = gst_gl_upload_new (gl_bi->gst_context); - if (!self->color_convert) - self->color_convert = gst_gl_color_convert_new (gl_bi->gst_context); - - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); - } - - return res; -} - static GstBuffer * _upload_perform_locked (GstClapperGLUploader *self, GstBuffer *buffer) { @@ -152,13 +133,19 @@ gst_clapper_gl_uploader_add_allocation_metas (GstClapperImporter *importer, GstQ GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer); GstGLUpload *upload; - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); + GST_CLAPPER_GL_UPLOADER_LOCK (self); upload = gst_object_ref (self->upload); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); + GST_CLAPPER_GL_UPLOADER_UNLOCK (self); + /* Add glupload supported meta */ gst_gl_upload_propose_allocation (upload, NULL, query); gst_object_unref (upload); + /* We can support GL sync meta */ + if (self->gl_handler->gst_context->gl_vtable->FenceSync) + gst_query_add_allocation_meta (query, GST_GL_SYNC_META_API_TYPE, NULL); + + /* Also add base importer class supported meta */ GST_CLAPPER_IMPORTER_CLASS (parent_class)->add_allocation_metas (importer, query); } @@ -167,7 +154,6 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer, GstBuffer *buffer, GstVideoInfo *v_info) { GstClapperGLUploader *self = GST_CLAPPER_GL_UPLOADER_CAST (importer); - GstClapperGLBaseImporter *gl_bi = GST_CLAPPER_GL_BASE_IMPORTER_CAST (importer); GstBuffer *upload_buf, *color_buf; GdkTexture *texture; @@ -177,13 +163,13 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer, GST_LOG_OBJECT (self, "Uploading %" GST_PTR_FORMAT, buffer); - GST_CLAPPER_GL_BASE_IMPORTER_LOCK (self); + GST_CLAPPER_GL_UPLOADER_LOCK (self); upload_buf = _upload_perform_locked (self, buffer); if (G_UNLIKELY (!upload_buf)) { GST_ERROR_OBJECT (self, "Could not perform upload on input buffer"); - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); + GST_CLAPPER_GL_UPLOADER_UNLOCK (self); return NULL; } @@ -198,7 +184,7 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer, self->has_pending_v_info = FALSE; } - GST_CLAPPER_GL_BASE_IMPORTER_UNLOCK (self); + GST_CLAPPER_GL_UPLOADER_UNLOCK (self); if (G_UNLIKELY (!color_buf)) { GST_ERROR_OBJECT (self, "Could not perform color conversion on input buffer"); @@ -206,7 +192,7 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer, } GST_LOG_OBJECT (self, "Color converted into %" GST_PTR_FORMAT, color_buf); - texture = gst_clapper_gl_base_importer_make_gl_texture (gl_bi, color_buf, &self->v_info); + texture = gst_clapper_gl_context_handler_make_gl_texture (self->gl_handler, color_buf, &self->v_info); gst_buffer_unref (color_buf); return texture; @@ -215,6 +201,8 @@ gst_clapper_gl_uploader_generate_texture (GstClapperImporter *importer, static void gst_clapper_gl_uploader_init (GstClapperGLUploader *self) { + g_mutex_init (&self->lock); + gst_video_info_init (&self->pending_v_info); gst_video_info_init (&self->v_info); } @@ -227,6 +215,10 @@ gst_clapper_gl_uploader_finalize (GObject *object) gst_clear_object (&self->upload); gst_clear_object (&self->color_convert); + gst_clear_object (&self->gl_handler); + + g_mutex_clear (&self->lock); + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } @@ -241,7 +233,6 @@ gst_clapper_gl_uploader_class_init (GstClapperGLUploaderClass *klass) gobject_class->finalize = gst_clapper_gl_uploader_finalize; - importer_class->prepare = gst_clapper_gl_uploader_prepare; importer_class->set_caps = gst_clapper_gl_uploader_set_caps; importer_class->create_pool = gst_clapper_gl_uploader_create_pool; importer_class->add_allocation_metas = gst_clapper_gl_uploader_add_allocation_metas; @@ -249,12 +240,26 @@ gst_clapper_gl_uploader_class_init (GstClapperGLUploaderClass *klass) } GstClapperImporter * -make_importer (void) +make_importer (GPtrArray *context_handlers) { - return g_object_new (GST_TYPE_CLAPPER_GL_UPLOADER, NULL); + GstClapperGLUploader *self; + GstClapperContextHandler *handler; + + handler = gst_clapper_context_handler_obtain_with_type (context_handlers, + GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER); + + if (G_UNLIKELY (!handler)) + return NULL; + + self = g_object_new (GST_TYPE_CLAPPER_GL_UPLOADER, NULL); + self->gl_handler = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST (handler); + self->upload = gst_gl_upload_new (self->gl_handler->gst_context); + self->color_convert = gst_gl_color_convert_new (self->gl_handler->gst_context); + + return GST_CLAPPER_IMPORTER_CAST (self); } -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 static gboolean _filter_glx_caps_cb (GstCapsFeatures *features, GstStructure *structure, gpointer user_data) @@ -277,7 +282,7 @@ _update_glx_caps_on_main (GstCaps *caps) if (GDK_IS_X11_DISPLAY (gdk_display)) { gboolean using_glx = TRUE; -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_EGL +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL using_glx = (gdk_x11_display_get_egl_display (gdk_display) == NULL); #endif @@ -292,11 +297,11 @@ _update_glx_caps_on_main (GstCaps *caps) #endif GstCaps * -make_caps (gboolean is_template, GstRank *rank, GStrv *context_types) +make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers) { GstCaps *caps = gst_gl_upload_get_input_template_caps (); -#if GST_CLAPPER_GL_BASE_IMPORTER_HAVE_X11_GLX +#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX if (!is_template && !(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) _update_glx_caps_on_main, caps))) gst_clear_caps (&caps); @@ -306,7 +311,9 @@ make_caps (gboolean is_template, GstRank *rank, GStrv *context_types) return NULL; *rank = GST_RANK_MARGINAL + 1; - *context_types = gst_clapper_gl_base_importer_make_gl_context_types (); + + if (!is_template && context_handlers) + gst_clapper_gl_context_handler_add_handler (context_handlers); return caps; } diff --git a/lib/gst/plugin/importers/gstclappergluploader.h b/lib/gst/plugin/importers/gstclappergluploader.h index aa76f9c2..b51a4916 100644 --- a/lib/gst/plugin/importers/gstclappergluploader.h +++ b/lib/gst/plugin/importers/gstclappergluploader.h @@ -19,18 +19,27 @@ #pragma once -#include "gstclapperglbaseimporter.h" +#include "gst/plugin/gstclapperimporter.h" +#include "gst/plugin/handlers/gl/gstclapperglcontexthandler.h" G_BEGIN_DECLS #define GST_TYPE_CLAPPER_GL_UPLOADER (gst_clapper_gl_uploader_get_type()) -G_DECLARE_FINAL_TYPE (GstClapperGLUploader, gst_clapper_gl_uploader, GST, CLAPPER_GL_UPLOADER, GstClapperGLBaseImporter) +G_DECLARE_FINAL_TYPE (GstClapperGLUploader, gst_clapper_gl_uploader, GST, CLAPPER_GL_UPLOADER, GstClapperImporter) #define GST_CLAPPER_GL_UPLOADER_CAST(obj) ((GstClapperGLUploader *)(obj)) +#define GST_CLAPPER_GL_UPLOADER_GET_LOCK(obj) (&GST_CLAPPER_GL_UPLOADER_CAST(obj)->lock) +#define GST_CLAPPER_GL_UPLOADER_LOCK(obj) g_mutex_lock (GST_CLAPPER_GL_UPLOADER_GET_LOCK(obj)) +#define GST_CLAPPER_GL_UPLOADER_UNLOCK(obj) g_mutex_unlock (GST_CLAPPER_GL_UPLOADER_GET_LOCK(obj)) + struct _GstClapperGLUploader { - GstClapperGLBaseImporter parent; + GstClapperImporter parent; + + GMutex lock; + + GstClapperGLContextHandler *gl_handler; GstGLUpload *upload; GstGLColorConvert *color_convert; diff --git a/lib/gst/plugin/importers/gstclapperrawimporter.c b/lib/gst/plugin/importers/gstclapperrawimporter.c index 00cd9b71..601ec986 100644 --- a/lib/gst/plugin/importers/gstclapperrawimporter.c +++ b/lib/gst/plugin/importers/gstclapperrawimporter.c @@ -47,13 +47,6 @@ gst_clapper_raw_importer_create_pool (GstClapperImporter *importer, GstStructure return pool; } -static void -gst_clapper_raw_importer_add_allocation_metas (GstClapperImporter *importer, GstQuery *query) -{ - gst_query_add_allocation_meta (query, GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, NULL); - gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); -} - static GdkTexture * gst_clapper_raw_importer_generate_texture (GstClapperImporter *importer, GstBuffer *buffer, GstVideoInfo *v_info) @@ -86,18 +79,17 @@ gst_clapper_raw_importer_class_init (GstClapperRawImporterClass *klass) "Clapper RAW Importer"); importer_class->create_pool = gst_clapper_raw_importer_create_pool; - importer_class->add_allocation_metas = gst_clapper_raw_importer_add_allocation_metas; importer_class->generate_texture = gst_clapper_raw_importer_generate_texture; } GstClapperImporter * -make_importer (void) +make_importer (GPtrArray *context_handlers) { return g_object_new (GST_TYPE_CLAPPER_RAW_IMPORTER, NULL); } GstCaps * -make_caps (gboolean is_template, GstRank *rank, GStrv *context_types) +make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers) { *rank = GST_RANK_MARGINAL; diff --git a/lib/gst/plugin/importers/meson.build b/lib/gst/plugin/importers/meson.build index d6121611..7cce1ef0 100644 --- a/lib/gst/plugin/importers/meson.build +++ b/lib/gst/plugin/importers/meson.build @@ -1,20 +1,9 @@ -gst_clapper_gl_base_importer_dep = dependency('', required: false) - all_importers = [ 'glimporter', 'gluploader', 'rawimporter', ] -build_glbase = ( - not get_option('glimporter').disabled() - or not get_option('gluploader').disabled() -) -gl_support_required = ( - get_option('glimporter').enabled() - or get_option('gluploader').enabled() -) - # We cannot build any importers without sink that they depend on if not gst_clapper_sink_dep.found() foreach imp : all_importers @@ -24,89 +13,16 @@ if not gst_clapper_sink_dep.found() endforeach endif -gst_plugin_gl_base_deps = [gst_clapper_sink_dep, gstgl_dep, gstglproto_dep] -have_gtk_gl_windowing = false - -if gst_gl_have_window_x11 and (gst_gl_have_platform_egl or gst_gl_have_platform_glx) - gtk_x11_dep = dependency('gtk4-x11', required: false) - if gtk_x11_dep.found() - gst_plugin_gl_base_deps += gtk_x11_dep - if gst_gl_have_platform_glx - gst_plugin_gl_base_deps += gstglx11_dep - endif - have_gtk_gl_windowing = true - endif -endif - -if gst_gl_have_window_wayland and gst_gl_have_platform_egl - gtk_wayland_dep = dependency('gtk4-wayland', required: false) - if gtk_wayland_dep.found() - gst_plugin_gl_base_deps += [gtk_wayland_dep, gstglwayland_dep] - have_gtk_gl_windowing = true - endif -endif - -if gst_gl_have_window_win32 and (gst_gl_have_platform_egl or gst_gl_have_platform_wgl) - gtk_win32_dep = dependency('gtk4-win32', required: false) - if gtk_win32_dep.found() - gst_plugin_gl_base_deps += gtk_win32_dep - have_gtk_gl_windowing = true - endif -endif - -if gst_gl_have_window_cocoa and gst_gl_have_platform_cgl - gtk_macos_dep = dependency('gtk4-macos', required: false) - if gtk_macos_dep.found() - gst_plugin_gl_base_deps += gtk_macos_dep - have_gtk_gl_windowing = true - endif -endif - -if not have_gtk_gl_windowing - if gl_support_required - error('GL-based importer was enabled, but support for current GL windowing is missing') - endif - build_glbase = false -endif - -if gst_gl_have_platform_egl - gst_plugin_gl_base_deps += gstglegl_dep -endif - -foreach dep : gst_plugin_gl_base_deps - if not dep.found() - if gl_support_required - error('GL-based importer was enabled, but required dependencies were not found') - endif - build_glbase = false - endif -endforeach - -if build_glbase - gst_clapper_gl_base_importer_dep = declare_dependency( - link_with: library('gstclapperglbaseimporter', - 'gstclapperglbaseimporter.c', - c_args: gst_clapper_plugin_args, - include_directories: configinc, - dependencies: gst_plugin_gl_base_deps, - version: libversion, - install: true, - ), - include_directories: configinc, - dependencies: gst_plugin_gl_base_deps, - ) -endif - build_glimporter = ( not get_option('glimporter').disabled() - and gst_clapper_gl_base_importer_dep.found() + and gst_clapper_gl_ch_dep.found() ) if build_glimporter library( 'gstclapperglimporter', 'gstclapperglimporter.c', - dependencies: gst_clapper_gl_base_importer_dep, + dependencies: gst_clapper_gl_ch_dep, include_directories: configinc, c_args: gst_clapper_plugin_args, install: true, @@ -116,14 +32,14 @@ endif build_gluploader = ( not get_option('gluploader').disabled() - and gst_clapper_gl_base_importer_dep.found() + and gst_clapper_gl_ch_dep.found() ) if build_gluploader library( 'gstclappergluploader', 'gstclappergluploader.c', - dependencies: gst_clapper_gl_base_importer_dep, + dependencies: gst_clapper_gl_ch_dep, include_directories: configinc, c_args: gst_clapper_plugin_args, install: true, diff --git a/lib/gst/plugin/meson.build b/lib/gst/plugin/meson.build index 48cc4b86..a8b581a4 100644 --- a/lib/gst/plugin/meson.build +++ b/lib/gst/plugin/meson.build @@ -61,4 +61,5 @@ if build_gst_plugin ) endif +subdir('handlers') subdir('importers') From 8ebf4e3b2fe15ca8422f4f20d630f99a4996e6c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Sun, 12 Jun 2022 21:11:06 +0200 Subject: [PATCH 3/3] plugin: gluploader: Check for formats actually supported Do not assume that HW can do every format that GLUpload/GLColorConvert can. Check what video formats GL context actually supports and advertise that, so a format that HW cannot do will never be picked up. --- .../plugin/importers/gstclappergluploader.c | 95 ++++++++++--------- 1 file changed, 52 insertions(+), 43 deletions(-) diff --git a/lib/gst/plugin/importers/gstclappergluploader.c b/lib/gst/plugin/importers/gstclappergluploader.c index b03e6f77..24fcc156 100644 --- a/lib/gst/plugin/importers/gstclappergluploader.c +++ b/lib/gst/plugin/importers/gstclappergluploader.c @@ -22,11 +22,6 @@ #endif #include "gstclappergluploader.h" -#include "gst/plugin/gstgtkutils.h" - -#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 -#include -#endif #define GST_CAT_DEFAULT gst_clapper_gl_uploader_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -259,61 +254,75 @@ make_importer (GPtrArray *context_handlers) return GST_CLAPPER_IMPORTER_CAST (self); } -#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11 -static gboolean -_filter_glx_caps_cb (GstCapsFeatures *features, - GstStructure *structure, gpointer user_data) +static GstCaps * +_make_actual_caps (GstClapperGLContextHandler *gl_handler) { - return !gst_caps_features_contains (features, "memory:DMABuf"); -} + GstGLUpload *upload; + GstCaps *gdk_sink_caps, *color_sink_caps, *upload_sink_caps, *actual; + guint i; -static gboolean -_update_glx_caps_on_main (GstCaps *caps) -{ - GdkDisplay *gdk_display; + /* Having "gst_context" means we also have all other contexts and + * display as they are used to create it, so no need to check */ + if (!gl_handler->gst_context) + return NULL; - if (!gtk_init_check ()) - return FALSE; + gdk_sink_caps = gst_clapper_gl_context_handler_make_gdk_gl_caps ( + GST_CAPS_FEATURE_MEMORY_GL_MEMORY, TRUE); - gdk_display = gdk_display_get_default (); - if (G_UNLIKELY (!gdk_display)) - return FALSE; + color_sink_caps = gst_gl_color_convert_transform_caps (gl_handler->gst_context, + GST_PAD_SRC, gdk_sink_caps, NULL); + gst_caps_unref (gdk_sink_caps); - if (GDK_IS_X11_DISPLAY (gdk_display)) { - gboolean using_glx = TRUE; + upload = gst_gl_upload_new (NULL); -#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_EGL - using_glx = (gdk_x11_display_get_egl_display (gdk_display) == NULL); -#endif + upload_sink_caps = gst_gl_upload_transform_caps (upload, gl_handler->gst_context, + GST_PAD_SRC, color_sink_caps, NULL); + gst_caps_unref (color_sink_caps); - if (using_glx) { - gst_caps_filter_and_map_in_place (caps, - (GstCapsFilterMapFunc) _filter_glx_caps_cb, NULL); - } + gst_object_unref (upload); + + /* Check for existence and remove duplicated structures, + * they may contain unsupported by our GL context formats */ + actual = gst_caps_new_empty (); + for (i = 0; i < gst_caps_get_size (upload_sink_caps); i++) { + GstCaps *tmp = gst_caps_copy_nth (upload_sink_caps, i); + + if (!gst_caps_can_intersect (actual, tmp)) + gst_caps_append (actual, tmp); + else + gst_caps_unref (tmp); } + gst_caps_unref (upload_sink_caps); - return TRUE; + if (G_UNLIKELY (gst_caps_is_empty (actual))) + gst_clear_caps (&actual); + + return actual; } -#endif GstCaps * make_caps (gboolean is_template, GstRank *rank, GPtrArray *context_handlers) { - GstCaps *caps = gst_gl_upload_get_input_template_caps (); + GstCaps *caps = NULL; -#if GST_CLAPPER_GL_CONTEXT_HANDLER_HAVE_X11_GLX - if (!is_template && !(! !gst_gtk_invoke_on_main ((GThreadFunc) (GCallback) - _update_glx_caps_on_main, caps))) - gst_clear_caps (&caps); -#endif + if (is_template) { + caps = gst_gl_upload_get_input_template_caps (); + } else if (context_handlers) { + GstClapperGLContextHandler *gl_handler; - if (G_UNLIKELY (!caps)) - return NULL; - - *rank = GST_RANK_MARGINAL + 1; - - if (!is_template && context_handlers) + /* Add GL context handler if not already present */ gst_clapper_gl_context_handler_add_handler (context_handlers); + if ((gl_handler = GST_CLAPPER_GL_CONTEXT_HANDLER_CAST ( + gst_clapper_context_handler_obtain_with_type (context_handlers, + GST_TYPE_CLAPPER_GL_CONTEXT_HANDLER)))) { + caps = _make_actual_caps (gl_handler); + gst_object_unref (gl_handler); + } + } + + if (caps) + *rank = GST_RANK_MARGINAL + 1; + return caps; }