/* GStreamer * Copyright (C) 2023 Collabora Ltd * * gstanalyticsclassificationmtd.c * * 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 "gstanalyticsclassificationmtd.h" /** * SECTION:gstanalyticsclassificationtd * @title: GstAnalyticsClsMtd * @short_description: An analytics metadata for classification inside a #GstAnalyticsRelationMeta * @symbols: * - GstAnalyticsClsMtd * @see_also: #GstAnalyticsMtd, #GstAnalyticsRelationMeta * * This type of metadata holds classification, it is generally used in * relationship with another metadata type to enhance its content. For example, * it can enhance the classifcation of an object detection held by the * #GstAnalyticsODMtd metadata type. * * Since: 1.24 */ static const GstAnalyticsMtdImpl cls_impl = { "classification", NULL }; typedef struct _GstAnalyticsClsConfLvlAndClass GstAnalyticsClsConfLvlAndClass; typedef struct _GstAnalyticsClsMtdData GstAnalyticsClsMtdData; struct _GstAnalyticsClsConfLvlAndClass { GQuark class; gfloat confidence_levels; }; /* * GstAnalyticsClsMtd: * @length: classes and confidence levels count * @class_quarks: (array length=length): Array of quark representing a class * @confidence_levels: (array length=length): Array of confidence levels for * each class in @class_quarks. * * Information on results of a classification of buffer content. */ struct _GstAnalyticsClsMtdData { gsize length; GstAnalyticsClsConfLvlAndClass confidence_levels_and_classes[]; // Must be last }; /** * gst_analytics_cls_mtd_get_mtd_type: * * Get an id identifying #GstAnalyticsMtd type. * * Returns: opaque id of #GstAnalyticsMtd type * * Since: 1.24 */ GstAnalyticsMtdType gst_analytics_cls_mtd_get_mtd_type (void) { return (GstAnalyticsMtdType) & cls_impl; } /** * gst_analytics_cls_mtd_get_level: * @handle: instance handle * @index: Object class index * * Get confidence level for class at @index * Returns: confidence level for @index, <0.0 if the call failed. * * Since: 1.24 */ gfloat gst_analytics_cls_mtd_get_level (const GstAnalyticsClsMtd * handle, gsize index) { g_return_val_if_fail (handle, -1.0); g_return_val_if_fail (handle->meta != NULL, -1.0); GstAnalyticsClsMtdData *cls_mtd_data; cls_mtd_data = gst_analytics_relation_meta_get_mtd_data (handle->meta, handle->id); g_return_val_if_fail (cls_mtd_data != NULL, -1.0); g_return_val_if_fail (cls_mtd_data->length > index, -1.0); return cls_mtd_data->confidence_levels_and_classes[index].confidence_levels; } /** * gst_analytics_cls_mtd_get_index_by_quark: * @handle: Instance handle * @quark: Quark of the class * Get index of class represented by @quark * Returns: index of the class associated with @quarks ( and label) or * a negative value on failure. * * Since: 1.24 */ gint gst_analytics_cls_mtd_get_index_by_quark (const GstAnalyticsClsMtd * handle, GQuark quark) { g_return_val_if_fail (handle, -1); GstAnalyticsClsMtdData *cls_mtd_data; cls_mtd_data = gst_analytics_relation_meta_get_mtd_data (handle->meta, handle->id); g_return_val_if_fail (cls_mtd_data != NULL, -1); for (gint i = 0; i < cls_mtd_data->length; i++) { if (quark == cls_mtd_data->confidence_levels_and_classes[i].class) { return i; } } return -1; } /** * gst_analytics_cls_mtd_get_length: * @handle: Instance handle * Get number of classes * Returns: Number of classes in this classification instance * * Since: 1.24 */ gsize gst_analytics_cls_mtd_get_length (const GstAnalyticsClsMtd * handle) { GstAnalyticsClsMtdData *cls_mtd_data; cls_mtd_data = gst_analytics_relation_meta_get_mtd_data (handle->meta, handle->id); g_return_val_if_fail (cls_mtd_data != NULL, 0); return cls_mtd_data->length; } /** * gst_analytics_cls_mtd_get_quark: * @handle: Instance handle * @index: index of the class * Get quark of the class at @index * Returns: Quark of this class (label) associated with @index * * Since: 1.24 */ GQuark gst_analytics_cls_mtd_get_quark (const GstAnalyticsClsMtd * handle, gsize index) { GstAnalyticsClsMtdData *cls_mtd_data; g_return_val_if_fail (handle, 0); cls_mtd_data = gst_analytics_relation_meta_get_mtd_data (handle->meta, handle->id); g_return_val_if_fail (cls_mtd_data != NULL, 0); g_return_val_if_fail (cls_mtd_data->length > index, 0); return cls_mtd_data->confidence_levels_and_classes[index].class; } /** * gst_analytics_relation_meta_add_cls_mtd: * @instance: Instance of #GstAnalyticsRelationMeta where to add classification instance * @length: length of @confidence_levels * @confidence_levels: (array length=length): confidence levels * @class_quarks: (array length=length): labels of this * classification. Order define index, quark, labels relation. This array * need to exist as long has this classification meta exist. * @cls_mtd: (out) (not nullable): Handle updated to newly added classification meta. * * Add analytic classification metadata to @instance. * Returns: Added successfully * * Since: 1.24 */ gboolean gst_analytics_relation_meta_add_cls_mtd (GstAnalyticsRelationMeta * instance, gsize length, gfloat * confidence_levels, GQuark * class_quarks, GstAnalyticsClsMtd * cls_mtd) { g_return_val_if_fail (instance, FALSE); g_return_val_if_fail (confidence_levels != NULL, FALSE); g_return_val_if_fail (class_quarks != NULL, FALSE); gsize confidence_levels_size = (sizeof (GstAnalyticsClsConfLvlAndClass) * length); gsize size = sizeof (GstAnalyticsClsMtdData) + confidence_levels_size; GstAnalyticsClsConfLvlAndClass *conf_lvls_and_classes; GstAnalyticsClsMtdData *cls_mtd_data = (GstAnalyticsClsMtdData *) gst_analytics_relation_meta_add_mtd (instance, &cls_impl, size, cls_mtd); if (cls_mtd_data) { cls_mtd_data->length = length; for (gsize i = 0; i < length; i++) { conf_lvls_and_classes = &(cls_mtd_data->confidence_levels_and_classes[i]); conf_lvls_and_classes->class = class_quarks[i]; conf_lvls_and_classes->confidence_levels = confidence_levels[i]; } } return cls_mtd_data != NULL; } /** * gst_analytics_relation_meta_add_one_cls_mtd: * @instance: Instance of #GstAnalyticsRelationMeta where to add classification instance * @confidence_level: confidence levels * @class_quark: labels of this * classification. Order define index, quark, labels relation. This array * need to exist as long has this classification meta exist. * @cls_mtd: (out) (not nullable): Handle updated to newly added classification meta. * * Add analytic classification metadata to @instance. * Returns: Added successfully * * Since: 1.24 */ gboolean gst_analytics_relation_meta_add_one_cls_mtd (GstAnalyticsRelationMeta * instance, gfloat confidence_level, GQuark class_quark, GstAnalyticsClsMtd * cls_mtd) { static const gsize len = 1; return gst_analytics_relation_meta_add_cls_mtd (instance, len, &confidence_level, &class_quark, cls_mtd); } /** * gst_analytics_relation_meta_get_cls_mtd: * @meta: Instance of #GstAnalyticsRelationMeta * @an_meta_id: Id of #GstAnalyticsClsMtd instance to retrieve * @rlt: (out caller-allocates)(not nullable): Will be filled with relatable * meta * * Fill @rlt if a analytics-meta with id == @an_meta_id exist in @meta instance, * otherwise this method return FALSE and @rlt is invalid. * * Returns: TRUE if successful. * * Since: 1.24 */ gboolean gst_analytics_relation_meta_get_cls_mtd (GstAnalyticsRelationMeta * meta, guint an_meta_id, GstAnalyticsClsMtd * rlt) { return gst_analytics_relation_meta_get_mtd (meta, an_meta_id, gst_analytics_cls_mtd_get_mtd_type (), (GstAnalyticsClsMtd *) rlt); }