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.git#5d55fc62547faa02e861af5ef93cc1c89800934a Lines: 91.0 % 134 122
Test Date: 2024-09-25 09:08:39 Functions: 100.0 % 13 13

            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         1083 : 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           29 : gst_tensor_sparse_enc_class_init (GstTensorSparseEncClass * klass)
     102              : {
     103              :   GObjectClass *object_class;
     104              :   GstElementClass *element_class;
     105              : 
     106           29 :   GST_DEBUG_CATEGORY_INIT (gst_tensor_sparse_enc_debug, "tensor_sparse_enc", 0,
     107              :       "Element to encode sparse tensors");
     108              : 
     109           29 :   object_class = (GObjectClass *) klass;
     110           29 :   element_class = (GstElementClass *) klass;
     111              : 
     112           29 :   object_class->set_property = gst_tensor_sparse_enc_set_property;
     113           29 :   object_class->get_property = gst_tensor_sparse_enc_get_property;
     114           29 :   object_class->finalize = gst_tensor_sparse_enc_finalize;
     115              : 
     116              :   /**
     117              :    * GstTensorSparseEnc::silent:
     118              :    *
     119              :    * The flag to enable/disable debugging messages.
     120              :    */
     121           29 :   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           29 :   gst_element_class_add_pad_template (element_class,
     126              :       gst_static_pad_template_get (&src_template));
     127              : 
     128           29 :   gst_element_class_add_pad_template (element_class,
     129              :       gst_static_pad_template_get (&sink_template));
     130              : 
     131           29 :   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           29 : }
     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 Parse caps and set tensors config
     226              :  */
     227              : static gboolean
     228            8 : gst_tensor_sparse_enc_parse_caps (GstTensorSparseEnc * self,
     229              :     const GstCaps * caps)
     230              : {
     231              :   GstStructure *structure;
     232              :   GstTensorsConfig config;
     233              : 
     234           16 :   g_return_val_if_fail (caps != NULL, FALSE);
     235            8 :   g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
     236              : 
     237            8 :   structure = gst_caps_get_structure (caps, 0);
     238              : 
     239            8 :   if (!gst_tensors_config_from_structure (&config, structure) ||
     240            8 :       !gst_tensors_config_validate (&config)) {
     241              :     /** not fully configured */
     242            0 :     GST_ERROR_OBJECT (self, "Failed to configure tensors config.\n");
     243            0 :     return FALSE;
     244              :   }
     245              : 
     246            8 :   self->in_config = config;
     247            8 :   return TRUE;
     248              : }
     249              : 
     250              : /**
     251              :  * @brief This function handles sink pad event.
     252              :  */
     253              : static gboolean
     254           33 : gst_tensor_sparse_enc_sink_event (GstPad * pad, GstObject * parent,
     255              :     GstEvent * event)
     256              : {
     257              :   GstTensorSparseEnc *self;
     258           33 :   self = GST_TENSOR_SPARSE_ENC (parent);
     259              : 
     260           33 :   g_return_val_if_fail (event != NULL, FALSE);
     261              : 
     262           33 :   switch (GST_EVENT_TYPE (event)) {
     263            8 :     case GST_EVENT_CAPS:
     264              :     {
     265              :       GstCaps *caps;
     266              :       gboolean ret;
     267              : 
     268            8 :       gst_event_parse_caps (event, &caps);
     269            8 :       silent_debug_caps (self, caps, "caps");
     270              : 
     271            8 :       ret = gst_tensor_sparse_enc_parse_caps (self, caps);
     272            8 :       gst_event_unref (event);
     273            8 :       return ret;
     274              :     }
     275           25 :     default:
     276           25 :       break;
     277              :   }
     278              : 
     279           25 :   return gst_pad_event_default (pad, parent, event);
     280              : }
     281              : 
     282              : /**
     283              :  * @brief Get pad caps for caps negotiation.
     284              :  */
     285              : static GstCaps *
     286           48 : gst_tensor_sparse_enc_query_caps (GstTensorSparseEnc * self, GstPad * pad,
     287              :     GstCaps * filter)
     288              : {
     289              :   GstCaps *caps;
     290              : 
     291           48 :   caps = gst_pad_get_current_caps (pad);
     292           48 :   if (!caps) {
     293              :     /** pad don't have current caps. use the template caps */
     294           48 :     caps = gst_pad_get_pad_template_caps (pad);
     295              :   }
     296              : 
     297           48 :   silent_debug_caps (self, caps, "caps");
     298           48 :   silent_debug_caps (self, filter, "filter");
     299              : 
     300           48 :   if (filter) {
     301              :     GstCaps *intersection;
     302              :     intersection =
     303            7 :         gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
     304              : 
     305            7 :     gst_caps_unref (caps);
     306            7 :     caps = intersection;
     307              :   }
     308              : 
     309           48 :   silent_debug_caps (self, caps, "result");
     310           48 :   return caps;
     311              : }
     312              : 
     313              : /**
     314              :  * @brief This function handles sink pad query.
     315              :  */
     316              : static gboolean
     317           69 : gst_tensor_sparse_enc_sink_query (GstPad * pad, GstObject * parent,
     318              :     GstQuery * query)
     319              : {
     320              :   GstTensorSparseEnc *self;
     321              : 
     322           69 :   self = GST_TENSOR_SPARSE_ENC (parent);
     323              : 
     324           69 :   GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT,
     325              :       GST_QUERY_TYPE_NAME (query), query);
     326              : 
     327           69 :   switch (GST_QUERY_TYPE (query)) {
     328           48 :     case GST_QUERY_CAPS:
     329              :     {
     330              :       GstCaps *caps;
     331              :       GstCaps *filter;
     332              : 
     333           48 :       gst_query_parse_caps (query, &filter);
     334           48 :       caps = gst_tensor_sparse_enc_query_caps (self, pad, filter);
     335           48 :       silent_debug_caps (self, filter, "filter");
     336           48 :       silent_debug_caps (self, caps, "caps");
     337           48 :       gst_query_set_caps_result (query, caps);
     338           48 :       gst_caps_unref (caps);
     339           48 :       return TRUE;
     340              :     }
     341           16 :     case GST_QUERY_ACCEPT_CAPS:
     342              :     {
     343              :       GstCaps *caps;
     344              :       GstCaps *template_caps;
     345           16 :       gboolean res = FALSE;
     346              : 
     347           16 :       gst_query_parse_accept_caps (query, &caps);
     348           16 :       silent_debug_caps (self, caps, "caps");
     349              : 
     350           16 :       if (gst_caps_is_fixed (caps)) {
     351           16 :         template_caps = gst_pad_get_pad_template_caps (pad);
     352              : 
     353           16 :         res = gst_caps_can_intersect (template_caps, caps);
     354           16 :         gst_caps_unref (template_caps);
     355              :       }
     356              : 
     357           16 :       gst_query_set_accept_caps_result (query, res);
     358           16 :       return TRUE;
     359              :     }
     360            5 :     default:
     361            5 :       break;
     362              :   }
     363              : 
     364            5 :   return gst_pad_query_default (pad, parent, query);
     365              : }
     366              : 
     367              : 
     368              : /**
     369              :  * @brief Internal function to transform the input buffer.
     370              :  */
     371              : static GstFlowReturn
     372           35 : gst_tensor_sparse_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
     373              : {
     374           35 :   GstFlowReturn ret = GST_FLOW_OK;
     375           35 :   GstTensorSparseEnc *self = GST_TENSOR_SPARSE_ENC (parent);
     376              :   GstMemory *in_mem, *out_mem;
     377              :   GstBuffer *outbuf;
     378              :   GstTensorsInfo *info;
     379              :   GstTensorInfo *_info;
     380              :   guint i;
     381              : 
     382              :   UNUSED (pad);
     383              : 
     384           35 :   info = &self->in_config.info;
     385           35 :   buf = gst_tensor_buffer_from_config (buf, &self->in_config);
     386           35 :   outbuf = gst_buffer_new ();
     387              : 
     388          101 :   for (i = 0; i < info->num_tensors; ++i) {
     389              :     GstTensorMetaInfo meta;
     390              : 
     391           66 :     _info = gst_tensors_info_get_nth_info (info, i);
     392           66 :     gst_tensor_info_convert_to_meta (_info, &meta);
     393              : 
     394           66 :     meta.format = _NNS_TENSOR_FORMAT_SPARSE;
     395           66 :     meta.media_type = _NNS_TENSOR;
     396              : 
     397              :     /* do real encoding here */
     398           66 :     in_mem = gst_tensor_buffer_get_nth_memory (buf, i);
     399           66 :     out_mem = gst_tensor_sparse_from_dense (&meta, in_mem);
     400           66 :     gst_memory_unref (in_mem);
     401              : 
     402           66 :     if (!out_mem) {
     403            0 :       nns_loge ("failed to convert to sparse tensor");
     404            0 :       ret = GST_FLOW_ERROR;
     405            0 :       goto done;
     406              :     }
     407              : 
     408           66 :     gst_tensor_buffer_append_memory (outbuf, out_mem, _info);
     409              :   }
     410              : 
     411           35 :   ret = gst_pad_push (self->srcpad, outbuf);
     412              : 
     413           35 : done:
     414           35 :   gst_buffer_unref (buf);
     415           35 :   if (ret != GST_FLOW_OK)
     416            0 :     gst_buffer_unref (outbuf);
     417              : 
     418           35 :   return ret;
     419              : }
        

Generated by: LCOV version 2.0-1