Doxygen Book
gsttensor_sparsedec.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-only */
33 #ifdef HAVE_CONFIG_H
34 #include <config.h>
35 #endif
36 
37 #include <string.h>
38 #include <nnstreamer_util.h>
39 #include "gsttensor_sparsedec.h"
40 
44 #ifndef DBG
45 #define DBG (!self->silent)
46 #endif
47 
48 GST_DEBUG_CATEGORY_STATIC (gst_tensor_sparse_dec_debug);
49 #define GST_CAT_DEFAULT gst_tensor_sparse_dec_debug
50 
54 enum
55 {
58 };
59 
63 #define DEFAULT_SILENT TRUE
64 
68 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
69  GST_PAD_SINK,
70  GST_PAD_ALWAYS,
71  GST_STATIC_CAPS (GST_TENSORS_SPARSE_CAP_DEFAULT));
72 
76 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
77  GST_PAD_SRC,
78  GST_PAD_ALWAYS,
79  GST_STATIC_CAPS (GST_TENSORS_CAP_DEFAULT));
80 
81 #define gst_tensor_sparse_dec_parent_class parent_class
82 G_DEFINE_TYPE (GstTensorSparseDec, gst_tensor_sparse_dec, GST_TYPE_ELEMENT);
83 
84 static void gst_tensor_sparse_dec_finalize (GObject * object);
85 static void gst_tensor_sparse_dec_set_property (GObject * object, guint prop_id,
86  const GValue * value, GParamSpec * pspec);
87 static void gst_tensor_sparse_dec_get_property (GObject * object, guint prop_id,
88  GValue * value, GParamSpec * pspec);
89 static GstFlowReturn
90 gst_tensor_sparse_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf);
91 static gboolean
92 gst_tensor_sparse_dec_sink_event (GstPad * pad, GstObject * parent,
93  GstEvent * event);
94 static gboolean gst_tensor_sparse_dec_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_dec_debug, "tensor_sparse_dec", 0,
107  "Element to decode sparse tensors");
108 
109  object_class = (GObjectClass *) klass;
110  element_class = (GstElementClass *) klass;
111 
112  object_class->set_property = gst_tensor_sparse_dec_set_property;
113  object_class->get_property = gst_tensor_sparse_dec_get_property;
114  object_class->finalize = gst_tensor_sparse_dec_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  gst_element_class_add_pad_template (element_class,
128  gst_static_pad_template_get (&sink_template));
129 
130  gst_element_class_set_static_metadata (element_class,
131  "TensorSparseDec",
132  "Filter/Tensor",
133  "Element to decode dense tensors into sparse tensors",
134  "Samsung Electronics Co., Ltd.");
135 }
136 
140 static void
142 {
143  /* setup sink pad */
144  self->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
145  gst_element_add_pad (GST_ELEMENT (self), self->sinkpad);
146 
147  /* setup src pad */
148  self->srcpad = gst_pad_new_from_static_template (&src_template, "src");
149  gst_element_add_pad (GST_ELEMENT (self), self->srcpad);
150 
151  /* setup chain function */
152  gst_pad_set_chain_function (self->sinkpad,
153  GST_DEBUG_FUNCPTR (gst_tensor_sparse_dec_chain));
154 
155  /* setup event function */
156  gst_pad_set_event_function (self->sinkpad,
157  GST_DEBUG_FUNCPTR (gst_tensor_sparse_dec_sink_event));
158 
159  gst_pad_set_query_function (self->sinkpad,
160  GST_DEBUG_FUNCPTR (gst_tensor_sparse_dec_sink_query));
161 
162  /* init properties */
163  self->silent = DEFAULT_SILENT;
164  gst_tensors_config_init (&self->in_config);
165  gst_tensors_config_init (&self->out_config);
166 }
167 
171 static void
173 {
174  GstTensorSparseDec *self;
175  self = GST_TENSOR_SPARSE_DEC (object);
176 
177  gst_tensors_config_free (&self->in_config);
178  gst_tensors_config_free (&self->out_config);
179 
180  G_OBJECT_CLASS (parent_class)->finalize (object);
181 }
182 
186 static void
187 gst_tensor_sparse_dec_set_property (GObject * object, guint prop_id,
188  const GValue * value, GParamSpec * pspec)
189 {
190  GstTensorSparseDec *self;
191 
192  self = GST_TENSOR_SPARSE_DEC (object);
193 
194  switch (prop_id) {
195  case PROP_SILENT:
196  self->silent = g_value_get_boolean (value);
197  break;
198  default:
199  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
200  break;
201  }
202 }
203 
207 static void
208 gst_tensor_sparse_dec_get_property (GObject * object, guint prop_id,
209  GValue * value, GParamSpec * pspec)
210 {
211  GstTensorSparseDec *self;
212 
213  self = GST_TENSOR_SPARSE_DEC (object);
214 
215  switch (prop_id) {
216  case PROP_SILENT:
217  g_value_set_boolean (value, self->silent);
218  break;
219  default:
220  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
221  break;
222  }
223 }
224 
228 static GstCaps *
230  GstCaps * filter)
231 {
232  GstCaps *caps;
233 
234  caps = gst_pad_get_current_caps (pad);
235  if (!caps) {
237  caps = gst_pad_get_pad_template_caps (pad);
238  }
239 
240  silent_debug_caps (self, caps, "caps");
241  silent_debug_caps (self, filter, "filter");
242 
243  if (filter) {
244  GstCaps *intersection;
245  intersection =
246  gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
247 
248  gst_caps_unref (caps);
249  caps = intersection;
250  }
251 
252  silent_debug_caps (self, caps, "result");
253  return caps;
254 }
255 
259 static gboolean
260 gst_tensor_sparse_dec_sink_query (GstPad * pad, GstObject * parent,
261  GstQuery * query)
262 {
263  GstTensorSparseDec *self;
264  self = GST_TENSOR_SPARSE_DEC (parent);
265 
266  GST_DEBUG_OBJECT (self, "Received %s query: %" GST_PTR_FORMAT,
267  GST_QUERY_TYPE_NAME (query), query);
268 
269  switch (GST_QUERY_TYPE (query)) {
270  case GST_QUERY_CAPS:
271  {
272  GstCaps *caps;
273  GstCaps *filter;
274 
275  gst_query_parse_caps (query, &filter);
276  caps = gst_tensor_sparse_dec_query_caps (self, pad, filter);
277  silent_debug_caps (self, filter, "filter");
278  silent_debug_caps (self, caps, "caps");
279  gst_query_set_caps_result (query, caps);
280  gst_caps_unref (caps);
281  return TRUE;
282  }
283  case GST_QUERY_ACCEPT_CAPS:
284  {
285  GstCaps *caps;
286  GstCaps *template_caps;
287  gboolean res = FALSE;
288 
289  gst_query_parse_accept_caps (query, &caps);
290  silent_debug_caps (self, caps, "caps");
291 
292  if (gst_caps_is_fixed (caps)) {
293  template_caps = gst_pad_get_pad_template_caps (pad);
294 
295  res = gst_caps_can_intersect (template_caps, caps);
296  gst_caps_unref (template_caps);
297  }
298 
299  gst_query_set_accept_caps_result (query, res);
300  return TRUE;
301  }
302  default:
303  break;
304  }
305 
306  return gst_pad_query_default (pad, parent, query);
307 }
308 
312 static gboolean
313 gst_tensor_sparse_dec_sink_event (GstPad * pad, GstObject * parent,
314  GstEvent * event)
315 {
316  GstTensorSparseDec *self;
317  self = GST_TENSOR_SPARSE_DEC (parent);
318  g_return_val_if_fail (event != NULL, FALSE);
319 
320  switch (GST_EVENT_TYPE (event)) {
321  case GST_EVENT_CAPS:
322  {
323  GstCaps *caps, *out_caps;
324  GstStructure *structure;
325 
326  gst_event_parse_caps (event, &caps);
327  silent_debug_caps (self, caps, "caps");
328 
329  /* set in_config */
330  structure = gst_caps_get_structure (caps, 0);
331  gst_tensors_config_from_structure (&self->in_config, structure);
332 
333  /* set out_config as srcpad's peer */
334  gst_tensors_config_from_peer (self->srcpad, &self->out_config, NULL);
335  self->out_config.rate_n = self->in_config.rate_n;
336  self->out_config.rate_d = self->in_config.rate_d;
337 
338  out_caps = gst_tensor_pad_caps_from_config (self->srcpad,
339  &self->out_config);
340 
341  silent_debug_caps (self, out_caps, "out_caps");
342  gst_pad_set_caps (self->srcpad, out_caps);
343  gst_caps_unref (out_caps);
344 
345  gst_event_unref (event);
346  return TRUE;
347  }
348  default:
349  break;
350  }
351 
352  return gst_pad_event_default (pad, parent, event);
353 }
354 
358 static GstFlowReturn
359 gst_tensor_sparse_dec_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
360 {
361  GstFlowReturn ret = GST_FLOW_ERROR;
362  GstTensorSparseDec *self = GST_TENSOR_SPARSE_DEC (parent);
363  GstTensorMetaInfo meta;
364  GstMemory *in_mem, *out_mem;
365  GstBuffer *outbuf;
366  GstTensorsInfo info;
367  GstTensorInfo *_info;
368  guint i;
369 
370  UNUSED (pad);
371 
372  buf = gst_tensor_buffer_from_config (buf, &self->in_config);
373  outbuf = gst_buffer_new ();
374 
375  gst_tensors_info_init (&info);
377 
378  for (i = 0; i < info.num_tensors; ++i) {
379  in_mem = gst_tensor_buffer_get_nth_memory (buf, i);
380  out_mem = gst_tensor_sparse_to_dense (&meta, in_mem);
381  gst_memory_unref (in_mem);
382 
383  if (!out_mem) {
384  nns_loge ("failed to convert to dense tensor");
385  goto done;
386  }
387 
388  _info = gst_tensors_info_get_nth_info (&info, i);
389  gst_tensor_meta_info_convert (&meta, _info);
390  gst_tensor_buffer_append_memory (outbuf, out_mem, _info);
391  }
392 
393  /* check the decoded tensor with negotiated config when it's valid */
394  if (gst_tensors_config_validate (&self->out_config)) {
395  if (!gst_tensors_info_is_equal (&self->out_config.info, &info)) {
396  /* if it's not compatible with downstream, do not send the buffer */
398  gst_buffer_unref (outbuf);
399  ret = GST_FLOW_OK;
400  goto done;
401  }
402  }
403 
404  ret = gst_pad_push (self->srcpad, outbuf);
405 
406 done:
407  gst_buffer_unref (buf);
408  if (ret != GST_FLOW_OK)
409  gst_buffer_unref (outbuf);
410 
411  return ret;
412 }
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorSparseDec, gst_tensor_sparse_dec, GST_TYPE_ELEMENT)
gst_tensor_sparse_dec_finalize
static void gst_tensor_sparse_dec_finalize(GObject *object)
Function to finalize instance.
Definition: gsttensor_sparsedec.c:172
gst_tensor_sparse_dec_query_caps
static GstCaps * gst_tensor_sparse_dec_query_caps(GstTensorSparseDec *self, GstPad *pad, GstCaps *filter)
Get pad caps for caps negotiation.
Definition: gsttensor_sparsedec.c:229
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
GstTensorInfo
Internal data structure for tensor info.
Definition: tensor_typedef.h:261
gst_tensor_sparse_dec_sink_event
static gboolean gst_tensor_sparse_dec_sink_event(GstPad *pad, GstObject *parent, GstEvent *event)
This function handles sink pad event.
Definition: gsttensor_sparsedec.c:313
FALSE
return FALSE
Definition: gsttensor_transform.c:590
gst_tensor_sparse_dec_set_property
static void gst_tensor_sparse_dec_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Setter for tensor_sparse_dec properties.
Definition: gsttensor_sparsedec.c:187
GstTensorsInfo
Internal meta data exchange format for a other/tensors instance.
Definition: tensor_typedef.h:273
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_sparse_dec_debug)
gst_tensors_config_from_peer
gboolean gst_tensors_config_from_peer(GstPad *pad, GstTensorsConfig *config, gboolean *is_fixed)
Parse caps from peer pad and set tensors config.
Definition: nnstreamer_plugin_api_impl.c:1041
DEFAULT_SILENT
#define DEFAULT_SILENT
Flag to print minimized log.
Definition: gsttensor_sparsedec.c:63
gst_tensor_sparse_dec_chain
static GstFlowReturn gst_tensor_sparse_dec_chain(GstPad *pad, GstObject *parent, GstBuffer *buf)
Internal function to transform the input buffer.
Definition: gsttensor_sparsedec.c:359
sink_template
static GstStaticPadTemplate sink_template
Template for sink pad.
Definition: gsttensor_sparsedec.c:68
gst_tensor_pad_caps_from_config
GstCaps * gst_tensor_pad_caps_from_config(GstPad *pad, const GstTensorsConfig *config)
Get pad caps from tensors config and caps of the peer connected to the pad.
Definition: nnstreamer_plugin_api_impl.c:1209
gst_tensors_info_init
void gst_tensors_info_init(GstTensorsInfo *info)
Initialize the tensors info structure.
Definition: nnstreamer_plugin_api_util_impl.c:325
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_sparsedec.c:57
GstTensorMetaInfo
Data structure to describe a tensor data. This represents the basic information of a memory block for...
Definition: tensor_typedef.h:310
gst_tensor_sparse_dec_init
static void gst_tensor_sparse_dec_init(GstTensorSparseDec *self)
Initialize tensor_sparse_dec element.
Definition: gsttensor_sparsedec.c:141
gst_tensor_sparse_dec_sink_query
static gboolean gst_tensor_sparse_dec_sink_query(GstPad *pad, GstObject *parent, GstQuery *query)
This function handles sink pad query.
Definition: gsttensor_sparsedec.c:260
GST_TENSOR_SPARSE_DEC
#define GST_TENSOR_SPARSE_DEC(obj)
Definition: gsttensor_sparsedec.h:24
gsttensor_sparsedec.h
GStreamer element to decode sparse tensors into dense tensors.
gst_tensor_sparse_dec_get_property
static void gst_tensor_sparse_dec_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Getter for tensor_sparse_dec properties.
Definition: gsttensor_sparsedec.c:208
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
_GstTensorSparseDec
GstTensorSparseDec data structure.
Definition: gsttensor_sparsedec.h:39
_GstTensorSparseDecClass
GstTensorSparseClass data structure.
Definition: gsttensor_sparsedec.h:54
gst_tensor_meta_info_convert
gboolean gst_tensor_meta_info_convert(GstTensorMetaInfo *meta, GstTensorInfo *info)
Convert GstTensorMetaInfo structure to GstTensorInfo.
Definition: nnstreamer_plugin_api_util_impl.c:1562
silent_debug_caps
#define silent_debug_caps(self, caps, msg)
Macro for capability debug message.
Definition: tensor_common.h:285
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
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
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
PROP_0
@ PROP_0
Definition: gsttensor_sparsedec.c:56
gst_tensors_info_is_equal
gboolean gst_tensors_info_is_equal(const GstTensorsInfo *i1, const GstTensorsInfo *i2)
Compare tensors info.
Definition: nnstreamer_plugin_api_util_impl.c:454
src_template
static GstStaticPadTemplate src_template
Template for src pad.
Definition: gsttensor_sparsedec.c:76
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_buffer_get_count
guint gst_tensor_buffer_get_count(GstBuffer *buffer)
Get the number of tensors in the buffer.
Definition: nnstreamer_plugin_api_impl.c:1813
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_to_dense
GstMemory * gst_tensor_sparse_to_dense(GstTensorMetaInfo *meta, GstMemory *mem)
Make dense tensor with input sparse tensor.
Definition: gsttensor_sparseutil.c:27
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
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_dec_class_init
static void gst_tensor_sparse_dec_class_init(GstTensorSparseDecClass *klass)
Initialize the tensor_sparse's class.
Definition: gsttensor_sparsedec.c:101