Doxygen Book
gsttensor_sparseenc.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-only */
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 
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 
53 enum
54 {
57 };
58 
62 #define DEFAULT_SILENT TRUE
63 
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 
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 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);
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 
100 static void
102 {
103  GObjectClass *object_class;
104  GstElementClass *element_class;
105 
106  GST_DEBUG_CATEGORY_INIT (gst_tensor_sparse_enc_debug, "tensor_sparse_enc", 0,
107  "Element to encode sparse tensors");
108 
109  object_class = (GObjectClass *) klass;
110  element_class = (GstElementClass *) klass;
111 
112  object_class->set_property = gst_tensor_sparse_enc_set_property;
113  object_class->get_property = gst_tensor_sparse_enc_get_property;
114  object_class->finalize = gst_tensor_sparse_enc_finalize;
115 
121  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  gst_element_class_add_pad_template (element_class,
126  gst_static_pad_template_get (&src_template));
127 
128  gst_element_class_add_pad_template (element_class,
129  gst_static_pad_template_get (&sink_template));
130 
131  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 }
137 
141 static void
143 {
144  /* setup sink pad */
145  self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
146  gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
147 
148  /* setup src pad */
149  self->srcpad = gst_pad_new_from_static_template (&src_template, "src");
150  gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
151 
152  /* setup chain function */
153  gst_pad_set_chain_function (self->sinkpad,
154  GST_DEBUG_FUNCPTR (gst_tensor_sparse_enc_chain));
155 
156  /* setup event function */
157  gst_pad_set_event_function (self->sinkpad,
158  GST_DEBUG_FUNCPTR (gst_tensor_sparse_enc_sink_event));
159 
160  gst_pad_set_query_function (self->sinkpad,
161  GST_DEBUG_FUNCPTR (gst_tensor_sparse_enc_sink_query));
162 
163  /* init properties */
164  self->silent = DEFAULT_SILENT;
165  gst_tensors_config_init (&self->in_config);
166 }
167 
171 static void
173 {
174  GstTensorSparseEnc *self;
175  self = GST_TENSOR_SPARSE_ENC (object);
176 
177  gst_tensors_config_free (&self->in_config);
178 
179  G_OBJECT_CLASS (parent_class)->finalize (object);
180 }
181 
185 static void
186 gst_tensor_sparse_enc_set_property (GObject * object, guint prop_id,
187  const GValue * value, GParamSpec * pspec)
188 {
189  GstTensorSparseEnc *self;
190 
191  self = GST_TENSOR_SPARSE_ENC (object);
192 
193  switch (prop_id) {
194  case PROP_SILENT:
195  self->silent = g_value_get_boolean (value);
196  break;
197  default:
198  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
199  break;
200  }
201 }
202 
206 static void
207 gst_tensor_sparse_enc_get_property (GObject * object, guint prop_id,
208  GValue * value, GParamSpec * pspec)
209 {
210  GstTensorSparseEnc *self;
211 
212  self = GST_TENSOR_SPARSE_ENC (object);
213 
214  switch (prop_id) {
215  case PROP_SILENT:
216  g_value_set_boolean (value, self->silent);
217  break;
218  default:
219  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
220  break;
221  }
222 }
223 
227 static gboolean
229  const GstCaps * caps)
230 {
231  GstStructure *structure;
232  GstTensorsConfig config;
233 
234  g_return_val_if_fail (caps != NULL, FALSE);
235  g_return_val_if_fail (gst_caps_is_fixed (caps), FALSE);
236 
237  structure = gst_caps_get_structure (caps, 0);
238 
239  if (!gst_tensors_config_from_structure (&config, structure) ||
240  !gst_tensors_config_validate (&config)) {
242  GST_ERROR_OBJECT (self, "Failed to configure tensors config.\n");
243  return FALSE;
244  }
245 
246  self->in_config = config;
247  return TRUE;
248 }
249 
253 static gboolean
254 gst_tensor_sparse_enc_sink_event (GstPad * pad, GstObject * parent,
255  GstEvent * event)
256 {
257  GstTensorSparseEnc *self;
258  self = GST_TENSOR_SPARSE_ENC (parent);
259 
260  g_return_val_if_fail (event != NULL, FALSE);
261 
262  switch (GST_EVENT_TYPE (event)) {
263  case GST_EVENT_CAPS:
264  {
265  GstCaps *caps;
266  gboolean ret;
267 
268  gst_event_parse_caps (event, &caps);
269  silent_debug_caps (self, caps, "caps");
270 
271  ret = gst_tensor_sparse_enc_parse_caps (self, caps);
272  gst_event_unref (event);
273  return ret;
274  }
275  default:
276  break;
277  }
278 
279  return gst_pad_event_default (pad, parent, event);
280 }
281 
285 static GstCaps *
287  GstCaps * filter)
288 {
289  GstCaps *caps;
290 
291  caps = gst_pad_get_current_caps (pad);
292  if (!caps) {
294  caps = gst_pad_get_pad_template_caps (pad);
295  }
296 
297  silent_debug_caps (self, caps, "caps");
298  silent_debug_caps (self, filter, "filter");
299 
300  if (filter) {
301  GstCaps *intersection;
302  intersection =
303  gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
304 
305  gst_caps_unref (caps);
306  caps = intersection;
307  }
308 
309  silent_debug_caps (self, caps, "result");
310  return caps;
311 }
312 
316 static gboolean
317 gst_tensor_sparse_enc_sink_query (GstPad * pad, GstObject * parent,
318  GstQuery * query)
319 {
320  GstTensorSparseEnc *self;
321 
322  self = GST_TENSOR_SPARSE_ENC (parent);
323 
324  GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT,
325  GST_QUERY_TYPE_NAME (query), query);
326 
327  switch (GST_QUERY_TYPE (query)) {
328  case GST_QUERY_CAPS:
329  {
330  GstCaps *caps;
331  GstCaps *filter;
332 
333  gst_query_parse_caps (query, &filter);
334  caps = gst_tensor_sparse_enc_query_caps (self, pad, filter);
335  silent_debug_caps (self, filter, "filter");
336  silent_debug_caps (self, caps, "caps");
337  gst_query_set_caps_result (query, caps);
338  gst_caps_unref (caps);
339  return TRUE;
340  }
341  case GST_QUERY_ACCEPT_CAPS:
342  {
343  GstCaps *caps;
344  GstCaps *template_caps;
345  gboolean res = FALSE;
346 
347  gst_query_parse_accept_caps (query, &caps);
348  silent_debug_caps (self, caps, "caps");
349 
350  if (gst_caps_is_fixed (caps)) {
351  template_caps = gst_pad_get_pad_template_caps (pad);
352 
353  res = gst_caps_can_intersect (template_caps, caps);
354  gst_caps_unref (template_caps);
355  }
356 
357  gst_query_set_accept_caps_result (query, res);
358  return TRUE;
359  }
360  default:
361  break;
362  }
363 
364  return gst_pad_query_default (pad, parent, query);
365 }
366 
367 
371 static GstFlowReturn
372 gst_tensor_sparse_enc_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
373 {
374  GstFlowReturn ret = GST_FLOW_OK;
375  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  info = &self->in_config.info;
385  buf = gst_tensor_buffer_from_config (buf, &self->in_config);
386  outbuf = gst_buffer_new ();
387 
388  for (i = 0; i < info->num_tensors; ++i) {
389  GstTensorMetaInfo meta;
390 
391  _info = gst_tensors_info_get_nth_info (info, i);
392  gst_tensor_info_convert_to_meta (_info, &meta);
393 
395  meta.media_type = _NNS_TENSOR;
396 
397  /* do real encoding here */
398  in_mem = gst_tensor_buffer_get_nth_memory (buf, i);
399  out_mem = gst_tensor_sparse_from_dense (&meta, in_mem);
400  gst_memory_unref (in_mem);
401 
402  if (!out_mem) {
403  nns_loge ("failed to convert to sparse tensor");
404  ret = GST_FLOW_ERROR;
405  goto done;
406  }
407 
408  gst_tensor_buffer_append_memory (outbuf, out_mem, _info);
409  }
410 
411  ret = gst_pad_push (self->srcpad, outbuf);
412 
413 done:
414  gst_buffer_unref (buf);
415  if (ret != GST_FLOW_OK)
416  gst_buffer_unref (outbuf);
417 
418  return ret;
419 }
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_sparse_enc_debug)
DEFAULT_SILENT
#define DEFAULT_SILENT
Flag to print minimized log.
Definition: gsttensor_sparseenc.c:62
gst_tensor_sparse_from_dense
GstMemory * gst_tensor_sparse_from_dense(GstTensorMetaInfo *meta, GstMemory *mem)
Make sparse tensor with input dense tensor.
Definition: gsttensor_sparseutil.c:116
gst_tensor_buffer_from_config
GstBuffer * gst_tensor_buffer_from_config(GstBuffer *in, GstTensorsConfig *config)
Configure gst-buffer with tensors information. NNStreamer handles single memory chunk as single tenso...
Definition: nnstreamer_plugin_api_impl.c:535
gst_tensor_sparse_enc_query_caps
static GstCaps * gst_tensor_sparse_enc_query_caps(GstTensorSparseEnc *self, GstPad *pad, GstCaps *filter)
Get pad caps for caps negotiation.
Definition: gsttensor_sparseenc.c:286
gst_tensor_sparse_enc_sink_query
static gboolean gst_tensor_sparse_enc_sink_query(GstPad *pad, GstObject *parent, GstQuery *query)
This function handles sink pad query.
Definition: gsttensor_sparseenc.c:317
GstTensorInfo
Internal data structure for tensor info.
Definition: tensor_typedef.h:261
FALSE
return FALSE
Definition: gsttensor_transform.c:590
GstTensorsInfo
Internal meta data exchange format for a other/tensors instance.
Definition: tensor_typedef.h:273
sink_template
static GstStaticPadTemplate sink_template
Template for sink pad.
Definition: gsttensor_sparseenc.c:67
_GstTensorSparseEncClass
GstTensorSparseClass data structure.
Definition: gsttensor_sparseenc.h:53
GST_TENSOR_SPARSE_ENC
#define GST_TENSOR_SPARSE_ENC(obj)
Definition: gsttensor_sparseenc.h:24
gst_tensor_sparse_enc_class_init
static void gst_tensor_sparse_enc_class_init(GstTensorSparseEncClass *klass)
Initialize the tensor_sparse's class.
Definition: gsttensor_sparseenc.c:101
GstTensorMetaInfo
Data structure to describe a tensor data. This represents the basic information of a memory block for...
Definition: tensor_typedef.h:310
_NNS_TENSOR
@ _NNS_TENSOR
Definition: tensor_typedef.h:186
GstTensorMetaInfo::media_type
uint32_t media_type
Definition: tensor_typedef.h:317
gst_tensor_sparse_enc_finalize
static void gst_tensor_sparse_enc_finalize(GObject *object)
Function to finalize instance.
Definition: gsttensor_sparseenc.c:172
gst_tensor_sparse_enc_init
static void gst_tensor_sparse_enc_init(GstTensorSparseEnc *self)
Initialize tensor_sparse_enc element.
Definition: gsttensor_sparseenc.c:142
gst_tensor_sparse_enc_chain
static GstFlowReturn gst_tensor_sparse_enc_chain(GstPad *pad, GstObject *parent, GstBuffer *buf)
Internal function to transform the input buffer.
Definition: gsttensor_sparseenc.c:372
GstTensorsInfo::info
GstTensorInfo info[NNS_TENSOR_MEMORY_MAX]
Definition: tensor_typedef.h:276
gst_tensors_config_free
void gst_tensors_config_free(GstTensorsConfig *config)
Free allocated data in tensors config structure.
Definition: nnstreamer_plugin_api_util_impl.c:845
gst_tensor_info_convert_to_meta
gboolean gst_tensor_info_convert_to_meta(GstTensorInfo *info, GstTensorMetaInfo *meta)
Convert GstTensorInfo structure to GstTensorMetaInfo.
Definition: nnstreamer_plugin_api_util_impl.c:260
_NNS_TENSOR_FORMAT_SPARSE
@ _NNS_TENSOR_FORMAT_SPARSE
Definition: tensor_typedef.h:197
GstTensorsConfig
Internal data structure for configured tensors info (for other/tensors).
Definition: tensor_typedef.h:284
silent_debug_caps
#define silent_debug_caps(self, caps, msg)
Macro for capability debug message.
Definition: tensor_common.h:285
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_sparseenc.c:56
TRUE
return TRUE
Definition: gsttensor_if.c:897
UNUSED
#define UNUSED(expr)
Definition: mqttcommon.h:19
nns_loge
#define nns_loge
Definition: nnstreamer_log.h:142
src_template
static GstStaticPadTemplate src_template
Template for src pad.
Definition: gsttensor_sparseenc.c:75
nnstreamer_util.h
Optional NNStreamer utility functions for sub-plugin writers and users.
GST_TENSORS_SPARSE_CAP_DEFAULT
#define GST_TENSORS_SPARSE_CAP_DEFAULT
Caps string for the caps template of sparse tensors. This mimetype handles non-static,...
Definition: tensor_typedef.h:131
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorSparseEnc, gst_tensor_sparse_enc, GST_TYPE_ELEMENT)
gst_tensors_info_get_nth_info
GstTensorInfo * gst_tensors_info_get_nth_info(GstTensorsInfo *info, guint index)
Get the pointer of nth tensor information.
Definition: nnstreamer_plugin_api_util_impl.c:296
GST_TENSORS_CAP_DEFAULT
#define GST_TENSORS_CAP_DEFAULT
Caps string for the caps template of static tensor stream.
Definition: tensor_typedef.h:115
GstTensorMetaInfo::format
uint32_t format
Definition: tensor_typedef.h:316
GstTensorsInfo::num_tensors
unsigned int num_tensors
Definition: tensor_typedef.h:275
gst_tensor_buffer_get_nth_memory
GstMemory * gst_tensor_buffer_get_nth_memory(GstBuffer *buffer, const guint index)
Get the nth GstMemory from given buffer.
Definition: nnstreamer_plugin_api_impl.c:1586
gst_tensors_config_init
void gst_tensors_config_init(GstTensorsConfig *config)
Initialize the tensors config info structure (for other/tensors)
Definition: nnstreamer_plugin_api_util_impl.c:830
gst_tensor_sparse_enc_parse_caps
static gboolean gst_tensor_sparse_enc_parse_caps(GstTensorSparseEnc *self, const GstCaps *caps)
Parse caps and set tensors config.
Definition: gsttensor_sparseenc.c:228
gst_tensor_sparse_enc_set_property
static void gst_tensor_sparse_enc_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Setter for tensor_sparse_enc properties.
Definition: gsttensor_sparseenc.c:186
gst_tensors_config_validate
gboolean gst_tensors_config_validate(const GstTensorsConfig *config)
Check the tensors are all configured (for other/tensors)
Definition: nnstreamer_plugin_api_util_impl.c:858
gst_tensor_sparse_enc_get_property
static void gst_tensor_sparse_enc_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Getter for tensor_sparse_enc properties.
Definition: gsttensor_sparseenc.c:207
PROP_0
@ PROP_0
Definition: gsttensor_sparseenc.c:55
gst_tensors_config_from_structure
gboolean gst_tensors_config_from_structure(GstTensorsConfig *config, const GstStructure *structure)
Parse structure and set tensors config (for other/tensors)
Definition: nnstreamer_plugin_api_impl.c:1413
_GstTensorSparseEnc
GstTensorSparseEnc data structure.
Definition: gsttensor_sparseenc.h:39
gst_tensor_buffer_append_memory
gboolean gst_tensor_buffer_append_memory(GstBuffer *buffer, GstMemory *memory, const GstTensorInfo *info)
Append memory to given buffer.
Definition: nnstreamer_plugin_api_impl.c:1666
gst_tensor_sparse_enc_sink_event
static gboolean gst_tensor_sparse_enc_sink_event(GstPad *pad, GstObject *parent, GstEvent *event)
This function handles sink pad event.
Definition: gsttensor_sparseenc.c:254
gsttensor_sparseenc.h
GStreamer element to encode sparse tensors into dense tensors.