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')