LCOV - code coverage report
Current view: top level - nnstreamer-2.4.2/gst/nnstreamer/elements - gsttensor_sparseenc.c (source / functions) Coverage Total Hit
Test: nnstreamer 2.4.2-0 nnstreamer/nnstreamer#eca68b8d050408568af95d831a8eef62aaee7784 Lines: 91.9 % 124 114
Test Date: 2025-03-14 05:36:58 Functions: 100.0 % 12 12

            Line data    Source code
       1              : /* SPDX-License-Identifier: LGPL-2.1-only */
       2              : /**
       3              :  * Copyright (C) 2021 Samsung Electronics Co., Ltd.
       4              :  *
       5              :  * @file        gsttensor_sparseenc.c
       6              :  * @date        27 Jul 2021
       7              :  * @brief       GStreamer element to encode dense tensors into sparse tensors
       8              :  * @see         https://github.com/nnstreamer/nnstreamer
       9              :  * @author      Yongjoo Ahn <yongjoo1.ahn@samsung.com>
      10              :  * @bug         No known bugs except for NYI items
      11              :  */
      12              : 
      13              : /**
      14              :  * SECTION:element-tensor_sparse_enc
      15              :  *
      16              :  * tensor_sparse_enc is a GStreamer element to encode incoming tensor into sparse format.
      17              :  *
      18              :  * The input is always in the format of other/tensors,format=static.
      19              :  * The output is always in the format of ohter/tensors,format=sparse.
      20              :  *
      21              :  * Please see also tensor_sparse_dec.
      22              :  *
      23              :  * <refsect2>
      24              :  * <title>Example launch line</title>
      25              :  * |[
      26              :  * gst-launch-1.0 ... ! other/tensors,format=static ! \
      27              :  *    tensor_sparse_enc ! tensor_sink
      28              :  * ]|
      29              :  * </refsect2>
      30              :  */
      31              : 
      32              : #ifdef HAVE_CONFIG_H
      33              : #include <config.h>
      34              : #endif
      35              : 
      36              : #include <string.h>
      37              : #include <nnstreamer_util.h>
      38              : #include "gsttensor_sparseenc.h"
      39              : 
      40              : /**
      41              :  * @brief Macro for debug mode.
      42              :  */
      43              : #ifndef DBG
      44              : #define DBG (!self->silent)
      45              : #endif
      46              : 
      47              : GST_DEBUG_CATEGORY_STATIC (gst_tensor_sparse_enc_debug);
      48              : #define GST_CAT_DEFAULT gst_tensor_sparse_enc_debug
      49              : 
      50              : /**
      51              :  * @brief tensor_sparse_enc properties
      52              :  */
      53              : enum
      54              : {
      55              :   PROP_0,
      56              :   PROP_SILENT
      57              : };
      58              : 
      59              : /**
      60              :  * @brief Flag to print minimized log.
      61              :  */
      62              : #define DEFAULT_SILENT TRUE
      63              : 
      64              : /**
      65              :  * @brief Template for sink pad.
      66              :  */
      67              : static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
      68              :     GST_PAD_SINK,
      69              :     GST_PAD_ALWAYS,
      70              :     GST_STATIC_CAPS (GST_TENSORS_CAP_DEFAULT));
      71              : 
      72              : /**
      73              :  * @brief Template for src pad.
      74              :  */
      75              : static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
      76              :     GST_PAD_SRC,
      77              :     GST_PAD_ALWAYS,
      78              :     GST_STATIC_CAPS (GST_TENSORS_SPARSE_CAP_DEFAULT));
      79              : 
      80              : #define gst_tensor_sparse_enc_parent_class parent_class
      81         1023 : G_DEFINE_TYPE (GstTensorSparseEnc, gst_tensor_sparse_enc, GST_TYPE_ELEMENT);
      82              : 
      83              : static void gst_tensor_sparse_enc_finalize (GObject * object);
      84              : static void gst_tensor_sparse_enc_set_property (GObject * object, guint prop_id,
      85              :     const GValue * value, GParamSpec * pspec);
      86              : static void gst_tensor_sparse_enc_get_property (GObject * object, guint prop_id,
      87              :     GValue * value, GParamSpec * pspec);
      88              : static GstFlowReturn
      89              : gst_tensor_sparse_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf);
      90              : static GstCaps *gst_tensor_sparse_enc_query_caps (GstTensorSparseEnc * self,
      91              :     GstPad * pad, GstCaps * filter);
      92              : static gboolean gst_tensor_sparse_enc_sink_event (GstPad * pad,
      93              :     GstObject * parent, GstEvent * event);
      94              : static gboolean gst_tensor_sparse_enc_sink_query (GstPad * pad,
      95              :     GstObject * parent, GstQuery * query);
      96              : 
      97              : /**
      98              :  * @brief Initialize the tensor_sparse's class.
      99              :  */
     100              : static void
     101            9 : gst_tensor_sparse_enc_class_init (GstTensorSparseEncClass * klass)
     102              : {
     103              :   GObjectClass *object_class;
     104              :   GstElementClass *element_class;
     105              : 
     106            9 :   GST_DEBUG_CATEGORY_INIT (gst_tensor_sparse_enc_debug, "tensor_sparse_enc", 0,
     107              :       "Element to encode sparse tensors");
     108              : 
     109            9 :   object_class = (GObjectClass *) klass;
     110            9 :   element_class = (GstElementClass *) klass;
     111              : 
     112            9 :   object_class->set_property = gst_tensor_sparse_enc_set_property;
     113            9 :   object_class->get_property = gst_tensor_sparse_enc_get_property;
     114            9 :   object_class->finalize = gst_tensor_sparse_enc_finalize;
     115              : 
     116              :   /**
     117              :    * GstTensorSparseEnc::silent:
     118              :    *
     119              :    * The flag to enable/disable debugging messages.
     120              :    */
     121            9 :   g_object_class_install_property (object_class, PROP_SILENT,
     122              :       g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
     123              :           DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
     124              : 
     125            9 :   gst_element_class_add_pad_template (element_class,
     126              :       gst_static_pad_template_get (&src_template));
     127              : 
     128            9 :   gst_element_class_add_pad_template (element_class,
     129              :       gst_static_pad_template_get (&sink_template));
     130              : 
     131            9 :   gst_element_class_set_static_metadata (element_class,
     132              :       "TensorSparseEnc",
     133              :       "Filter/Tensor",
     134              :       "Element to encode dense tensors into sparse tensors",
     135              :       "Samsung Electronics Co., Ltd.");
     136            9 : }
     137              : 
     138              : /**
     139              :  * @brief Initialize tensor_sparse_enc element.
     140              :  */
     141              : static void
     142           10 : gst_tensor_sparse_enc_init (GstTensorSparseEnc * self)
     143              : {
     144              :   /* setup sink pad */
     145           10 :   self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
     146           10 :   gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
     147              : 
     148              :   /* setup src pad */
     149           10 :   self->srcpad = gst_pad_new_from_static_template (&src_template, "src");
     150           10 :   gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
     151              : 
     152              :   /* setup chain function */
     153           10 :   gst_pad_set_chain_function (self->sinkpad,
     154              :       GST_DEBUG_FUNCPTR (gst_tensor_sparse_enc_chain));
     155              : 
     156              :   /* setup event function */
     157           10 :   gst_pad_set_event_function (self->sinkpad,
     158              :       GST_DEBUG_FUNCPTR (gst_tensor_sparse_enc_sink_event));
     159              : 
     160           10 :   gst_pad_set_query_function (self->sinkpad,
     161              :       GST_DEBUG_FUNCPTR (gst_tensor_sparse_enc_sink_query));
     162              : 
     163              :   /* init properties */
     164           10 :   self->silent = DEFAULT_SILENT;
     165           10 :   gst_tensors_config_init (&self->in_config);
     166           10 : }
     167              : 
     168              : /**
     169              :  * @brief Function to finalize instance.
     170              :  */
     171              : static void
     172           10 : gst_tensor_sparse_enc_finalize (GObject * object)
     173              : {
     174              :   GstTensorSparseEnc *self;
     175           10 :   self = GST_TENSOR_SPARSE_ENC (object);
     176              : 
     177           10 :   gst_tensors_config_free (&self->in_config);
     178              : 
     179           10 :   G_OBJECT_CLASS (parent_class)->finalize (object);
     180           10 : }
     181              : 
     182              : /**
     183              :  * @brief Setter for tensor_sparse_enc properties.
     184              :  */
     185              : static void
     186            1 : gst_tensor_sparse_enc_set_property (GObject * object, guint prop_id,
     187              :     const GValue * value, GParamSpec * pspec)
     188              : {
     189              :   GstTensorSparseEnc *self;
     190              : 
     191            1 :   self = GST_TENSOR_SPARSE_ENC (object);
     192              : 
     193            1 :   switch (prop_id) {
     194            1 :     case PROP_SILENT:
     195            1 :       self->silent = g_value_get_boolean (value);
     196            1 :       break;
     197            0 :     default:
     198            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     199            0 :       break;
     200              :   }
     201            1 : }
     202              : 
     203              : /**
     204              :  * @brief Getter for tensor_sparse_enc properties.
     205              :  */
     206              : static void
     207            2 : gst_tensor_sparse_enc_get_property (GObject * object, guint prop_id,
     208              :     GValue * value, GParamSpec * pspec)
     209              : {
     210              :   GstTensorSparseEnc *self;
     211              : 
     212            2 :   self = GST_TENSOR_SPARSE_ENC (object);
     213              : 
     214            2 :   switch (prop_id) {
     215            2 :     case PROP_SILENT:
     216            2 :       g_value_set_boolean (value, self->silent);
     217            2 :       break;
     218            0 :     default:
     219            0 :       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
     220            0 :       break;
     221              :   }
     222            2 : }
     223              : 
     224              : /**
     225              :  * @brief This function handles sink pad event.
     226              :  */
     227              : static gboolean
     228           33 : gst_tensor_sparse_enc_sink_event (GstPad * pad, GstObject * parent,
     229              :     GstEvent * event)
     230              : {
     231              :   GstTensorSparseEnc *self;
     232           33 :   self = GST_TENSOR_SPARSE_ENC (parent);
     233              : 
     234           33 :   g_return_val_if_fail (event != NULL, FALSE);
     235              : 
     236           33 :   switch (GST_EVENT_TYPE (event)) {
     237            8 :     case GST_EVENT_CAPS:
     238              :     {
     239              :       GstCaps *caps;
     240              :       gboolean ret;
     241              : 
     242            8 :       gst_event_parse_caps (event, &caps);
     243            8 :       silent_debug_caps (self, caps, "caps");
     244              : 
     245            8 :       ret = gst_tensors_config_from_cap (&self->in_config, caps);
     246            8 :       gst_event_unref (event);
     247            8 :       return ret;
     248              :     }
     249           25 :     default:
     250           25 :       break;
     251              :   }
     252              : 
     253           25 :   return gst_pad_event_default (pad, parent, event);
     254              : }
     255              : 
     256              : /**
     257              :  * @brief Get pad caps for caps negotiation.
     258              :  */
     259              : static GstCaps *
     260           48 : gst_tensor_sparse_enc_query_caps (GstTensorSparseEnc * self, GstPad * pad,
     261              :     GstCaps * filter)
     262              : {
     263              :   GstCaps *caps;
     264              : 
     265           48 :   caps = gst_pad_get_current_caps (pad);
     266           48 :   if (!caps) {
     267              :     /** pad don't have current caps. use the template caps */
     268           48 :     caps = gst_pad_get_pad_template_caps (pad);
     269              :   }
     270              : 
     271           48 :   silent_debug_caps (self, caps, "caps");
     272           48 :   silent_debug_caps (self, filter, "filter");
     273              : 
     274           48 :   if (filter) {
     275              :     GstCaps *intersection;
     276              :     intersection =
     277            7 :         gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
     278              : 
     279            7 :     gst_caps_unref (caps);
     280            7 :     caps = intersection;
     281              :   }
     282              : 
     283           48 :   silent_debug_caps (self, caps, "result");
     284           48 :   return caps;
     285              : }
     286              : 
     287              : /**
     288              :  * @brief This function handles sink pad query.
     289              :  */
     290              : static gboolean
     291           69 : gst_tensor_sparse_enc_sink_query (GstPad * pad, GstObject * parent,
     292              :     GstQuery * query)
     293              : {
     294              :   GstTensorSparseEnc *self;
     295              : 
     296           69 :   self = GST_TENSOR_SPARSE_ENC (parent);
     297              : 
     298           69 :   GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT,
     299              :       GST_QUERY_TYPE_NAME (query), query);
     300              : 
     301           69 :   switch (GST_QUERY_TYPE (query)) {
     302           48 :     case GST_QUERY_CAPS:
     303              :     {
     304              :       GstCaps *caps;
     305              :       GstCaps *filter;
     306              : 
     307           48 :       gst_query_parse_caps (query, &filter);
     308           48 :       caps = gst_tensor_sparse_enc_query_caps (self, pad, filter);
     309           48 :       silent_debug_caps (self, filter, "filter");
     310           48 :       silent_debug_caps (self, caps, "caps");
     311           48 :       gst_query_set_caps_result (query, caps);
     312           48 :       gst_caps_unref (caps);
     313           48 :       return TRUE;
     314              :     }
     315           16 :     case GST_QUERY_ACCEPT_CAPS:
     316              :     {
     317              :       GstCaps *caps;
     318              :       GstCaps *template_caps;
     319           16 :       gboolean res = FALSE;
     320              : 
     321           16 :       gst_query_parse_accept_caps (query, &caps);
     322           16 :       silent_debug_caps (self, caps, "caps");
     323              : 
     324           16 :       if (gst_caps_is_fixed (caps)) {
     325           16 :         template_caps = gst_pad_get_pad_template_caps (pad);
     326              : 
     327           16 :         res = gst_caps_can_intersect (template_caps, caps);
     328           16 :         gst_caps_unref (template_caps);
     329              :       }
     330              : 
     331           16 :       gst_query_set_accept_caps_result (query, res);
     332           16 :       return TRUE;
     333              :     }
     334            5 :     default:
     335            5 :       break;
     336              :   }
     337              : 
     338            5 :   return gst_pad_query_default (pad, parent, query);
     339              : }
     340              : 
     341              : 
     342              : /**
     343              :  * @brief Internal function to transform the input buffer.
     344              :  */
     345              : static GstFlowReturn
     346           35 : gst_tensor_sparse_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
     347              : {
     348           35 :   GstFlowReturn ret = GST_FLOW_OK;
     349           35 :   GstTensorSparseEnc *self = GST_TENSOR_SPARSE_ENC (parent);
     350              :   GstMemory *in_mem, *out_mem;
     351              :   GstBuffer *outbuf;
     352              :   GstTensorsInfo *info;
     353              :   GstTensorInfo *_info;
     354              :   guint i;
     355              : 
     356              :   UNUSED (pad);
     357              : 
     358           35 :   info = &self->in_config.info;
     359           35 :   buf = gst_tensor_buffer_from_config (buf, &self->in_config);
     360           35 :   outbuf = gst_buffer_new ();
     361              : 
     362          101 :   for (i = 0; i < info->num_tensors; ++i) {
     363              :     GstTensorMetaInfo meta;
     364              : 
     365           66 :     _info = gst_tensors_info_get_nth_info (info, i);
     366           66 :     gst_tensor_info_convert_to_meta (_info, &meta);
     367              : 
     368           66 :     meta.format = _NNS_TENSOR_FORMAT_SPARSE;
     369           66 :     meta.media_type = _NNS_TENSOR;
     370              : 
     371              :     /* do real encoding here */
     372           66 :     in_mem = gst_tensor_buffer_get_nth_memory (buf, i);
     373           66 :     out_mem = gst_tensor_sparse_from_dense (&meta, in_mem);
     374           66 :     gst_memory_unref (in_mem);
     375              : 
     376           66 :     if (!out_mem) {
     377            0 :       nns_loge ("failed to convert to sparse tensor");
     378            0 :       ret = GST_FLOW_ERROR;
     379            0 :       goto done;
     380              :     }
     381              : 
     382           66 :     gst_tensor_buffer_append_memory (outbuf, out_mem, _info);
     383              :   }
     384              : 
     385           35 :   ret = gst_pad_push (self->srcpad, outbuf);
     386              : 
     387           35 : done:
     388           35 :   gst_buffer_unref (buf);
     389           35 :   if (ret != GST_FLOW_OK)
     390            0 :     gst_buffer_unref (outbuf);
     391              : 
     392           35 :   return ret;
     393              : }
        

Generated by: LCOV version 2.0-1