From 3e624357553b6c30e4b9e23e3284666234e699c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Cerveau?= Date: Tue, 4 Jun 2024 18:49:37 +0200 Subject: [PATCH] vkh26xdec: register multiple elements Register the multiple devices available on the system in separate features in the registry for the vulkan decoders. Part-of: --- .../gst-plugins-bad/ext/vulkan/gstvulkan.c | 34 ++++- .../ext/vulkan/gstvulkanelement.c | 31 +++++ .../ext/vulkan/gstvulkanelements.h | 10 ++ .../gst-plugins-bad/ext/vulkan/vkh264dec.c | 118 +++++++++++++++--- .../gst-plugins-bad/ext/vulkan/vkh264dec.h | 8 +- .../gst-plugins-bad/ext/vulkan/vkh265dec.c | 117 ++++++++++++++--- .../gst-plugins-bad/ext/vulkan/vkh265dec.h | 8 +- 7 files changed, 281 insertions(+), 45 deletions(-) diff --git a/subprojects/gst-plugins-bad/ext/vulkan/gstvulkan.c b/subprojects/gst-plugins-bad/ext/vulkan/gstvulkan.c index 023dd30f55..0b2ff9b843 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/gstvulkan.c +++ b/subprojects/gst-plugins-bad/ext/vulkan/gstvulkan.c @@ -52,6 +52,22 @@ static gboolean plugin_init (GstPlugin * plugin) { gboolean ret = FALSE; + GstVulkanInstance *instance = gst_vulkan_instance_new (); + gboolean have_instance = gst_vulkan_instance_open (instance, NULL); + const gchar *env_vars[] = + { "VK_ICD_FILENAMES", "VK_DRIVER_FILES", "VK_ADD_DRIVER_FILES", NULL }; +#ifndef G_OS_WIN32 + const gchar *kernel_paths[] = { "/dev/dri", NULL }; + const gchar *kernel_names[] = { "renderD", NULL }; + + /* features get updated upon changes in /dev/dri/renderD* */ + gst_plugin_add_dependency (plugin, NULL, kernel_paths, kernel_names, + GST_PLUGIN_DEPENDENCY_FLAG_FILE_NAME_IS_PREFIX); + + /* features get updated upon changes on VK_ICD_FILENAMES envvar */ +#endif + gst_plugin_add_dependency (plugin, env_vars, NULL, NULL, + GST_PLUGIN_DEPENDENCY_FLAG_NONE); ret |= GST_DEVICE_PROVIDER_REGISTER (vulkandeviceprovider, plugin); @@ -71,11 +87,23 @@ plugin_init (GstPlugin * plugin) ret |= GST_ELEMENT_REGISTER (vulkanoverlaycompositor, plugin); #endif + if (have_instance && instance->n_physical_devices) { #if GST_VULKAN_HAVE_VIDEO_EXTENSIONS - GST_ELEMENT_REGISTER (vulkanh264dec, plugin); - GST_ELEMENT_REGISTER (vulkanh265dec, plugin); + for (gint i = 0; i < instance->n_physical_devices; i++) { + GstVulkanDevice *device = gst_vulkan_device_new_with_index (instance, i); + if (gst_vulkan_device_is_extension_enabled (device, + VK_KHR_VIDEO_DECODE_H264_EXTENSION_NAME)) { + ret |= gst_vulkan_h264_decoder_register (plugin, device, GST_RANK_NONE); + } + if (gst_vulkan_device_is_extension_enabled (device, + VK_KHR_VIDEO_DECODE_H265_EXTENSION_NAME)) { + ret |= gst_vulkan_h265_decoder_register (plugin, device, GST_RANK_NONE); + } + gst_object_unref (device); + } #endif - + } + gst_object_unref (instance); return ret; } diff --git a/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelement.c b/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelement.c index 72c6d68528..68f5e068cb 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelement.c +++ b/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelement.c @@ -31,6 +31,8 @@ #include "gstvulkanelements.h" +#include + #define GST_CAT_DEFAULT gst_vulkan_debug GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); @@ -44,3 +46,32 @@ vulkan_element_init (GstPlugin * plugin) g_once_init_leave (&res, TRUE); } } + +void +gst_vulkan_create_feature_name (GstVulkanDevice * device, + const gchar * type_name_default, const gchar * type_name_templ, + gchar ** type_name, const gchar * feature_name_default, + const gchar * feature_name_templ, gchar ** feature_name, + gchar ** desc, guint * rank) +{ + /* The first element to be registered should use a constant name, + * like vkh264enc, for any additional elements, we create unique + * names, using inserting the render device name. */ + if (device->physical_device->device_index == 0) { + *type_name = g_strdup (type_name_default); + *feature_name = g_strdup (feature_name_default); + *desc = g_strdup (device->physical_device->properties.deviceName); + return; + } + + *type_name = + g_strdup_printf (type_name_templ, device->physical_device->device_index); + *feature_name = + g_strdup_printf (feature_name_templ, + device->physical_device->device_index); + + *desc = g_strdup (device->physical_device->properties.deviceName); + + if (*rank > 0) + *rank -= 1; +} diff --git a/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelements.h b/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelements.h index 82a423862c..984ef898d0 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelements.h +++ b/subprojects/gst-plugins-bad/ext/vulkan/gstvulkanelements.h @@ -26,7 +26,17 @@ #endif #include +#include void vulkan_element_init (GstPlugin * plugin); +void gst_vulkan_create_feature_name (GstVulkanDevice * device, + const gchar * type_name_default, + const gchar * type_name_templ, + gchar ** type_name, + const gchar * feature_name_default, + const gchar * feature_name_templ, + gchar ** feature_name, + gchar ** desc, + guint * rank); #endif /* __GST_VULKAN_ELEMENTS_H__ */ diff --git a/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.c b/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.c index 10bf59f332..c55c60c029 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.c +++ b/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.c @@ -29,6 +29,24 @@ #include "gst/vulkan/gstvkdecoder-private.h" #include "gstvulkanelements.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vulkan_h264_decoder_debug); +#define GST_CAT_DEFAULT gst_vulkan_h264_decoder_debug + +#define GST_VULKAN_H264_DECODER(obj) ((GstVulkanH264Decoder *) obj) +#define GST_VULKAN_H264_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVulkanH264DecoderClass)) +#define GST_VULKAN_H264_DECODER_CLASS(klass) ((GstVulkanH264DecoderClass *) klass) + +static GstElementClass *parent_class = NULL; + +struct CData +{ + gchar *description; + gint device_index; +}; + +typedef struct _GstVulkanH264Decoder GstVulkanH264Decoder; +typedef struct _GstVulkanH264DecoderClass GstVulkanH264DecoderClass; typedef struct _GstVulkanH264Decoder GstVulkanH264Decoder; typedef struct _GstVulkanH264Picture GstVulkanH264Picture; typedef struct _SPS SPS; @@ -95,6 +113,13 @@ struct _GstVulkanH264Decoder PPS std_pps; }; +struct _GstVulkanH264DecoderClass +{ + GstH264DecoderClass parent; + + gint device_index; +}; + static GstStaticPadTemplate gst_vulkan_h264dec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/x-h264, " @@ -107,16 +132,16 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE, "NV12"))); -GST_DEBUG_CATEGORY (gst_debug_vulkan_h264_decoder); -#define GST_CAT_DEFAULT gst_debug_vulkan_h264_decoder - #define gst_vulkan_h264_decoder_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstVulkanH264Decoder, gst_vulkan_h264_decoder, - GST_TYPE_H264_DECODER, - GST_DEBUG_CATEGORY_INIT (gst_debug_vulkan_h264_decoder, - "vulkanh264dec", 0, "Vulkan H.264 Decoder")); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (vulkanh264dec, "vulkanh264dec", - GST_RANK_NONE, GST_TYPE_VULKAN_H264_DECODER, vulkan_element_init (plugin)); + +static gpointer +_register_debug_category (gpointer data) +{ + GST_DEBUG_CATEGORY_INIT (gst_vulkan_h264_decoder_debug, + "gst_vulkan_h264_decoder_debug", 0, "Vulkan H.264 decoder"); + + return NULL; +} static gboolean _find_queues (GstVulkanDevice * device, GstVulkanQueue * queue, gpointer data) @@ -147,6 +172,7 @@ static gboolean gst_vulkan_h264_decoder_open (GstVideoDecoder * decoder) { GstVulkanH264Decoder *self = GST_VULKAN_H264_DECODER (decoder); + GstVulkanH264DecoderClass *klass = GST_VULKAN_H264_DECODER_GET_CLASS (self); if (!gst_vulkan_ensure_element_data (GST_ELEMENT (decoder), NULL, &self->instance)) { @@ -156,7 +182,7 @@ gst_vulkan_h264_decoder_open (GstVideoDecoder * decoder) } if (!gst_vulkan_ensure_element_device (GST_ELEMENT (decoder), self->instance, - &self->device, 0)) { + &self->device, klass->device_index)) { return FALSE; } @@ -1315,22 +1341,40 @@ gst_vulkan_h264_decoder_output_picture (GstH264Decoder * decoder, } static void -gst_vulkan_h264_decoder_init (GstVulkanH264Decoder * self) +gst_vulkan_h264_decoder_init (GTypeInstance * instance, gpointer g_class) { gst_vulkan_buffer_memory_init_once (); } static void -gst_vulkan_h264_decoder_class_init (GstVulkanH264DecoderClass * klass) +gst_vulkan_h264_decoder_class_init (gpointer g_klass, gpointer class_data) { - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass); - GstH264DecoderClass *h264decoder_class = GST_H264_DECODER_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass); + GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_klass); + GstH264DecoderClass *h264decoder_class = GST_H264_DECODER_CLASS (g_klass); + GstVulkanH264DecoderClass *vk_h264_class = + GST_VULKAN_H264_DECODER_CLASS (g_klass); + struct CData *cdata = class_data; + gchar *long_name; + const gchar *name, *desc; - gst_element_class_set_metadata (element_class, "Vulkan H.264 decoder", - "Codec/Decoder/Video/Hardware", "A H.264 video decoder based on Vulkan", + name = "Vulkan H.264 decoder"; + desc = "A H.264 video decoder based on Vulkan"; + + if (cdata->description) + long_name = g_strdup_printf ("%s on %s", name, cdata->description); + else + long_name = g_strdup (name); + + vk_h264_class->device_index = cdata->device_index; + + gst_element_class_set_metadata (element_class, long_name, + "Codec/Decoder/Video/Hardware", desc, "Víctor Jáquez "); + parent_class = g_type_class_peek_parent (g_klass); + + gst_element_class_add_static_pad_template (element_class, &gst_vulkan_h264dec_sink_template); @@ -1367,3 +1411,43 @@ gst_vulkan_h264_decoder_class_init (GstVulkanH264DecoderClass * klass) h264decoder_class->output_picture = GST_DEBUG_FUNCPTR (gst_vulkan_h264_decoder_output_picture); } + +gboolean +gst_vulkan_h264_decoder_register (GstPlugin * plugin, GstVulkanDevice * device, + guint rank) +{ + static GOnce debug_once = G_ONCE_INIT; + GType type; + GTypeInfo type_info = { + .class_size = sizeof (GstVulkanH264DecoderClass), + .class_init = gst_vulkan_h264_decoder_class_init, + .instance_size = sizeof (GstVulkanH264Decoder), + .instance_init = gst_vulkan_h264_decoder_init, + }; + struct CData *cdata; + gboolean ret; + gchar *type_name, *feature_name; + + cdata = g_new (struct CData, 1); + cdata->description = NULL; + cdata->device_index = device->physical_device->device_index; + + g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE); + + gst_vulkan_create_feature_name (device, "GstVulkanH264Decoder", + "GstVulkanH264Device%dDecoder", &type_name, "vulkanh264dec", + "vulkanh264device%ddec", &feature_name, &cdata->description, &rank); + + type_info.class_data = cdata; + + g_once (&debug_once, _register_debug_category, NULL); + type = g_type_register_static (GST_TYPE_H264_DECODER, + type_name, &type_info, 0); + + ret = gst_element_register (plugin, feature_name, rank, type); + + g_free (type_name); + g_free (feature_name); + + return ret; +} diff --git a/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.h b/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.h index 35481c1175..a25160aaf6 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.h +++ b/subprojects/gst-plugins-bad/ext/vulkan/vkh264dec.h @@ -21,11 +21,11 @@ #include +#include + G_BEGIN_DECLS -#define GST_TYPE_VULKAN_H264_DECODER (gst_vulkan_h264_decoder_get_type()) -G_DECLARE_FINAL_TYPE (GstVulkanH264Decoder, gst_vulkan_h264_decoder, GST, VULKAN_H264_DECODER, GstH264Decoder) - -GST_ELEMENT_REGISTER_DECLARE (vulkanh264dec); +gboolean +gst_vulkan_h264_decoder_register (GstPlugin * plugin, GstVulkanDevice *device, guint rank); G_END_DECLS diff --git a/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.c b/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.c index 67c573edea..c57cdf3c7e 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.c +++ b/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.c @@ -29,6 +29,23 @@ #include "gstvulkanelements.h" +GST_DEBUG_CATEGORY_STATIC (gst_vulkan_h265_decoder_debug); +#define GST_CAT_DEFAULT gst_vulkan_h265_decoder_debug + +#define GST_VULKAN_H265_DECODER(obj) ((GstVulkanH265Decoder *) obj) +#define GST_VULKAN_H265_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), G_TYPE_FROM_INSTANCE (obj), GstVulkanH265DecoderClass)) +#define GST_VULKAN_H265_DECODER_CLASS(klass) ((GstVulkanH265DecoderClass *) klass) + +static GstElementClass *parent_class = NULL; + +struct CData +{ + gchar *description; + gint device_index; +}; + +typedef struct _GstVulkanH265Decoder GstVulkanH265Decoder; +typedef struct _GstVulkanH265DecoderClass GstVulkanH265DecoderClass; typedef struct _GstVulkanH265Decoder GstVulkanH265Decoder; typedef struct _GstVulkanH265Picture GstVulkanH265Picture; typedef struct _VPS VPS; @@ -117,6 +134,14 @@ struct _GstVulkanH265Decoder PPS std_pps; }; + +struct _GstVulkanH265DecoderClass +{ + GstH265DecoderClass parent; + + gint device_index; +}; + static GstStaticPadTemplate gst_vulkan_h265dec_sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/x-h265, " @@ -129,16 +154,16 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_VULKAN_IMAGE, "NV12"))); -GST_DEBUG_CATEGORY (gst_debug_vulkan_h265_decoder); -#define GST_CAT_DEFAULT gst_debug_vulkan_h265_decoder - #define gst_vulkan_h265_decoder_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstVulkanH265Decoder, gst_vulkan_h265_decoder, - GST_TYPE_H265_DECODER, - GST_DEBUG_CATEGORY_INIT (gst_debug_vulkan_h265_decoder, - "vulkanh265dec", 0, "Vulkan H.265 Decoder")); -GST_ELEMENT_REGISTER_DEFINE_WITH_CODE (vulkanh265dec, "vulkanh265dec", - GST_RANK_NONE, GST_TYPE_VULKAN_H265_DECODER, vulkan_element_init (plugin)); + +static gpointer +_register_debug_category (gpointer data) +{ + GST_DEBUG_CATEGORY_INIT (gst_vulkan_h265_decoder_debug, + "gst_vulkan_h265_decoder_debug", 0, "Vulkan H.265 decoder"); + + return NULL; +} static void gst_vulkan_h265_decoder_set_context (GstElement * element, GstContext * context) @@ -227,6 +252,7 @@ static gboolean gst_vulkan_h265_decoder_open (GstVideoDecoder * decoder) { GstVulkanH265Decoder *self = GST_VULKAN_H265_DECODER (decoder); + GstVulkanH265DecoderClass *klass = GST_VULKAN_H265_DECODER_GET_CLASS (self); if (!gst_vulkan_ensure_element_data (GST_ELEMENT (decoder), NULL, &self->instance)) { @@ -236,7 +262,7 @@ gst_vulkan_h265_decoder_open (GstVideoDecoder * decoder) } if (!gst_vulkan_ensure_element_device (GST_ELEMENT (decoder), self->instance, - &self->device, 0)) { + &self->device, klass->device_index)) { return FALSE; } @@ -1634,22 +1660,39 @@ gst_vulkan_h265_decoder_output_picture (GstH265Decoder * decoder, } static void -gst_vulkan_h265_decoder_init (GstVulkanH265Decoder * self) +gst_vulkan_h265_decoder_init (GTypeInstance * instance, gpointer g_class) { gst_vulkan_buffer_memory_init_once (); } static void -gst_vulkan_h265_decoder_class_init (GstVulkanH265DecoderClass * klass) +gst_vulkan_h265_decoder_class_init (gpointer g_klass, gpointer class_data) { - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (klass); - GstH265DecoderClass *h265decoder_class = GST_H265_DECODER_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (g_klass); + GstVideoDecoderClass *decoder_class = GST_VIDEO_DECODER_CLASS (g_klass); + GstH265DecoderClass *h265decoder_class = GST_H265_DECODER_CLASS (g_klass); + GstVulkanH265DecoderClass *vk_h265_class = + GST_VULKAN_H265_DECODER_CLASS (g_klass); + struct CData *cdata = class_data; + gchar *long_name; + const gchar *name, *desc; - gst_element_class_set_metadata (element_class, "Vulkan H.265 decoder", - "Codec/Decoder/Video/Hardware", "A H.265 video decoder based on Vulkan", + name = "Vulkan H.265 decoder"; + desc = "A H.265 video decoder based on Vulkan"; + + if (cdata->description) + long_name = g_strdup_printf ("%s on %s", name, cdata->description); + else + long_name = g_strdup (name); + + vk_h265_class->device_index = cdata->device_index; + + gst_element_class_set_metadata (element_class, long_name, + "Codec/Decoder/Video/Hardware", desc, "Víctor Jáquez "); + parent_class = g_type_class_peek_parent (g_klass); + gst_element_class_add_static_pad_template (element_class, &gst_vulkan_h265dec_sink_template); @@ -1684,3 +1727,43 @@ gst_vulkan_h265_decoder_class_init (GstVulkanH265DecoderClass * klass) h265decoder_class->output_picture = GST_DEBUG_FUNCPTR (gst_vulkan_h265_decoder_output_picture); } + +gboolean +gst_vulkan_h265_decoder_register (GstPlugin * plugin, GstVulkanDevice * device, + guint rank) +{ + static GOnce debug_once = G_ONCE_INIT; + GType type; + GTypeInfo type_info = { + .class_size = sizeof (GstVulkanH265DecoderClass), + .class_init = gst_vulkan_h265_decoder_class_init, + .instance_size = sizeof (GstVulkanH265Decoder), + .instance_init = gst_vulkan_h265_decoder_init, + }; + struct CData *cdata; + gboolean ret; + gchar *type_name, *feature_name; + + cdata = g_new (struct CData, 1); + cdata->description = NULL; + cdata->device_index = device->physical_device->device_index; + + g_return_val_if_fail (GST_IS_PLUGIN (plugin), FALSE); + + gst_vulkan_create_feature_name (device, "GstVulkanH265Decoder", + "GstVulkanH265Device%dDecoder", &type_name, "vulkanh265dec", + "vulkanh265device%ddec", &feature_name, &cdata->description, &rank); + + type_info.class_data = cdata; + + g_once (&debug_once, _register_debug_category, NULL); + type = g_type_register_static (GST_TYPE_H265_DECODER, + type_name, &type_info, 0); + + ret = gst_element_register (plugin, feature_name, rank, type); + + g_free (type_name); + g_free (feature_name); + + return ret; +} diff --git a/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.h b/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.h index 545234ad4b..e368de8411 100644 --- a/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.h +++ b/subprojects/gst-plugins-bad/ext/vulkan/vkh265dec.h @@ -21,11 +21,11 @@ #include +#include + G_BEGIN_DECLS -#define GST_TYPE_VULKAN_H265_DECODER (gst_vulkan_h265_decoder_get_type()) -G_DECLARE_FINAL_TYPE (GstVulkanH265Decoder, gst_vulkan_h265_decoder, GST, VULKAN_H265_DECODER, GstH265Decoder) - -GST_ELEMENT_REGISTER_DECLARE (vulkanh265dec); +gboolean +gst_vulkan_h265_decoder_register (GstPlugin * plugin, GstVulkanDevice *device, guint rank); G_END_DECLS