Doxygen Book
gsttensor_if.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: LGPL-2.1-only */
67 #ifdef HAVE_CONFIG_H
68 #include <config.h>
69 #endif
70 
71 #include <nnstreamer_log.h>
72 #include <string.h>
73 
74 #include <nnstreamer_subplugin.h>
75 #include <nnstreamer_util.h>
76 #include "gsttensor_if.h"
77 
81 #ifndef DBG
82 #define DBG (!tensor_if->silent)
83 #endif
84 
88 enum
89 {
100 };
101 
102 GST_DEBUG_CATEGORY_STATIC (gst_tensor_if_debug);
103 #define GST_CAT_DEFAULT gst_tensor_if_debug
104 
105 #define CAPS_STRING GST_TENSOR_CAP_DEFAULT "; " GST_TENSORS_CAP_DEFAULT
106 
109 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
110  GST_PAD_SINK,
111  GST_PAD_ALWAYS,
112  GST_STATIC_CAPS (CAPS_STRING));
113 
117 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
118  GST_PAD_SRC,
119  GST_PAD_SOMETIMES,
120  GST_STATIC_CAPS (CAPS_STRING));
121 
122 #define gst_tensor_if_parent_class parent_class
123 G_DEFINE_TYPE (GstTensorIf, gst_tensor_if, GST_TYPE_ELEMENT);
124 
125 /* GObject vmethod implementations */
126 static void gst_tensor_if_set_property (GObject * object, guint prop_id,
127  const GValue * value, GParamSpec * pspec);
128 static void gst_tensor_if_get_property (GObject * object, guint prop_id,
129  GValue * value, GParamSpec * pspec);
130 
131 static GstFlowReturn gst_tensor_if_chain (GstPad * pad, GstObject * parent,
132  GstBuffer * buf);
133 static gboolean gst_tensor_if_event (GstPad * pad, GstObject * parent,
134  GstEvent * event);
135 static void gst_tensor_if_dispose (GObject * object);
136 
137 static void gst_tensor_if_install_properties (GObjectClass * gobject_class);
138 
139 #define GST_TYPE_TENSOR_IF_CV (gst_tensor_if_cv_get_type ())
140 
144 static GType
146 {
147  static GType mode_type = 0;
148 
149  if (mode_type == 0) {
150  static GEnumValue mode_types[] = {
151  {TIFCV_A_VALUE, "A_VALUE", "Decide based on a single scalar value"},
152  {TIFCV_TENSOR_AVERAGE_VALUE, "TENSOR_AVERAGE_VALUE",
153  "Decide based on a average value of a specific tensor"},
154  {TIFCV_CUSTOM, "CUSTOM", "Decide based on a user defined callback"},
155  {0, NULL, NULL},
156  };
157  mode_type = g_enum_register_static ("tensor_if_compared_value", mode_types);
158  }
159 
160  return mode_type;
161 }
162 
163 #define GST_TYPE_TENSOR_IF_OP (gst_tensor_if_op_get_type ())
164 
168 static GType
170 {
171  static GType mode_type = 0;
172 
173  if (mode_type == 0) {
174  static GEnumValue mode_types[] = {
175  {TIFOP_EQ, "EQ", "eqaual"},
176  {TIFOP_NE, "NE", "not_eqaual"},
177  {TIFOP_GT, "GT", "greater_than"},
178  {TIFOP_GE, "GE", "greater_or_equal"},
179  {TIFOP_LT, "LT", "less_than"},
180  {TIFOP_LE, "LE", "less_or_equal"},
181  {TIFOP_RANGE_INCLUSIVE, "RANGE_INCLUSIVE", "range inclusive"},
182  {TIFOP_RANGE_EXCLUSIVE, "RANGE_EXCLUSIVE", "range exclusive"},
183  {TIFOP_NOT_IN_RANGE_INCLUSIVE, "NOT_IN_RANGE_INCLUSIVE",
184  "not in range inclusive"},
185  {TIFOP_NOT_IN_RANGE_EXCLUSIVE, "NOT_IN_RANGE_EXCLUSIVE",
186  "not in range exclusive"},
187  {0, NULL, NULL},
188  };
189  mode_type = g_enum_register_static ("tensor_if_operator", mode_types);
190  }
191 
192  return mode_type;
193 }
194 
195 #define GST_TYPE_TENSOR_IF_ACT (gst_tensor_if_act_get_type ())
196 
200 static GType
202 {
203  static GType mode_type = 0;
204 
205  if (mode_type == 0) {
206  static GEnumValue mode_types[] = {
207  {TIFB_PASSTHROUGH, "PASSTHROUGH", "passthrough"},
208  {TIFB_SKIP, "SKIP", "skip"},
209  {TIFB_TENSORPICK, "TENSORPICK", "tensorpick"},
210  {0, NULL, NULL},
211  };
212  mode_type = g_enum_register_static ("tensor_if_behavior", mode_types);
213  }
214 
215  return mode_type;
216 }
217 
221 static void
223 {
224  GObjectClass *gobject_class;
225  GstElementClass *gstelement_class;
226 
227  GST_DEBUG_CATEGORY_INIT (gst_tensor_if_debug, "tensor_if", 0,
228  "Tensor if to control streams based on tensor(s) values");
229 
230  gobject_class = (GObjectClass *) klass;
231  gstelement_class = (GstElementClass *) klass;
232 
233  parent_class = g_type_class_peek_parent (klass);
234 
235  gobject_class->set_property = gst_tensor_if_set_property;
236  gobject_class->get_property = gst_tensor_if_get_property;
237  gobject_class->dispose = gst_tensor_if_dispose;
238 
239  gst_tensor_if_install_properties (gobject_class);
240 
241  gst_element_class_set_details_simple (gstelement_class,
242  "TensorIf",
243  "Filter/Tensor",
244  "Controls streams based on the tensor(s) values",
245  "MyungJoo Ham <myungjoo.ham@samsung.com>");
246 
247  gst_element_class_add_pad_template (gstelement_class,
248  gst_static_pad_template_get (&src_factory));
249  gst_element_class_add_pad_template (gstelement_class,
250  gst_static_pad_template_get (&sink_factory));
251 }
252 
259 static void
261 {
262  tensor_if->silent = TRUE;
263  gst_tensors_config_init (&tensor_if->in_config);
264  gst_tensors_config_init (&tensor_if->out_config[0]);
265  gst_tensors_config_init (&tensor_if->out_config[1]);
266 
267  tensor_if->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
268  gst_element_add_pad (GST_ELEMENT_CAST (tensor_if), tensor_if->sinkpad);
269  gst_pad_set_chain_function (tensor_if->sinkpad,
270  GST_DEBUG_FUNCPTR (gst_tensor_if_chain));
271  gst_pad_set_event_function (tensor_if->sinkpad,
272  GST_DEBUG_FUNCPTR (gst_tensor_if_event));
273 
274  tensor_if->num_srcpads = 0;
275  tensor_if->srcpads = NULL;
276  tensor_if->cv_option = NULL;
277  tensor_if->then_option = NULL;
278  tensor_if->else_option = NULL;
279  memset (tensor_if->sv, 0, sizeof (tensor_if_sv_s) * 2);
280  memset (&tensor_if->custom, 0, sizeof (custom_cb_s));
281  tensor_if->custom_configured = FALSE;
282 
283  g_mutex_init (&tensor_if->lock);
284 }
285 
289 static void
291 {
292  while (tensor_if->srcpads != NULL) {
293  GstTensorPad *tensor_pad = tensor_if->srcpads->data;
294  gst_element_remove_pad (GST_ELEMENT (tensor_if), tensor_pad->pad);
295  g_free (tensor_pad);
296  tensor_if->srcpads =
297  g_slist_delete_link (tensor_if->srcpads, tensor_if->srcpads);
298  }
299  tensor_if->srcpads = NULL;
300  tensor_if->num_srcpads = 0;
301 }
302 
306 static void
307 gst_tensor_if_dispose (GObject * object)
308 {
309  GstTensorIf *tensor_if = GST_TENSOR_IF (object);
310  g_mutex_clear (&tensor_if->lock);
311 
312  gst_tensor_if_remove_src_pads (tensor_if);
313  g_list_free (tensor_if->cv_option);
314  g_list_free (tensor_if->then_option);
315  g_list_free (tensor_if->else_option);
316  g_free (tensor_if->custom.name);
317  tensor_if->custom.func = NULL;
318  tensor_if->custom.data = NULL;
319  tensor_if->custom_configured = FALSE;
320 
321  G_OBJECT_CLASS (parent_class)->dispose (object);
322 }
323 
327 static void
328 gst_tensor_if_set_property_glist (const GValue * value, GList ** prop_list,
329  const gchar * delimiters)
330 {
331  gint64 val;
332  const gchar *param = g_value_get_string (value);
333  gchar **strv = g_strsplit_set (param, delimiters, -1);
334  gint i, num = g_strv_length (strv);
335 
336  g_list_free (*prop_list);
337  *prop_list = NULL;
338 
339  for (i = 0; i < num; i++) {
340  val = g_ascii_strtoll (strv[i], NULL, 10);
341  if (errno == ERANGE) {
342  ml_loge ("Overflow occurred during converting %s to a gint64 value",
343  strv[i]);
344  }
345  *prop_list = g_list_append (*prop_list, GINT_TO_POINTER (val));
346  }
347  g_strfreev (strv);
348 }
349 
353 static void
354 gst_tensor_if_set_property_cv_option (const GValue * value, GList ** prop_list)
355 {
356  gint64 val;
357  gint length, i;
358  const gchar *param = g_value_get_string (value);
359  gchar **strv = g_strsplit_set (param, ",", -1);
360  GValue tmp = G_VALUE_INIT;
361 
362  length = g_strv_length (strv);
363 
364  if (length > 2) {
365  ml_loge
366  ("Invalid compared value option. It should be in the form of 'IDX_DIM0: ... :INDEX_DIM_LAST,nth-tensor'(A_VALUE) or 'nth-tensor' (TENSOR_AVERAGE_VALUE)");
367  g_strfreev (strv);
368  return;
369  }
370 
371  g_value_init (&tmp, G_TYPE_STRING);
372  g_value_set_string (&tmp, strv[0]);
373 
374  gst_tensor_if_set_property_glist (&tmp, prop_list, ":");
375 
376  /* A_VALUE */
377  if (length == 2) {
378  length = g_list_length (*prop_list);
379 
380  /* append zero value for undefined dimensions */
381  for (i = length; i < NNS_TENSOR_RANK_LIMIT; i++) {
382  *prop_list = g_list_append (*prop_list, GINT_TO_POINTER (0));
383  }
384 
385  val = g_ascii_strtoll (strv[1], NULL, 10);
386  if (errno == ERANGE) {
387  ml_loge ("Overflow occurred during converting %s to a gint64 value",
388  strv[1]);
389  }
390  *prop_list = g_list_append (*prop_list, GINT_TO_POINTER (val));
391  }
392  g_strfreev (strv);
393  g_value_reset (&tmp);
394 }
395 
399 static void
401  tensor_if_sv_s * sv, const gchar * delimiters)
402 {
403  gint i;
404  gboolean is_float = FALSE;
405  const gchar *param = g_value_get_string (value);
406  gchar **strv = g_strsplit_set (param, delimiters, -1);
407  gint num = g_strv_length (strv);
408 
409  if (!param) {
410  ml_loge ("Invalid supplied value. The value is NULL.");
411  return;
412  }
413 
414  if (strchr (param, '.') || strchr (param, 'E') || strchr (param, 'e')) {
415  is_float = TRUE;
416  }
417 
418  sv->num = num;
419  for (i = 0; i < num; i++) {
420  if (is_float) {
421  sv->type = _NNS_FLOAT64;
422  sv->data[i]._double = g_ascii_strtod (strv[i], NULL);
423  } else {
424  sv->type = _NNS_INT64;
425  sv->data[i]._int64_t = g_ascii_strtoll (strv[i], NULL, 10);
426  }
427  }
428  g_strfreev (strv);
429 }
430 
434 static void
436 {
437  if (!self->custom.name)
438  return;
439 
440  if (self->cv == TIFCV_CUSTOM) {
441  const custom_cb_s *ptr = get_subplugin (NNS_IF_CUSTOM, self->custom.name);
442  if (!ptr) {
443  nns_logw ("Failed to find custom subplugin of the tensor_if");
444  return;
445  }
446  self->custom_configured = TRUE;
447  self->custom.func = (*ptr).func;
448  self->custom.data = (*ptr).data;
449  }
450 }
451 
455 static void
456 gst_tensor_if_set_property (GObject * object, guint prop_id,
457  const GValue * value, GParamSpec * pspec)
458 {
459  GstTensorIf *self = GST_TENSOR_IF (object);
460 
461  switch (prop_id) {
462  case PROP_CV:
463  self->cv = g_value_get_enum (value);
465  break;
466  case PROP_CV_OPTION:
467  g_free (self->custom.name);
468  self->custom.name = g_value_dup_string (value);
470  gst_tensor_if_set_property_cv_option (value, &self->cv_option);
471  break;
472  case PROP_OP:
473  self->op = g_value_get_enum (value);
474  break;
475  case PROP_SV:
476  gst_tensor_if_set_property_supplied_value (value, self->sv, ",");
477  break;
478  case PROP_THEN:
479  self->act_then = g_value_get_enum (value);
480  break;
481  case PROP_THEN_OPTION:
482  gst_tensor_if_set_property_glist (value, &self->then_option, ",");
483  break;
484  case PROP_ELSE:
485  self->act_else = g_value_get_enum (value);
486  break;
487  case PROP_ELSE_OPTION:
488  gst_tensor_if_set_property_glist (value, &self->else_option, ",");
489  break;
490  case PROP_SILENT:
491  self->silent = g_value_get_boolean (value);
492  break;
493  default:
494  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
495  break;
496  }
497 }
498 
502 static void
503 gst_tensor_if_property_to_string (GValue * value, GList * prop_list,
504  guint prop_id)
505 {
506  GList *list;
507  gchar *p;
508  GPtrArray *arr;
509  gchar **strings;
510  guint len;
511 
512  if (prop_list == NULL) {
513  g_value_set_string (value, "");
514  return;
515  }
516 
517  arr = g_ptr_array_new ();
518  for (list = prop_list; list != NULL; list = list->next) {
519  g_ptr_array_add (arr, g_strdup_printf ("%i", GPOINTER_TO_INT (list->data)));
520  }
521  g_ptr_array_add (arr, NULL);
522 
523  len = arr->len;
524 
525  if (prop_id == PROP_CV_OPTION && len % (NNS_TENSOR_RANK_LIMIT + 2) == 0) {
526  gchar *dim;
527  gchar *tensor = (gchar *) g_ptr_array_index (arr, len - 2);
528  g_ptr_array_remove_index (arr, len - 2);
529  strings = (gchar **) g_ptr_array_free (arr, FALSE);
530  dim = g_strjoinv (":", strings);
531  p = g_strjoin (",", dim, tensor, NULL);
532  g_free (dim);
533  g_free (tensor);
534  } else {
535  strings = (gchar **) g_ptr_array_free (arr, FALSE);
536  p = g_strjoinv (",", strings);
537  }
538 
539  g_strfreev (strings);
540  g_value_take_string (value, p);
541 }
542 
546 static void
548 {
549  guint i;
550  gchar *p;
551  GPtrArray *arr;
552  gchar **strings;
553 
554  if (sv == NULL || sv->num == 0) {
555  g_value_set_string (value, "");
556  return;
557  }
558 
559  arr = g_ptr_array_new ();
560  for (i = 0; i < sv->num; i++) {
561  if (sv->type == _NNS_FLOAT64) {
562  g_ptr_array_add (arr, g_strdup_printf ("%lf", sv->data[i]._double));
563  } else {
564  g_ptr_array_add (arr, g_strdup_printf ("%ld",
565  (long int) sv->data[i]._int64_t));
566  }
567  }
568  g_ptr_array_add (arr, NULL);
569  strings = (gchar **) g_ptr_array_free (arr, FALSE);
570  p = g_strjoinv (",", strings);
571  g_strfreev (strings);
572  g_value_take_string (value, p);
573 }
574 
578 static void
579 gst_tensor_if_get_property (GObject * object, guint prop_id,
580  GValue * value, GParamSpec * pspec)
581 {
582  GstTensorIf *self = GST_TENSOR_IF (object);
583 
584  switch (prop_id) {
585  case PROP_CV:
586  g_value_set_enum (value, self->cv);
587  break;
588  case PROP_CV_OPTION:
589  if (self->cv == TIFCV_CUSTOM) {
590  g_value_set_string (value, self->custom.name ? self->custom.name : "");
591  } else {
592  gst_tensor_if_property_to_string (value, self->cv_option, prop_id);
593  }
594  break;
595  case PROP_OP:
596  g_value_set_enum (value, self->op);
597  break;
598  case PROP_SV:
600  break;
601  case PROP_THEN:
602  g_value_set_enum (value, self->act_then);
603  break;
604  case PROP_THEN_OPTION:
605  gst_tensor_if_property_to_string (value, self->then_option, prop_id);
606  break;
607  case PROP_ELSE:
608  g_value_set_enum (value, self->act_else);
609  break;
610  case PROP_ELSE_OPTION:
611  gst_tensor_if_property_to_string (value, self->else_option, prop_id);
612  break;
613  case PROP_SILENT:
614  g_value_set_boolean (value, self->silent);
615  break;
616  default:
617  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
618  break;
619  }
620 }
621 
626 static void
627 gst_tensor_if_install_properties (GObjectClass * gobject_class)
628 {
629  g_object_class_install_property (gobject_class, PROP_SILENT,
630  g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
631  FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
632 
633  g_object_class_install_property (gobject_class, PROP_CV,
634  g_param_spec_enum ("compared-value", "CV",
635  "Compared value from input tensor(s)", GST_TYPE_TENSOR_IF_CV,
636  TIFCV_A_VALUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
637 
638  g_object_class_install_property (gobject_class, PROP_CV_OPTION,
639  g_param_spec_string ("compared-value-option", "CV_OPTION",
640  "Specify an element of the nth tensor or pick tensor ", "",
641  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
642 
643  g_object_class_install_property (gobject_class, PROP_SV,
644  g_param_spec_string ("supplied-value", "SV",
645  " Supplied Value by user ", "",
646  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
647 
648  g_object_class_install_property (gobject_class, PROP_OP,
649  g_param_spec_enum ("operator", "OP", "Comparison Operator",
651  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
652 
653  g_object_class_install_property (gobject_class, PROP_THEN,
654  g_param_spec_enum ("then", "THEN", "Action if it is TRUE",
656  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
657 
658  g_object_class_install_property (gobject_class, PROP_THEN_OPTION,
659  g_param_spec_string ("then-option", "THEN_OPTION",
660  "Pick tensor ", "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
661 
662  g_object_class_install_property (gobject_class, PROP_ELSE,
663  g_param_spec_enum ("else", "ELSE", "Action if it is FALSE",
665  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
666 
667  g_object_class_install_property (gobject_class, PROP_ELSE_OPTION,
668  g_param_spec_string ("else-option", "ELSE_OPTION",
669  "Pick tensor ", "", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
670 }
671 
678 static gboolean
679 gst_tensor_if_parse_caps (GstTensorIf * tensor_if, GstCaps * caps)
680 {
681  GstStructure *structure;
682  GstTensorsConfig *config;
683 
684  config = &tensor_if->in_config;
685  structure = gst_caps_get_structure (caps, 0);
686  gst_tensors_config_from_structure (config, structure);
687 
688  return gst_tensors_config_validate (config);
689 }
690 
694 static gboolean
695 gst_tensor_if_event (GstPad * pad, GstObject * parent, GstEvent * event)
696 {
697  GstTensorIf *tensor_if;
698  tensor_if = GST_TENSOR_IF (parent);
699 
700  switch (GST_EVENT_TYPE (event)) {
701  case GST_EVENT_CAPS:
702  {
703  GstCaps *caps;
704  gst_event_parse_caps (event, &caps);
705  if (!gst_tensor_if_parse_caps (tensor_if, caps)) {
706  GST_ERROR_OBJECT (tensor_if, "Failed to parse caps.\n");
707  return FALSE;
708  }
709  break;
710  }
711  default:
712  break;
713  }
714 
715  return gst_pad_event_default (pad, parent, event);
716 }
717 
726 static GstTensorPad *
728  GstTensorsConfig * config, gboolean * created, guint nth)
729 {
730  GSList *walk;
731  GstPad *pad;
732  GstTensorPad *tensorpad;
733  gchar *name;
734  GstCaps *caps = NULL;
735 
736  walk = tensor_if->srcpads;
737  while (walk) {
738  GstTensorPad *pad = (GstTensorPad *) walk->data;
739  if (nth == pad->nth) {
740  if (created) {
741  *created = FALSE;
742  }
743  return pad;
744  }
745  walk = walk->next;
746  }
747 
748  tensorpad = g_new0 (GstTensorPad, 1);
749  g_assert (tensorpad != NULL);
750  GST_DEBUG_OBJECT (tensor_if, "creating pad: %d(%dth)",
751  tensor_if->num_srcpads, nth);
752 
753  name = g_strdup_printf ("src_%d", nth);
754  pad = gst_pad_new_from_static_template (&src_factory, name);
755  g_free (name);
756 
757  tensorpad->pad = pad;
758  tensorpad->nth = nth;
759  tensorpad->last_ret = GST_FLOW_OK;
760  tensorpad->last_ts = GST_CLOCK_TIME_NONE;
761 
762  tensor_if->srcpads = g_slist_append (tensor_if->srcpads, tensorpad);
763  tensor_if->num_srcpads++;
764 
765  gst_pad_use_fixed_caps (pad);
766  gst_pad_set_active (pad, TRUE);
767  gst_element_add_pad (GST_ELEMENT_CAST (tensor_if), pad);
768 
769  caps = gst_tensor_pad_caps_from_config (pad, config);
770 
771  silent_debug_caps (tensor_if, caps, "out caps");
772  gst_pad_set_caps (pad, caps);
773 
774  gst_caps_unref (caps);
775 
776  if (created) {
777  *created = TRUE;
778  }
779 
780  return tensorpad;
781 }
782 
790 static GstFlowReturn
792  GstTensorPad * pad, GstFlowReturn ret)
793 {
794  GSList *walk;
795  pad->last_ret = ret;
796 
797  if (ret != GST_FLOW_NOT_LINKED)
798  goto done;
799 
800  for (walk = tensor_if->srcpads; walk; walk = g_slist_next (walk)) {
801  GstTensorPad *opad = (GstTensorPad *) walk->data;
802  ret = opad->last_ret;
803  if (ret != GST_FLOW_NOT_LINKED)
804  goto done;
805  }
806 done:
807  return ret;
808 }
809 
813 #define operator_func(cv,t,op,sv1,sv2,ret) do { \
814  switch (op) { \
815  case TIFOP_EQ: ret = (cv._
816  case TIFOP_NE: ret = (cv._
817  case TIFOP_GT: ret = (cv._
818  case TIFOP_GE: ret = (cv._
819  case TIFOP_LT: ret = (cv._
820  case TIFOP_LE: ret = (cv._
821  case TIFOP_RANGE_INCLUSIVE: \
822  ret = (sv1._
823  case TIFOP_RANGE_EXCLUSIVE: \
824  ret = (sv1._
825  case TIFOP_NOT_IN_RANGE_INCLUSIVE: \
826  ret = (cv._
827  case TIFOP_NOT_IN_RANGE_EXCLUSIVE: \
828  ret = (cv._
829  default: break; \
830  } \
831 } while (0)
832 
836 static gboolean
837 gst_tensor_if_get_comparison_result (GstTensorIf * tensor_if,
838  tensor_data_s * cv, gboolean * result)
839 {
840  gboolean ret = FALSE;
842 
843  svtc_1.type = tensor_if->sv->type;
844  svtc_1.data = tensor_if->sv->data[0];
846 
847  svtc_2.type = tensor_if->sv->type;
848  svtc_2.data = tensor_if->sv->data[1];
850 
851  switch (cv->type) {
852  case _NNS_INT32:
853  operator_func (cv->data, int32_t, tensor_if->op, svtc_1.data, svtc_2.data,
854  ret);
855  break;
856  case _NNS_UINT32:
857  operator_func (cv->data, uint32_t, tensor_if->op, svtc_1.data,
858  svtc_2.data, ret);
859  break;
860  case _NNS_INT16:
861  operator_func (cv->data, int16_t, tensor_if->op, svtc_1.data, svtc_2.data,
862  ret);
863  break;
864  case _NNS_UINT16:
865  operator_func (cv->data, uint16_t, tensor_if->op, svtc_1.data,
866  svtc_2.data, ret);
867  break;
868  case _NNS_INT8:
869  operator_func (cv->data, int8_t, tensor_if->op, svtc_1.data, svtc_2.data,
870  ret);
871  break;
872  case _NNS_UINT8:
873  operator_func (cv->data, uint8_t, tensor_if->op, svtc_1.data, svtc_2.data,
874  ret);
875  break;
876  case _NNS_FLOAT64:
877  operator_func (cv->data, double, tensor_if->op, svtc_1.data, svtc_2.data,
878  ret);
879  break;
880  case _NNS_FLOAT32:
881  operator_func (cv->data, float, tensor_if->op, svtc_1.data, svtc_2.data,
882  ret);
883  break;
884  case _NNS_INT64:
885  operator_func (cv->data, int64_t, tensor_if->op, svtc_1.data, svtc_2.data,
886  ret);
887  break;
888  case _NNS_UINT64:
889  operator_func (cv->data, uint64_t, tensor_if->op, svtc_1.data,
890  svtc_2.data, ret);
891  break;
892  default:
893  GST_ERROR_OBJECT (tensor_if, "Unknown tensor type %d", cv->type);
894  return FALSE;
895  }
896  *result = ret;
897  return TRUE;
898 }
899 
903 static gboolean
905  GstBuffer * buf, tensor_data_s * cv, guint nth)
906 {
907  GstTensorInfo *_info;
908  GstMemory *in_mem;
909  GstMapInfo in_info;
910  gdouble *avg = NULL;
912 
913  in_mem = gst_tensor_buffer_get_nth_memory (buf, nth);
914  if (!gst_memory_map (in_mem, &in_info, GST_MAP_READ)) {
915  GST_WARNING_OBJECT (tensor_if, "Failed to map the input buffer.");
916  gst_memory_unref (in_mem);
917  return FALSE;
918  }
919 
920  _info = gst_tensors_info_get_nth_info (&tensor_if->in_config.info, nth);
921  type = _info->type;
922 
923  gst_tensor_data_raw_average (in_info.data, in_info.size, type, &avg);
924 
925  gst_memory_unmap (in_mem, &in_info);
926  gst_memory_unref (in_mem);
927 
930 
931  g_free (avg);
932  return TRUE;
933 }
934 
938 static gboolean
939 gst_tensor_if_calculate_cv (GstTensorIf * tensor_if, GstBuffer * buf,
940  tensor_data_s * cv)
941 {
942  GstTensorInfo *_info;
943 
944  switch (tensor_if->cv) {
945  case TIFCV_A_VALUE:
946  {
947  GstMemory *in_mem;
948  GstMapInfo in_info;
949  GList *list;
950  uint32_t idx = 0, nth, i, offset = 1;
951  tensor_dim target;
952  const uint32_t *in_dim;
953  tensor_type in_type;
954 
955  if (g_list_length (tensor_if->cv_option) != NNS_TENSOR_RANK_LIMIT + 1) {
956  GST_ERROR_OBJECT (tensor_if,
957  "Please specify a proper 'compared-value-option' property, e.g., 0:1:2:3,0");
958  return FALSE;
959  }
960  for (list = tensor_if->cv_option; list->next != NULL; list = list->next) {
961  target[idx++] = GPOINTER_TO_INT (list->data);
962  }
963 
964  nth = GPOINTER_TO_INT (list->data);
965  if (gst_tensor_buffer_get_count (buf) <= nth) {
966  GST_ERROR_OBJECT (tensor_if, "Index should be lower than buffer size");
967  return FALSE;
968  }
969 
970  _info = gst_tensors_info_get_nth_info (&tensor_if->in_config.info, nth);
971  in_type = _info->type;
972  in_dim = _info->dimension;
973 
974  in_mem = gst_tensor_buffer_get_nth_memory (buf, nth);
975  if (!gst_memory_map (in_mem, &in_info, GST_MAP_READ)) {
976  GST_WARNING_OBJECT (tensor_if, "Failed to map the input buffer.");
977  gst_memory_unref (in_mem);
978  return FALSE;
979  }
980 
981  /* Find data index for mem access */
982  idx = target[0];
983  for (i = 1; i < NNS_TENSOR_RANK_LIMIT; i++) {
984  offset *= in_dim[i - 1];
985  idx += (target[i]) * offset;
986  }
987 
988  idx *= gst_tensor_get_element_size (in_type);
989 
990  gst_tensor_data_set (cv, in_type, in_info.data + idx);
991  gst_memory_unmap (in_mem, &in_info);
992  gst_memory_unref (in_mem);
993  break;
994  }
996  {
997  uint32_t nth;
998  if (g_list_length (tensor_if->cv_option) != 1) {
999  GST_ERROR_OBJECT (tensor_if,
1000  "Please specify a proper 'compared-value-option' property, For TENSOR_AVERAGE_VALUE, specify only one tensor. Tensors is not supported.");
1001  return FALSE;
1002  }
1003  nth = GPOINTER_TO_INT (tensor_if->cv_option->data);
1004  if (gst_tensor_buffer_get_count (buf) <= nth) {
1005  GST_ERROR_OBJECT (tensor_if, "Index should be lower than buffer size");
1006  return FALSE;
1007  }
1008  return gst_tensor_if_get_tensor_average (tensor_if, buf, cv, nth);
1009  }
1010  default:
1011  GST_ERROR_OBJECT (tensor_if,
1012  "Compared value is not supported yet or not defined");
1013  return FALSE;
1014  }
1015  return TRUE;
1016 }
1017 
1022 int
1024  void *data)
1025 {
1026  custom_cb_s *ptr;
1027 
1028  g_return_val_if_fail (name && strlen (name), -EINVAL);
1029  g_return_val_if_fail (func, -EINVAL);
1030 
1031  if (!(ptr = g_try_new0 (custom_cb_s, 1)))
1032  return -ENOMEM;
1033 
1034  ptr->func = func;
1035  ptr->data = data;
1036 
1037  if (register_subplugin (NNS_IF_CUSTOM, name, ptr))
1038  return 0;
1039 
1040  g_free (ptr);
1041  return -EINVAL;
1042 }
1043 
1048 int
1050 {
1051  custom_cb_s *ptr;
1052 
1053  ptr = (custom_cb_s *) get_subplugin (NNS_IF_CUSTOM, name);
1054  if (!unregister_subplugin (NNS_IF_CUSTOM, name)) {
1055  ml_loge ("Failed to unregister custom callback %s.", name);
1056  return -EINVAL;
1057  }
1058  g_free (ptr);
1059 
1060  return 0;
1061 }
1062 
1069 static gboolean
1070 gst_tensor_if_check_condition (GstTensorIf * tensor_if, GstBuffer * buf,
1071  gboolean * result)
1072 {
1073  gboolean ret = FALSE;
1074 
1075  if (tensor_if->cv == TIFCV_CUSTOM) {
1076  GstMemory *in_mem[NNS_TENSOR_SIZE_LIMIT];
1077  GstMapInfo in_info[NNS_TENSOR_SIZE_LIMIT];
1079  guint i, j;
1080 
1081  if (!tensor_if->custom_configured) {
1082  nns_loge ("custom condition of the tensor_if is not configured.");
1083  return FALSE;
1084  }
1085 
1086  for (i = 0; i < tensor_if->in_config.info.num_tensors; i++) {
1087  in_mem[i] = gst_tensor_buffer_get_nth_memory (buf, i);
1088  if (!gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ)) {
1089  for (j = 0; j < i; j++) {
1090  gst_memory_unmap (in_mem[j], &in_info[j]);
1091  gst_memory_unref (in_mem[j]);
1092  }
1093  gst_memory_unref (in_mem[i]);
1094 
1095  GST_WARNING_OBJECT (tensor_if, "Cannot map input buffer(%d)\n", i);
1096  return FALSE;
1097  }
1098  in_tensors[i].data = in_info[i].data;
1099  in_tensors[i].size = in_info[i].size;
1100  }
1101 
1102  ret = tensor_if->custom.func (&tensor_if->in_config.info, in_tensors,
1103  tensor_if->custom.data, result);
1104 
1105  for (i = 0; i < tensor_if->in_config.info.num_tensors; i++) {
1106  gst_memory_unmap (in_mem[i], &in_info[i]);
1107  gst_memory_unref (in_mem[i]);
1108  }
1109  } else {
1110  tensor_data_s cv = {.type = _NNS_END,.data._uint8_t = 0 };
1111  if (!gst_tensor_if_calculate_cv (tensor_if, buf, &cv)) {
1112  GST_ERROR_OBJECT (tensor_if, " failed to calculate compared value");
1113  return FALSE;
1114  }
1115  ret = gst_tensor_if_get_comparison_result (tensor_if, &cv, result);
1116  }
1117 
1118  return ret;
1119 }
1120 
1124 static GstFlowReturn
1125 gst_tensor_if_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
1126 {
1127  guint num_tensors, i;
1128  GstFlowReturn res = GST_FLOW_OK;
1129  GstTensorIf *tensor_if = GST_TENSOR_IF (parent);
1130  gboolean condition_result = FALSE;
1132  tensor_if_srcpads which_srcpad = TIFSP_THEN_PAD;
1133  GList *curr_act_option = NULL;
1134  GstTensorsConfig *config;
1135  GstTensorPad *srcpad;
1136  GstBuffer *outbuf = NULL;
1137  GstMemory *mem = NULL;
1138  gboolean created;
1139  GstClockTime ts;
1140  UNUSED (pad);
1141 
1142  num_tensors = tensor_if->in_config.info.num_tensors;
1143  GST_DEBUG_OBJECT (tensor_if, " Number of Tensors: %u", num_tensors);
1144  /* supposed n memory blocks in buffer */
1145  g_assert (gst_tensor_buffer_get_count (buf) == num_tensors);
1146 
1147  if (!gst_tensor_if_check_condition (tensor_if, buf, &condition_result)) {
1148  GST_ERROR_OBJECT (tensor_if, " Failed to check condition");
1149  return GST_FLOW_ERROR;
1150  }
1151 
1152  if (condition_result) {
1153  curr_act = tensor_if->act_then;
1154  curr_act_option = tensor_if->then_option;
1155  which_srcpad = TIFSP_THEN_PAD;
1156  } else {
1157  curr_act = tensor_if->act_else;
1158  curr_act_option = tensor_if->else_option;
1159  which_srcpad = TIFSP_ELSE_PAD;
1160  }
1161 
1162  config = &tensor_if->out_config[which_srcpad];
1163 
1164  if (config->info.num_tensors == 0) {
1165  config->rate_n = tensor_if->in_config.rate_n;
1166  config->rate_d = tensor_if->in_config.rate_d;
1167  }
1168 
1169  switch (curr_act) {
1170  case TIFB_PASSTHROUGH:
1171  if (config->info.num_tensors == 0) {
1172  gst_tensors_info_copy (&config->info, &tensor_if->in_config.info);
1173  }
1174  outbuf = gst_buffer_ref (buf);
1175 
1176  break;
1177  case TIFB_TENSORPICK:
1178  {
1179  GList *list;
1180  gint info_idx = 0;
1181  GstTensorInfo *dest, *src;
1182 
1183  outbuf = gst_buffer_new ();
1184  for (list = curr_act_option; list != NULL; list = list->next) {
1185  i = GPOINTER_TO_INT (list->data);
1186  src = gst_tensors_info_get_nth_info (&tensor_if->in_config.info, i);
1187 
1188  if (config->info.num_tensors == 0) {
1189  dest = gst_tensors_info_get_nth_info (&config->info, info_idx);
1190  info_idx++;
1191 
1192  gst_tensor_info_copy (dest, src);
1193  }
1194 
1195  mem = gst_tensor_buffer_get_nth_memory (buf, i);
1196  gst_tensor_buffer_append_memory (outbuf, mem, src);
1197  }
1198  config->info.num_tensors = info_idx;
1199  break;
1200  }
1201  case TIFB_SKIP:
1202  goto done;
1203  default:
1204  GST_DEBUG_OBJECT (tensor_if, " Not defined behavior");
1205  break;
1206  }
1207 
1208  srcpad =
1209  gst_tensor_if_get_tensor_pad (tensor_if, config, &created, which_srcpad);
1210 
1211  if (created) {
1212  GstSegment segment;
1213  gst_segment_init (&segment, GST_FORMAT_TIME);
1214  gst_pad_push_event (srcpad->pad, gst_event_new_segment (&segment));
1215  }
1216 
1217  outbuf = gst_buffer_make_writable (outbuf);
1218 
1219  /* metadata from incoming buffer */
1220  gst_buffer_copy_into (outbuf, buf, GST_BUFFER_COPY_METADATA, 0, -1);
1221 
1222  ts = GST_BUFFER_TIMESTAMP (buf);
1223  if (srcpad->last_ts == GST_CLOCK_TIME_NONE || srcpad->last_ts != ts) {
1224  srcpad->last_ts = ts;
1225  } else {
1226  GST_DEBUG_OBJECT (tensor_if, "invalid timestamp %" GST_TIME_FORMAT,
1227  GST_TIME_ARGS (ts));
1228  }
1229 
1230  res = gst_pad_push (srcpad->pad, outbuf);
1231  res = gst_tensor_if_combine_flows (tensor_if, srcpad, res);
1232 
1233 done:
1234  gst_buffer_unref (buf);
1235  return res;
1236 }
_GstTensorIf::else_option
GList * else_option
Definition: gsttensor_if.h:140
cv
case tensor_data_s * cv
Definition: gsttensor_if.c:838
_GstTensorIf::sv
tensor_if_sv_s sv[2]
Definition: gsttensor_if.h:137
g_assert
g_assert(sizeof(DTYPE_UNSIGNED)==sizeof(DTYPE_SIGNED))
NNS_IF_CUSTOM
@ NNS_IF_CUSTOM
Definition: nnstreamer_subplugin.h:48
_NNS_UINT64
@ _NNS_UINT64
Definition: tensor_typedef.h:149
_GstTensorIf::silent
gboolean silent
Definition: gsttensor_if.h:127
custom_cb_s
Definition: gsttensor_if.h:112
data
svtc_1 data
Definition: gsttensor_if.c:844
GstTensorInfo
Internal data structure for tensor info.
Definition: tensor_typedef.h:261
tensor_data_s
Structure for tensor data.
Definition: tensor_data.h:23
NNS_TENSOR_SIZE_LIMIT
#define NNS_TENSOR_SIZE_LIMIT
The number of tensors NNStreamer supports is 256. The max memories of gst-buffer is 16 (See NNS_TENSO...
Definition: tensor_typedef.h:42
_NNS_INT64
@ _NNS_INT64
Definition: tensor_typedef.h:148
tensor_dim
uint32_t tensor_dim[NNS_TENSOR_RANK_LIMIT]
Definition: tensor_typedef.h:247
GstTensorPad
Internal data structure for pad in demux / split.
Definition: tensor_common.h:102
FALSE
return FALSE
Definition: gsttensor_transform.c:590
result
case tensor_data_s gboolean * result
Definition: gsttensor_if.c:839
nnstreamer_subplugin.h
Subplugin Manager for NNStreamer.
TIFB_PASSTHROUGH
@ TIFB_PASSTHROUGH
Definition: gsttensor_if.h:80
gst_tensor_if_set_property
static void gst_tensor_if_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Setter for tensor_if properties.
Definition: gsttensor_if.c:456
GstTensorMemory::data
void * data
Definition: tensor_typedef.h:254
_GstTensorIf::custom_configured
gboolean custom_configured
Definition: gsttensor_if.h:142
PROP_OP
@ PROP_OP
Definition: gsttensor_if.c:94
tensor_if_behavior
tensor_if_behavior
Behaviors that may fit in THEN and ELSE.
Definition: gsttensor_if.h:79
_NNS_UINT16
@ _NNS_UINT16
Definition: tensor_typedef.h:143
gst_tensor_if_remove_src_pads
static void gst_tensor_if_remove_src_pads(GstTensorIf *tensor_if)
function to remove srcpad list
Definition: gsttensor_if.c:290
nnstreamer_if_custom_unregister
int nnstreamer_if_custom_unregister(const gchar *name)
Unregisters a callback for tensor_if custom condition.
Definition: gsttensor_if.c:1049
TIFOP_EQ
@ TIFOP_EQ
Definition: gsttensor_if.h:61
gst_tensor_info_copy
void gst_tensor_info_copy(GstTensorInfo *dest, const GstTensorInfo *src)
Copy tensor info.
Definition: nnstreamer_plugin_api_util_impl.c:248
nnstreamer_log.h
Internal log util for NNStreamer plugins and native APIs.
custom_cb_s::name
gchar * name
Definition: gsttensor_if.h:114
PROP_CV_OPTION
@ PROP_CV_OPTION
Definition: gsttensor_if.c:93
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_TYPE_TENSOR_IF_ACT
#define GST_TYPE_TENSOR_IF_ACT
Definition: gsttensor_if.c:195
svtc_1
tensor_data_s svtc_1
Definition: gsttensor_if.c:841
tensor_element::_int64_t
int64_t _int64_t
Definition: tensor_typedef.h:240
tensor_if_sv_s::data
tensor_element data[2]
Definition: gsttensor_if.h:109
CAPS_STRING
#define CAPS_STRING
Definition: gsttensor_if.c:105
GstTensorMemory
The unit of each data tensors. It will be used as an input/output tensor of other/tensors.
Definition: tensor_typedef.h:252
gst_tensor_if_parse_caps
static gboolean gst_tensor_if_parse_caps(GstTensorIf *tensor_if, GstCaps *caps)
Parse caps and configure tensors info.
Definition: gsttensor_if.c:679
TIFB_TENSORPICK
@ TIFB_TENSORPICK
Definition: gsttensor_if.h:89
TIFCV_TENSOR_AVERAGE_VALUE
@ TIFCV_TENSOR_AVERAGE_VALUE
Definition: gsttensor_if.h:49
GstTensorsConfig::rate_d
int rate_d
Definition: tensor_typedef.h:288
TIFB_SKIP
@ TIFB_SKIP
Definition: gsttensor_if.h:81
TIFSP_ELSE_PAD
@ TIFSP_ELSE_PAD
Definition: gsttensor_if.h:99
gst_tensor_data_raw_average
gboolean gst_tensor_data_raw_average(gpointer raw, gsize length, tensor_type type, gdouble **result)
Calculate average value of the tensor.
Definition: tensor_data.c:315
_GstTensorIf::custom
custom_cb_s custom
Definition: gsttensor_if.h:143
GstTensorPad::last_ts
GstClockTime last_ts
Definition: tensor_common.h:105
_GstTensorIfClass
GstTensorIfClass inherits GstElementClass.
Definition: gsttensor_if.h:151
_GstTensorIf::out_config
GstTensorsConfig out_config[2]
Definition: gsttensor_if.h:130
gst_tensor_if_op_get_type
static GType gst_tensor_if_op_get_type(void)
A private function to register GEnumValue array for the 'operator' property to a GType and return it.
Definition: gsttensor_if.c:169
gst_tensor_if_calculate_cv
static gboolean gst_tensor_if_calculate_cv(GstTensorIf *tensor_if, GstBuffer *buf, tensor_data_s *cv)
Calculate compared value.
Definition: gsttensor_if.c:939
gst_tensor_if_install_properties
static void gst_tensor_if_install_properties(GObjectClass *gobject_class)
Installs all the properties for tensor_if.
Definition: gsttensor_if.c:627
g_free
g_free(self->option[(opnum) - 1])
opnum: \
gst_tensor_if_configure_custom_prop
static void gst_tensor_if_configure_custom_prop(GstTensorIf *self)
Set custom compared value property.
Definition: gsttensor_if.c:435
tensor_if_custom
G_BEGIN_DECLS typedef gboolean(* tensor_if_custom)(const GstTensorsInfo *info, const GstTensorMemory *input, void *user_data, gboolean *result)
Calls the user defined conditions function.
Definition: tensor_if.h:63
tensor_type
enum _nns_tensor_type tensor_type
Possible data element types of other/tensor.
_GstTensorIf
Tensor If data structure.
Definition: gsttensor_if.h:122
_GstTensorIf::in_config
GstTensorsConfig in_config
Definition: gsttensor_if.h:129
g_value_set_string
g_value_set_string(value, self->option[opnum - 1])
opnum: \
src_factory
static GstStaticPadTemplate src_factory
The capabilities of the outputs.
Definition: gsttensor_if.c:117
GstTensorsConfig::rate_n
int rate_n
Definition: tensor_typedef.h:287
_NNS_END
@ _NNS_END
Definition: tensor_typedef.h:152
gst_tensor_if_dispose
static void gst_tensor_if_dispose(GObject *object)
dispose function for tensor if (gst element vmethod)
Definition: gsttensor_if.c:307
gst_tensor_if_get_property_supplied_value
static void gst_tensor_if_get_property_supplied_value(GValue *value, tensor_if_sv_s *sv)
Convert GValue to supplied value according to delimiters.
Definition: gsttensor_if.c:547
gst_tensor_data_set
gboolean gst_tensor_data_set(tensor_data_s *td, tensor_type type, gpointer value)
Set tensor element data with given type.
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_if.c:91
GST_TYPE_TENSOR_IF_OP
#define GST_TYPE_TENSOR_IF_OP
Definition: gsttensor_if.c:163
_GstTensorIf::srcpads
GSList * srcpads
Definition: gsttensor_if.h:126
TIFOP_RANGE_INCLUSIVE
@ TIFOP_RANGE_INCLUSIVE
Definition: gsttensor_if.h:67
gst_tensor_get_element_size
gsize gst_tensor_get_element_size(tensor_type type)
Get element size of tensor type (byte per element)
Definition: nnstreamer_plugin_api_util_impl.c:1205
GstTensorMemory::size
size_t size
Definition: tensor_typedef.h:255
gst_tensor_if_get_property
static void gst_tensor_if_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Getter for tensor_if properties.
Definition: gsttensor_if.c:579
TIFOP_LT
@ TIFOP_LT
Definition: gsttensor_if.h:65
custom_cb_s::data
void * data
Definition: gsttensor_if.h:116
_NNS_FLOAT32
@ _NNS_FLOAT32
Definition: tensor_typedef.h:147
tensor_data_s::data
tensor_element data
Definition: tensor_data.h:26
register_subplugin
gboolean register_subplugin(subpluginType type, const char *name, const void *data)
Public function defined in the header.
Definition: nnstreamer_subplugin.c:225
gst_tensor_if_set_property_supplied_value
static void gst_tensor_if_set_property_supplied_value(const GValue *value, tensor_if_sv_s *sv, const gchar *delimiters)
Convert GValue to GList according to delimiters.
Definition: gsttensor_if.c:400
gst_tensor_if_combine_flows
static GstFlowReturn gst_tensor_if_combine_flows(GstTensorIf *tensor_if, GstTensorPad *pad, GstFlowReturn ret)
Check the status among sources in if.
Definition: gsttensor_if.c:791
tensor_if_sv_s
Internal data structure for supplied value.
Definition: gsttensor_if.h:105
tensor_element::_double
double _double
Definition: tensor_typedef.h:238
gst_tensor_if_cv_get_type
static GType gst_tensor_if_cv_get_type(void)
A private function to register GEnumValue array for the 'compared-value' property to a GType and retu...
Definition: gsttensor_if.c:145
GstTensorsConfig
Internal data structure for configured tensors info (for other/tensors).
Definition: tensor_typedef.h:284
PROP_THEN
@ PROP_THEN
Definition: gsttensor_if.c:96
operator_func
#define operator_func(cv, t, op, sv1, sv2, ret)
Macro for operator function.
Definition: gsttensor_if.c:813
silent_debug_caps
#define silent_debug_caps(self, caps, msg)
Macro for capability debug message.
Definition: tensor_common.h:285
ml_loge
#define ml_loge
Definition: nnstreamer_log.h:78
_GstTensorIf::act_then
tensor_if_behavior act_then
Definition: gsttensor_if.h:135
_NNS_INT32
@ _NNS_INT32
Definition: tensor_typedef.h:140
nnstreamer_if_custom_register
int nnstreamer_if_custom_register(const gchar *name, tensor_if_custom func, void *data)
Registers a callback for tensor_if custom condition.
Definition: gsttensor_if.c:1023
_GstTensorIf::then_option
GList * then_option
Definition: gsttensor_if.h:139
TIFSP_THEN_PAD
@ TIFSP_THEN_PAD
Definition: gsttensor_if.h:98
TRUE
return TRUE
Definition: gsttensor_if.c:897
UNUSED
#define UNUSED(expr)
Definition: mqttcommon.h:19
gst_tensor_if_set_property_cv_option
static void gst_tensor_if_set_property_cv_option(const GValue *value, GList **prop_list)
Convert GValue to GList for cv option.
Definition: gsttensor_if.c:354
nns_loge
#define nns_loge
Definition: nnstreamer_log.h:142
nnstreamer_util.h
Optional NNStreamer utility functions for sub-plugin writers and users.
_GstTensorIf::cv
tensor_if_compared_value cv
Definition: gsttensor_if.h:133
gst_tensor_if_class_init
static void gst_tensor_if_class_init(GstTensorIfClass *klass)
initialize the tensor_if's class (GST Standard)
Definition: gsttensor_if.c:222
_GstTensorIf::num_srcpads
guint32 num_srcpads
Definition: gsttensor_if.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
GstTensorPad::pad
GstPad * pad
Definition: tensor_common.h:104
_GstTensorIf::op
tensor_if_operator op
Definition: gsttensor_if.h:134
_GstTensorIf::cv_option
GList * cv_option
Definition: gsttensor_if.h:138
TIFOP_GT
@ TIFOP_GT
Definition: gsttensor_if.h:63
GstTensorPad::nth
guint nth
Definition: tensor_common.h:107
gst_tensor_if_check_condition
static gboolean gst_tensor_if_check_condition(GstTensorIf *tensor_if, GstBuffer *buf, gboolean *result)
Determining whether a given condition is true or false.
Definition: gsttensor_if.c:1070
_NNS_INT16
@ _NNS_INT16
Definition: tensor_typedef.h:142
TIFCV_A_VALUE
@ TIFCV_A_VALUE
Definition: gsttensor_if.h:43
TIFCV_CUSTOM
@ TIFCV_CUSTOM
Definition: gsttensor_if.h:53
_GstTensorIf::lock
GMutex lock
Definition: gsttensor_if.h:145
nns_logw
#define nns_logw
Definition: nnstreamer_log.h:141
tensor_if_sv_s::type
tensor_type type
Definition: gsttensor_if.h:108
gst_tensor_if_act_get_type
static GType gst_tensor_if_act_get_type(void)
A private function to register GEnumValue array for the 'then' and 'else' properties to a GType and r...
Definition: gsttensor_if.c:201
TIFOP_LE
@ TIFOP_LE
Definition: gsttensor_if.h:66
GstTensorsInfo::num_tensors
unsigned int num_tensors
Definition: tensor_typedef.h:275
_NNS_FLOAT64
@ _NNS_FLOAT64
Definition: tensor_typedef.h:146
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
tensor_data_s::type
tensor_type type
Definition: tensor_data.h:25
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_if_chain
static GstFlowReturn gst_tensor_if_chain(GstPad *pad, GstObject *parent, GstBuffer *buf)
chain function for sink (gst element vmethod)
Definition: gsttensor_if.c:1125
tensor_if_sv_s::num
guint32 num
Definition: gsttensor_if.h:107
TIFOP_NOT_IN_RANGE_EXCLUSIVE
@ TIFOP_NOT_IN_RANGE_EXCLUSIVE
Definition: gsttensor_if.h:70
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
GstTensorInfo::type
tensor_type type
Definition: tensor_typedef.h:266
GstTensorsConfig::info
GstTensorsInfo info
Definition: tensor_typedef.h:286
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
tensor_if_srcpads
tensor_if_srcpads
Which src pad.
Definition: gsttensor_if.h:96
custom_cb_s::func
tensor_if_custom func
Definition: gsttensor_if.h:115
_GstTensorIf::act_else
tensor_if_behavior act_else
Definition: gsttensor_if.h:136
GST_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensor_if_debug)
_NNS_UINT32
@ _NNS_UINT32
Definition: tensor_typedef.h:141
TIFOP_NOT_IN_RANGE_INCLUSIVE
@ TIFOP_NOT_IN_RANGE_INCLUSIVE
Definition: gsttensor_if.h:69
PROP_ELSE
@ PROP_ELSE
Definition: gsttensor_if.c:98
gst_tensor_data_typecast
gboolean gst_tensor_data_typecast(tensor_data_s *td, tensor_type type)
Typecast tensor element data.
Definition: tensor_data.c:203
gst_tensor_if_get_tensor_pad
static GstTensorPad * gst_tensor_if_get_tensor_pad(GstTensorIf *tensor_if, GstTensorsConfig *config, gboolean *created, guint nth)
Checking if the source pad is created and if not, create TensorPad.
Definition: gsttensor_if.c:727
_NNS_INT8
@ _NNS_INT8
Definition: tensor_typedef.h:144
gst_tensor_if_set_property_glist
static void gst_tensor_if_set_property_glist(const GValue *value, GList **prop_list, const gchar *delimiters)
Convert GValue to GList according to delimiters.
Definition: gsttensor_if.c:328
gst_tensors_info_copy
void gst_tensors_info_copy(GstTensorsInfo *dest, const GstTensorsInfo *src)
Copy tensor info.
Definition: nnstreamer_plugin_api_util_impl.c:502
GstTensorInfo::dimension
tensor_dim dimension
Definition: tensor_typedef.h:267
GST_TYPE_TENSOR_IF_CV
#define GST_TYPE_TENSOR_IF_CV
Definition: gsttensor_if.c:139
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
gsttensor_if.h
GStreamer plugin to control flow based on tensor values.
GST_TENSOR_IF
#define GST_TENSOR_IF(obj)
Definition: gsttensor_if.h:30
PROP_SV
@ PROP_SV
Definition: gsttensor_if.c:95
_NNS_UINT8
@ _NNS_UINT8
Definition: tensor_typedef.h:145
NNS_TENSOR_RANK_LIMIT
#define NNS_TENSOR_RANK_LIMIT
Definition: tensor_typedef.h:34
PROP_0
@ PROP_0
Definition: gsttensor_if.c:90
TIFOP_GE
@ TIFOP_GE
Definition: gsttensor_if.h:64
type
svtc_1 type
Definition: gsttensor_if.c:843
gst_tensor_if_get_tensor_average
static gboolean gst_tensor_if_get_tensor_average(GstTensorIf *tensor_if, GstBuffer *buf, tensor_data_s *cv, guint nth)
Calculate average value of the nth tensor.
Definition: gsttensor_if.c:904
TIFOP_RANGE_EXCLUSIVE
@ TIFOP_RANGE_EXCLUSIVE
Definition: gsttensor_if.h:68
GstTensorPad::last_ret
GstFlowReturn last_ret
Definition: tensor_common.h:106
if
if(!gst_tensordec_process_plugin_options(self,(opnum) - 1)) GST_ERROR_OBJECT(self
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorIf, gst_tensor_if, GST_TYPE_ELEMENT)
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
_GstTensorIf::sinkpad
GstPad * sinkpad
Definition: gsttensor_if.h:125
PROP_ELSE_OPTION
@ PROP_ELSE_OPTION
Definition: gsttensor_if.c:99
TIFOP_NE
case TIFOP_NE
t == sv1._##t) ? TRUE : FALSE; break; \
Definition: gsttensor_if.c:837
get_subplugin
const void * get_subplugin(subpluginType type, const char *name)
Public function defined in the header.
Definition: nnstreamer_subplugin.c:141
unregister_subplugin
gboolean unregister_subplugin(subpluginType type, const char *name)
Public function defined in the header.
Definition: nnstreamer_subplugin.c:289
sink_factory
static GstStaticPadTemplate sink_factory
The capabilities of the inputs.
Definition: gsttensor_if.c:109
PROP_THEN_OPTION
@ PROP_THEN_OPTION
Definition: gsttensor_if.c:97
gst_tensor_if_init
static void gst_tensor_if_init(GstTensorIf *tensor_if)
initialize the new element (GST Standard) instantiate pads and add them to element set pad callback f...
Definition: gsttensor_if.c:260
gst_tensor_if_property_to_string
static void gst_tensor_if_property_to_string(GValue *value, GList *prop_list, guint prop_id)
Convert GList to GValue.
Definition: gsttensor_if.c:503
gst_tensor_if_event
static gboolean gst_tensor_if_event(GstPad *pad, GstObject *parent, GstEvent *event)
event function for sink (gst element vmethod)
Definition: gsttensor_if.c:695
svtc_2
tensor_data_s svtc_2
Definition: gsttensor_if.c:841
PROP_CV
@ PROP_CV
Definition: gsttensor_if.c:92