vkh26xdec: register multiple elements

Register the multiple devices available on the system in
separate features in the registry for the vulkan decoders.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7011>
This commit is contained in:
Stéphane Cerveau 2024-06-04 18:49:37 +02:00 committed by GStreamer Marge Bot
parent 7fb19b37d8
commit 3e62435755
7 changed files with 281 additions and 45 deletions

View file

@ -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;
}

View file

@ -31,6 +31,8 @@
#include "gstvulkanelements.h"
#include <gst/vulkan/vulkan.h>
#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;
}

View file

@ -26,7 +26,17 @@
#endif
#include <gst/gst.h>
#include <gst/vulkan/vulkan.h>
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__ */

View file

@ -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 <vjaquez@igalia.com>");
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;
}

View file

@ -21,11 +21,11 @@
#include <gst/codecs/gsth264decoder.h>
#include <gst/vulkan/vulkan.h>
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

View file

@ -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 <vjaquez@igalia.com>");
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;
}

View file

@ -21,11 +21,11 @@
#include <gst/codecs/gsth265decoder.h>
#include <gst/vulkan/vulkan.h>
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