From 5874db45ea509b7e5333e462f6e32992aaa5c170 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Dzi=C4=99giel?= Date: Tue, 24 Aug 2021 13:10:25 +0200 Subject: [PATCH] api: Introduce custom gstreamer init function Initializes GStreamer library and tweaks some of its defaults to our liking. This also allows usage of GstClapper API alone without importing GStreamer on the implementation side. It changes preferred hardware acceleration order (depending on plugins versions) into: v4l2sl -> nv -> va -> vaapi -> v4l2 --- lib/gst/clapper/gstclapper.c | 97 +++++++++++++++++++++++++++++++++++- lib/gst/clapper/gstclapper.h | 3 ++ src/main.js | 4 +- 3 files changed, 101 insertions(+), 3 deletions(-) diff --git a/lib/gst/clapper/gstclapper.c b/lib/gst/clapper/gstclapper.c index a491fa2b..7505da37 100644 --- a/lib/gst/clapper/gstclapper.c +++ b/lib/gst/clapper/gstclapper.c @@ -65,6 +65,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_clapper_debug); #define DEFAULT_SUBTITLE_VIDEO_OFFSET 0 #define DEFAULT_SEEK_MODE GST_CLAPPER_SEEK_MODE_DEFAULT +static gboolean gst_clapper_gstreamer_prepared = FALSE; + /** * gst_clapper_error_quark: */ @@ -270,7 +272,6 @@ static void remove_seek_source (GstClapper * self); static void gst_clapper_init (GstClapper * self) { - GST_DEBUG_CATEGORY_INIT (gst_clapper_debug, "Clapper", 0, "GstClapper"); GST_TRACE_OBJECT (self, "Initializing"); self = gst_clapper_get_instance_private (self); @@ -302,6 +303,8 @@ gst_clapper_class_init (GstClapperClass * klass) gobject_class->finalize = gst_clapper_finalize; gobject_class->constructed = gst_clapper_constructed; + GST_DEBUG_CATEGORY_INIT (gst_clapper_debug, "Clapper", 0, "GstClapper"); + param_specs[PROP_VIDEO_RENDERER] = g_param_spec_object ("video-renderer", "Video Renderer", "Video renderer to use for rendering videos", @@ -3237,6 +3240,98 @@ gst_clapper_main (gpointer data) return NULL; } +static gboolean +gst_clapper_set_feature_rank_versioned (const gchar * name, guint rank, + guint min_major, guint min_minor, guint min_micro) +{ + GstRegistry *registry = gst_registry_get (); + GstPluginFeature *feature = gst_registry_lookup_feature (registry, name); + gboolean res = FALSE; + + if (!feature) { + GST_DEBUG ("Cannot change rank of unavailable feature: %s", name); + goto out; + } + if (gst_plugin_feature_check_version (feature, min_major, min_minor, min_micro)) { + guint old_rank = gst_plugin_feature_get_rank (feature); + gst_plugin_feature_set_rank (feature, rank); + res = TRUE; + GST_DEBUG ("Changed rank: %i -> %i for %s", old_rank, rank, name); + } else { + GST_DEBUG ("Feature %s is at older version then required", name); + } + +out: + gst_object_unref (feature); + return res; +} + +static gboolean +gst_clapper_set_feature_rank (const gchar * name, guint rank) +{ + return gst_clapper_set_feature_rank_versioned (name, rank, 0, 0, 0); +} + +static gboolean +gst_clapper_has_plugin_with_features (const gchar * name) +{ + GstRegistry *registry = gst_registry_get (); + GList *features = gst_registry_get_feature_list_by_plugin (registry, name); + + gboolean ret = g_list_length (features) > 0; + + gst_plugin_feature_list_free (features); + return ret; +} + +static void +gst_clapper_prepare_gstreamer (void) +{ + GstRegistry *registry = gst_registry_get (); + const guint rank = GST_RANK_PRIMARY + 24; + + GST_DEBUG ("Preparing GStreamer plugins"); + + if (gst_clapper_has_plugin_with_features ("va")) { + gst_clapper_set_feature_rank_versioned ("vah264dec", rank, 1, 19, 1); + gst_clapper_set_feature_rank_versioned ("vampeg2dec", rank, 1, 19, 1); + } + if (gst_clapper_has_plugin_with_features ("nvcodec")) { + gst_clapper_set_feature_rank ("nvh264dec", rank + 4); + gst_clapper_set_feature_rank ("nvh265dec", rank + 4); + } + if (gst_clapper_has_plugin_with_features ("v4l2codecs")) { + if (!gst_clapper_set_feature_rank_versioned ("v4l2slh264dec", rank + 10, 1, 19, 1)) + gst_clapper_set_feature_rank ("v4l2slh264dec", GST_RANK_NONE); + if (!gst_clapper_set_feature_rank_versioned ("v4l2slvp8dec", rank + 10, 1, 19, 2)) + gst_clapper_set_feature_rank ("v4l2slvp8dec", GST_RANK_NONE); + } + + gst_clapper_gstreamer_prepared = TRUE; + GST_DEBUG ("GStreamer plugins prepared"); +} + +/** + * gst_clapper_gst_init: + * @argc: (inout) (allow-none): pointer to application's argc + * @argv: (inout) (array length=argc) (allow-none): pointer to application's argv + * + * Automatically initializes GStreamer library if this was not done by the user yet + * and tweaks some of its defaults to our liking. It is recommended to use this + * function instead of plain gst_init(). + * + * This also allows usage of GstClapper API alone without importing GStreamer + * on the implementation side. + */ +void +gst_clapper_gst_init (int * argc, char ** argv[]) +{ + if (!gst_is_initialized ()) + gst_init (argc, argv); + if (!gst_clapper_gstreamer_prepared) + gst_clapper_prepare_gstreamer (); +} + /** * gst_clapper_new: * @video_renderer: (transfer full) (allow-none): GstClapperVideoRenderer to use diff --git a/lib/gst/clapper/gstclapper.h b/lib/gst/clapper/gstclapper.h index 35895109..d93cdf31 100644 --- a/lib/gst/clapper/gstclapper.h +++ b/lib/gst/clapper/gstclapper.h @@ -153,6 +153,9 @@ G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstClapper, gst_object_unref) GST_CLAPPER_API GType gst_clapper_get_type (void); +GST_CLAPPER_API +void gst_clapper_gst_init (int *argc, char **argv[]); + GST_CLAPPER_API GstClapper * gst_clapper_new (GstClapperVideoRenderer *video_renderer, GstClapperSignalDispatcher *signal_dispatcher, GstClapperMpris *mpris); diff --git a/src/main.js b/src/main.js index f933a725..2535bd5a 100644 --- a/src/main.js +++ b/src/main.js @@ -2,9 +2,9 @@ imports.gi.versions.Gdk = '4.0'; imports.gi.versions.Gtk = '4.0'; imports.gi.versions.Soup = '2.4'; -const { Gst, Gtk, Adw } = imports.gi; +const { GstClapper, Gtk, Adw } = imports.gi; -Gst.init(null); +GstClapper.Clapper.gst_init(null); Gtk.init(); Adw.init();