diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstlcevcmeta.c b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstlcevcmeta.c new file mode 100644 index 0000000000..561f927c2a --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstlcevcmeta.c @@ -0,0 +1,230 @@ +/* GStreamer LCEVC meta + * Copyright (C) <2024> V-Nova International Limited + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstlcevcmeta.h" + +/** + * SECTION:gstlcevcmeta + * @title: GstMeta for LCEVC + * @short_description: LCEVC related GstMeta + * + */ + +#define GST_CAT_DEFAULT lcevcmeta_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT); + +static gboolean +gst_lcevc_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer) +{ + GstLcevcMeta *emeta = (GstLcevcMeta *) meta; + + emeta->id = 0; + emeta->enhancement_data = NULL; + + return TRUE; +} + +static void +gst_lcevc_meta_free (GstMeta * meta, GstBuffer * buffer) +{ + GstLcevcMeta *emeta = (GstLcevcMeta *) meta; + + g_clear_pointer (&emeta->enhancement_data, gst_buffer_unref); +} + +static gboolean +gst_lcevc_meta_transform (GstBuffer * dest, GstMeta * meta, + GstBuffer * buffer, GQuark type, gpointer data) +{ + GstLcevcMeta *dmeta, *smeta; + + smeta = (GstLcevcMeta *) meta; + + if (GST_META_TRANSFORM_IS_COPY (type)) { + GstMetaTransformCopy *copy = data; + + if (!copy->region) { + /* only copy if the complete data is copied as well */ + dmeta = (GstLcevcMeta *) gst_buffer_add_meta (dest, + GST_LCEVC_META_INFO, NULL); + + if (!dmeta) + return FALSE; + + GST_TRACE ("copying lcevc metadata"); + dmeta->id = smeta->id; + + g_clear_pointer (&dmeta->enhancement_data, gst_buffer_unref); + dmeta->enhancement_data = gst_buffer_copy (smeta->enhancement_data); + } + } else { + /* return FALSE, if transform type is not supported */ + return FALSE; + } + return TRUE; +} + + +/** + * gst_lcevc_meta_api_get_type: + * + * Gets the #GType of the LCEVC meta API. + * + * Returns: the #GType of the LCEVC meta API. + * + * Since: 1.26 + */ +GType +gst_lcevc_meta_api_get_type (void) +{ + static GType type = 0; + static const gchar *tags[] = { "video", NULL }; + + if (g_once_init_enter (&type)) { + GType _type = gst_meta_api_type_register ("GstLcevcMetaAPI", tags); + g_once_init_leave (&type, _type); + } + return type; +} + +/** + * gst_lcevc_meta_get_info: + * + * Gets the #GstMetaInfo of the LCEVC meta. + * + * Returns: (transfer none) : the #GstLcevcMeta of the LCEVC meta. + * + * Since: 1.26 + */ +const GstMetaInfo * +gst_lcevc_meta_get_info (void) +{ + static const GstMetaInfo *lcevc_meta_info = NULL; + + if (g_once_init_enter ((GstMetaInfo **) & lcevc_meta_info)) { + GST_DEBUG_CATEGORY_INIT (lcevcmeta_debug, "lcevcmeta", 0, "LCEVC Metadata"); + + const GstMetaInfo *meta = gst_meta_register (GST_LCEVC_META_API_TYPE, + "GstLcevcMeta", + sizeof (GstLcevcMeta), + (GstMetaInitFunction) gst_lcevc_meta_init, + (GstMetaFreeFunction) gst_lcevc_meta_free, + gst_lcevc_meta_transform); + g_once_init_leave ((GstMetaInfo **) & lcevc_meta_info, + (GstMetaInfo *) meta); + } + return lcevc_meta_info; +} + +/** + * gst_buffer_get_lcevc_meta: + * @buffer: a #GstBuffer + * + * Find the #GstLcevcMeta on @buffer with the lowest @id. + * + * Buffers can contain multiple #GstLcevcMeta metadata items when dealing with + * multiview buffers. + * + * Returns: (transfer none) (nullable): the #GstLcevcMeta with lowest id (usually 0) or %NULL when there + * is no such metadata on @buffer. + * + * Since: 1.26 + */ +GstLcevcMeta * +gst_buffer_get_lcevc_meta (GstBuffer * buffer) +{ + gpointer state = NULL; + GstLcevcMeta *out = NULL; + GstMeta *meta; + const GstMetaInfo *info = GST_LCEVC_META_INFO; + + while ((meta = gst_buffer_iterate_meta (buffer, &state))) { + if (meta->info->api == info->api) { + GstLcevcMeta *vmeta = (GstLcevcMeta *) meta; + if (vmeta->id == 0) + return vmeta; /* Early out for id 0 */ + if (out == NULL || vmeta->id < out->id) + out = vmeta; + } + } + return out; +} + +/** + * gst_buffer_get_lcevc_meta_id: + * @buffer: a #GstBuffer + * @id: a metadata id + * + * Find the #GstLcevcMeta on @buffer with the given @id. + * + * Buffers can contain multiple #GstLcevcMeta metadata items when dealing with + * multiview buffers. + * + * Returns: (transfer none) (nullable): the #GstLcevcMeta with @id or %NULL when there is no such metadata + * on @buffer. + * + * Since: 1.26 + */ +GstLcevcMeta * +gst_buffer_get_lcevc_meta_id (GstBuffer * buffer, gint id) +{ + gpointer state = NULL; + GstMeta *meta; + const GstMetaInfo *info = GST_LCEVC_META_INFO; + + while ((meta = gst_buffer_iterate_meta (buffer, &state))) { + if (meta->info->api == info->api) { + GstLcevcMeta *vmeta = (GstLcevcMeta *) meta; + if (vmeta->id == id) + return vmeta; + } + } + return NULL; +} + +/** + * gst_buffer_add_lcevc_meta: + * @buffer: a #GstBuffer + * @enhancement_data: (transfer none): the parsed LCEVC enhancement data + * + * Attaches GstLcevcMeta metadata to @buffer. + * + * Returns: (transfer none): the #GstLcevcMeta on @buffer. + * + * Since: 1.26 + */ +GstLcevcMeta * +gst_buffer_add_lcevc_meta (GstBuffer * buffer, GstBuffer * enhancement_data) +{ + GstLcevcMeta *meta; + + meta = (GstLcevcMeta *) gst_buffer_add_meta (buffer, GST_LCEVC_META_INFO, + NULL); + if (!meta) + return NULL; + + meta->id = 0; + g_clear_pointer (&meta->enhancement_data, gst_buffer_unref); + meta->enhancement_data = gst_buffer_ref (enhancement_data); + + return meta; +} diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstlcevcmeta.h b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstlcevcmeta.h new file mode 100644 index 0000000000..f7ff6eee55 --- /dev/null +++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/gstlcevcmeta.h @@ -0,0 +1,69 @@ +/* GStreamer LCEVC meta + * Copyright (C) <2024> V-Nova International Limited + * + * 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. + */ + +#ifndef __GST_LCEVC_META_H__ +#define __GST_LCEVC_META_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_LCEVC_META_API_TYPE (gst_lcevc_meta_api_get_type()) +#define GST_LCEVC_META_INFO (gst_lcevc_meta_get_info()) +typedef struct _GstLcevcMeta GstLcevcMeta; + +#define GST_CAPS_FEATURE_META_GST_LCEVC_META "meta:GstLcevcMeta" + +/** + * GstLcevcMeta: + * @meta: parent #GstMeta + * @id: the id of the LCEVC meta + * @enhancement_data: the parsed LCEVC enhancement data + * + * LCEVC data for LCEVC codecs + * + * Since: 1.26 + */ +struct _GstLcevcMeta { + GstMeta meta; + + gint id; + GstBuffer *enhancement_data; +}; + +GST_CODEC_PARSERS_API +GType gst_lcevc_meta_api_get_type (void); + +GST_CODEC_PARSERS_API +const GstMetaInfo * gst_lcevc_meta_get_info (void); + +GST_CODEC_PARSERS_API +GstLcevcMeta * gst_buffer_get_lcevc_meta (GstBuffer *buffer); + +GST_CODEC_PARSERS_API +GstLcevcMeta * gst_buffer_get_lcevc_meta_id (GstBuffer *buffer, gint id); + +GST_CODEC_PARSERS_API +GstLcevcMeta * gst_buffer_add_lcevc_meta (GstBuffer *buffer, + GstBuffer *enhancement_data); + +G_END_DECLS + +#endif /* __GST_VIDEO_META_H__ */ diff --git a/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/meson.build b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/meson.build index 76bae6ec46..82e9855a50 100644 --- a/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/meson.build +++ b/subprojects/gst-plugins-bad/gst-libs/gst/codecparsers/meson.build @@ -21,6 +21,7 @@ codecparser_sources = files([ 'gstav1bitwriter.c', 'gstvp9bitwriter.c', 'gstjpegbitwriter.c', + 'gstlcevcmeta.c', ]) codecparser_headers = [ 'codecparsers-prelude.h', @@ -36,6 +37,7 @@ codecparser_headers = [ 'gstmpegvideometa.h', 'gstvp9parser.h', 'gstav1parser.h', + 'gstlcevcmeta.h', ] install_headers(codecparser_headers, subdir : 'gstreamer-1.0/gst/codecparsers')