Doxygen Book
gsttensor_decoder.c
Go to the documentation of this file.
1 
43 #ifdef HAVE_CONFIG_H
44 #include <config.h>
45 #endif
46 
47 #include <string.h>
48 #include "gsttensor_decoder.h"
49 
53 #ifndef DBG
54 #define DBG (!self->silent)
55 #endif
56 
57 GST_DEBUG_CATEGORY_STATIC (gst_tensordec_debug);
58 #define GST_CAT_DEFAULT gst_tensordec_debug
59 
63 enum
64 {
79 };
80 
84 #define DEFAULT_SILENT TRUE
85 
89 #define CAPS_STRING GST_TENSOR_CAP_DEFAULT ";" GST_TENSORS_CAP_DEFAULT ";" GST_TENSORS_FLEX_CAP_DEFAULT
90 
94 static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
95  GST_PAD_SINK,
96  GST_PAD_ALWAYS,
97  GST_STATIC_CAPS (CAPS_STRING));
98 
102 static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
103  GST_PAD_SRC,
104  GST_PAD_ALWAYS,
105  GST_STATIC_CAPS ("ANY"));
106 
107 #define gst_tensordec_parent_class parent_class
108 G_DEFINE_TYPE (GstTensorDecoder, gst_tensordec, GST_TYPE_BASE_TRANSFORM);
109 
111 static void gst_tensordec_set_property (GObject * object, guint prop_id,
112  const GValue * value, GParamSpec * pspec);
113 static void gst_tensordec_get_property (GObject * object, guint prop_id,
114  GValue * value, GParamSpec * pspec);
115 static void gst_tensordec_class_finalize (GObject * object);
116 
118 static GstFlowReturn gst_tensordec_transform (GstBaseTransform * trans,
119  GstBuffer * inbuf, GstBuffer * outbuf);
120 static GstCaps *gst_tensordec_transform_caps (GstBaseTransform * trans,
121  GstPadDirection direction, GstCaps * caps, GstCaps * filter);
122 static GstCaps *gst_tensordec_fixate_caps (GstBaseTransform * trans,
123  GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
124 static gboolean gst_tensordec_set_caps (GstBaseTransform * trans,
125  GstCaps * incaps, GstCaps * outcaps);
126 static gboolean gst_tensordec_transform_size (GstBaseTransform * trans,
127  GstPadDirection direction, GstCaps * caps, gsize size,
128  GstCaps * othercaps, gsize * othersize);
129 
133 static gboolean
135 {
136  if (!decoder || !decoder->modename) {
137  /* invalid name */
138  return FALSE;
139  }
140 
141  if (!decoder->init || !decoder->getOutCaps || !decoder->decode) {
142  /* invalid methods in decoder sub-plugin */
143  return FALSE;
144  }
145 
146  return TRUE;
147 }
148 
154 int
156 {
157  g_return_val_if_fail (nnstreamer_decoder_validate (decoder), FALSE);
158  return register_subplugin (NNS_SUBPLUGIN_DECODER, decoder->modename, decoder);
159 }
160 
165 void
166 nnstreamer_decoder_exit (const char *name)
167 {
169 }
170 
176 const GstTensorDecoderDef *
177 nnstreamer_decoder_find (const char *name)
178 {
179  return get_subplugin (NNS_SUBPLUGIN_DECODER, name);
180 }
181 
185 void
186 nnstreamer_decoder_set_custom_property_desc (const char *name, const char *prop,
187  ...)
188 {
189  va_list varargs;
190 
191  va_start (varargs, prop);
193  varargs);
194  va_end (varargs);
195 }
196 
200 #define gst_tensor_decoder_clean_plugin(self) do { \
201  if (self->decoder) { \
202  if (self->decoder->exit) \
203  self->decoder->exit (&self->plugin_data); \
204  else \
205  g_free (self->plugin_data); \
206  self->plugin_data = NULL; \
207  } \
208  } while (0)
209 
216 static GstCaps *
218  const GstTensorsConfig * config)
219 {
220  g_return_val_if_fail (config != NULL, NULL);
221 
222  if (self->decoder == NULL) {
223  if (self->is_custom) {
224  GstCaps *caps;
225  caps = gst_caps_from_string ("application/octet-stream");
226  if (config->rate_n >= 0 && config->rate_d > 0)
227  gst_caps_set_simple (caps, "framerate",
228  GST_TYPE_FRACTION, config->rate_n, config->rate_d, NULL);
229  return caps;
230  }
231  GST_ERROR_OBJECT (self, "Decoder plugin is not yet configured.");
232  return NULL;
233  }
234 
235  /* call sub-plugin vmethod */
236  return self->decoder->getOutCaps (&self->plugin_data, config);
237 }
238 
244 static GstCaps *
246  const GstStructure * structure)
247 {
248  GstTensorsConfig config;
249  GstCaps *result = NULL;
250 
251  if (gst_tensors_config_from_structure (&config, structure)) {
253  }
254 
255  if (result == NULL) {
256  /* we cannot specify the media type */
257  result = gst_caps_new_any ();
258  }
259 
260  return result;
261 }
262 
268 static gboolean
270  GstTensorsConfig * config)
271 {
272  g_return_val_if_fail (self != NULL, FALSE);
273  g_return_val_if_fail (config != NULL, FALSE);
274 
275  if (self->configured) {
276  return gst_tensors_config_is_equal (&self->tensor_config, config);
277  }
278 
280  return FALSE;
281 }
282 
286 static void
288 {
289  GObjectClass *gobject_class;
290  GstElementClass *gstelement_class;
291  GstBaseTransformClass *trans_class;
292  gchar **subplugins = NULL;
293  gchar *strbuf;
294  static gchar *strprint = NULL;
295 
296  GST_DEBUG_CATEGORY_INIT (gst_tensordec_debug, "tensor_decoder", 0,
297  "Element to convert tensor to media stream");
298 
299  trans_class = (GstBaseTransformClass *) klass;
300  gstelement_class = (GstElementClass *) trans_class;
301  gobject_class = (GObjectClass *) gstelement_class;
302 
303  gobject_class->set_property = gst_tensordec_set_property;
304  gobject_class->get_property = gst_tensordec_get_property;
305  gobject_class->finalize = gst_tensordec_class_finalize;
306 
307  g_object_class_install_property (gobject_class, PROP_SILENT,
308  g_param_spec_boolean ("silent", "Silent", "Produce verbose output",
309  DEFAULT_SILENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
310 
312  strbuf = g_strjoinv (", ", subplugins);
313  g_free (strprint);
314  strprint = g_strdup_printf
315  ("Decoder mode. Other options (option1 to optionN) depend on the specified model. For more detail on optionX for each mode, please refer to the documentation or nnstreamer-check utility. Available modes (decoder subplugins) are: {%s}.",
316  strbuf);
317 
318  g_object_class_install_property (gobject_class, PROP_MODE,
319  g_param_spec_string ("mode", "Mode", strprint, "",
320  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
321  g_free (strbuf);
322  g_strfreev (subplugins);
323 
324  g_object_class_install_property (gobject_class, PROP_MODE_OPTION1,
325  g_param_spec_string ("option1", "Mode option 1",
326  "option for specific decoder modes, 1st one.", "",
327  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
328 
329  g_object_class_install_property (gobject_class, PROP_MODE_OPTION2,
330  g_param_spec_string ("option2", "Mode option 2",
331  "option for specific decoder modes, 2nd one.", "",
332  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
333 
334  g_object_class_install_property (gobject_class, PROP_MODE_OPTION3,
335  g_param_spec_string ("option3", "Mode option 3",
336  "option for specific decoder modes, 3rd one.", "",
337  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
338 
339  g_object_class_install_property (gobject_class, PROP_MODE_OPTION4,
340  g_param_spec_string ("option4", "Mode option 4",
341  "option for specific decoder modes, 4th one.", "",
342  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
343 
344  g_object_class_install_property (gobject_class, PROP_MODE_OPTION5,
345  g_param_spec_string ("option5", "Mode option 5",
346  "option for specific decoder modes, 5th one.", "",
347  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
348 
349  g_object_class_install_property (gobject_class, PROP_MODE_OPTION6,
350  g_param_spec_string ("option6", "Mode option 6",
351  "option for specific decoder modes, 6th one.", "",
352  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
353 
354  g_object_class_install_property (gobject_class, PROP_MODE_OPTION7,
355  g_param_spec_string ("option7", "Mode option 7",
356  "option for specific decoder modes, 7th one.", "",
357  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
358 
359  g_object_class_install_property (gobject_class, PROP_MODE_OPTION8,
360  g_param_spec_string ("option8", "Mode option 8",
361  "option for specific decoder modes, 8th one.", "",
362  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
363 
364  g_object_class_install_property (gobject_class, PROP_MODE_OPTION9,
365  g_param_spec_string ("option9", "Mode option 9",
366  "option for specific decoder modes, 9th one.", "",
367  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
368 
369  g_object_class_install_property (gobject_class, PROP_SUBPLUGINS,
370  g_param_spec_string ("sub-plugins", "Sub-plugins",
371  "Registrable sub-plugins list", "",
372  G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
373 
374  g_object_class_install_property (gobject_class, PROP_CONFIG,
375  g_param_spec_string ("config-file", "Configuration-file",
376  "Path to configuration file which contains plugins properties", "",
377  G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
378 
379  gst_element_class_set_details_simple (gstelement_class,
380  "TensorDecoder",
381  "Converter/Tensor",
382  "Converts tensor stream of C-Array for neural network framework filters to audio or video stream",
383  "Jijoong Moon <jijoong.moon@samsung.com>");
384 
385  gst_element_class_add_pad_template (gstelement_class,
386  gst_static_pad_template_get (&sink_factory));
387 
388  gst_element_class_add_pad_template (gstelement_class,
389  gst_static_pad_template_get (&src_factory));
390 
392  trans_class->passthrough_on_same_caps = FALSE;
393  trans_class->transform_ip_on_passthrough = FALSE;
394 
396  trans_class->transform = GST_DEBUG_FUNCPTR (gst_tensordec_transform);
397 
399  trans_class->transform_caps =
400  GST_DEBUG_FUNCPTR (gst_tensordec_transform_caps);
401  trans_class->fixate_caps = GST_DEBUG_FUNCPTR (gst_tensordec_fixate_caps);
402  trans_class->set_caps = GST_DEBUG_FUNCPTR (gst_tensordec_set_caps);
403 
405  trans_class->transform_size =
406  GST_DEBUG_FUNCPTR (gst_tensordec_transform_size);
407 }
408 
415 static void
417 {
418  guint i;
419 
420  self->silent = DEFAULT_SILENT;
421  self->configured = FALSE;
422  self->negotiated = FALSE;
423  self->decoder = NULL;
424  self->plugin_data = NULL;
425  self->is_custom = FALSE;
426  self->custom.func = NULL;
427  self->custom.data = NULL;
428  self->config_path = NULL;
429  for (i = 0; i < TensorDecMaxOpNum; i++)
430  self->option[i] = NULL;
431 
432  gst_tensors_config_init (&self->tensor_config);
433 }
434 
439 static gboolean
441 {
442  g_assert (opnum < TensorDecMaxOpNum); /* Internal logic error! */
443  if (self->decoder == NULL)
444  return TRUE; /* decoder plugin not available. */
445  if (self->decoder->setOption == NULL)
446  return TRUE; /* This decoder cannot process options */
447  if (self->option[opnum] == NULL)
448  return TRUE; /* No option to process */
449  return self->decoder->setOption (&self->plugin_data, opnum,
450  self->option[opnum]);
451 }
452 
457 #define PROP_MODE_OPTION(opnum) \
458  case PROP_MODE_OPTION
459  g_free (self->option[(opnum) - 1]); \
460  self->option[(opnum) - 1] = g_value_dup_string (value); \
461  if (!gst_tensordec_process_plugin_options (self, (opnum) - 1)) \
462  GST_ERROR_OBJECT (self, "Configuring option for tensor-decoder failed (option %d = %s)", \
463  (opnum), self->option[(opnum) - 1]); \
464  break
465 
469 static void
470 gst_tensordec_set_property (GObject * object, guint prop_id,
471  const GValue * value, GParamSpec * pspec)
472 {
473  GstTensorDecoder *self;
474 
475  self = GST_TENSOR_DECODER (object);
476 
477  switch (prop_id) {
478  case PROP_SILENT:
479  self->silent = g_value_get_boolean (value);
480  break;
481  case PROP_MODE:
482  {
483  const GstTensorDecoderDef *decoder;
484  const gchar *mode_string;
485  guint i;
486 
487  mode_string = g_value_get_string (value);
488  if (g_ascii_strcasecmp (mode_string, "custom-code") == 0) {
489  self->is_custom = TRUE;
490  break;
491  }
492 
493  decoder = nnstreamer_decoder_find (mode_string);
494 
495  /* See if we are using "plugin" */
496  if (nnstreamer_decoder_validate (decoder)) {
497  silent_debug (self, "tensor_decoder plugin mode (%s)\n", mode_string);
498 
499  if (decoder == self->decoder) {
500  /* Already configured??? */
501  GST_WARNING_OBJECT (self,
502  "nnstreamer tensor_decoder %s is already configured.\n",
503  mode_string);
504  } else {
505  /* Changing decoder. Deallocate the previous */
507  self->decoder = decoder;
508  }
509 
510  if (0 == self->decoder->init (&self->plugin_data)) {
511  ml_loge ("Failed to initialize a decode subplugin, \"%s\".\n",
512  mode_string);
513  break;
514  }
515 
516  for (i = 0; i < TensorDecMaxOpNum; i++)
518  GST_WARNING_OBJECT (self,
519  "Failed to configure while setting the option %d.", (i + 1));
520  } else {
521  GST_ERROR_OBJECT (self,
522  "The given mode for tensor_decoder, %s, is unrecognized.\n",
523  mode_string);
525  self->decoder = NULL;
526  }
527  break;
528  }
529  case PROP_CONFIG:
530  {
531  g_free (self->config_path);
532  self->config_path = g_strdup (g_value_get_string (value));
533  gst_tensor_parse_config_file (self->config_path, object);
534  break;
535  }
536  PROP_MODE_OPTION (1);
537  PROP_MODE_OPTION (2);
538  PROP_MODE_OPTION (3);
539  PROP_MODE_OPTION (4);
540  PROP_MODE_OPTION (5);
541  PROP_MODE_OPTION (6);
542  PROP_MODE_OPTION (7);
543  PROP_MODE_OPTION (8);
544  PROP_MODE_OPTION (9);
545 
546  default:
547  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
548  break;
549  }
550 }
551 
556 #define PROP_READ_OPTION(opnum) \
557  case PROP_MODE_OPTION
558  g_value_set_string (value, self->option[opnum - 1]); \
559  break
560 
564 static void
565 gst_tensordec_get_property (GObject * object, guint prop_id,
566  GValue * value, GParamSpec * pspec)
567 {
568  GstTensorDecoder *self;
569 
570  self = GST_TENSOR_DECODER (object);
571 
572  switch (prop_id) {
573  case PROP_SILENT:
574  g_value_set_boolean (value, self->silent);
575  break;
576  case PROP_MODE:
577  if (self->is_custom)
578  g_value_set_string (value, "custom-code");
579  else if (self->decoder)
580  g_value_set_string (value, self->decoder->modename);
581  else
582  g_value_set_string (value, "");
583  break;
584  PROP_READ_OPTION (1);
585  PROP_READ_OPTION (2);
586  PROP_READ_OPTION (3);
587  PROP_READ_OPTION (4);
588  PROP_READ_OPTION (5);
589  PROP_READ_OPTION (6);
590  PROP_READ_OPTION (7);
591  PROP_READ_OPTION (8);
592  PROP_READ_OPTION (9);
593  case PROP_SUBPLUGINS:
594  {
595  gchar **str_array = get_all_subplugins (NNS_SUBPLUGIN_DECODER);
596 
597  if (str_array) {
598  g_value_take_string (value, g_strjoinv (",", str_array));
599  g_strfreev (str_array);
600  } else {
601  g_value_set_string (value, "");
602  }
603  break;
604  }
605  case PROP_CONFIG:
606  g_value_set_string (value, self->config_path ? self->config_path : "");
607  break;
608  default:
609  G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
610  break;
611  }
612 }
613 
617 static void
619 {
620  GstTensorDecoder *self;
621  guint i;
622 
623  self = GST_TENSOR_DECODER (object);
624 
626 
627  g_free (self->config_path);
628  for (i = 0; i < TensorDecMaxOpNum; ++i) {
629  g_free (self->option[i]);
630  }
631  self->custom.func = NULL;
632  self->custom.data = NULL;
633 
634  G_OBJECT_CLASS (parent_class)->finalize (object);
635 }
636 
640 static gboolean
641 gst_tensordec_configure (GstTensorDecoder * self, const GstCaps * in_caps,
642  const GstCaps * out_caps)
643 {
644  GstStructure *structure;
645  GstTensorsConfig config;
646 
648  structure = gst_caps_get_structure (in_caps, 0);
649 
650  if (!gst_tensors_config_from_structure (&config, structure)) {
651  GST_ERROR_OBJECT (self, "Cannot configure tensor from structure");
652  return FALSE;
653  }
654 
655  if (!gst_tensors_config_validate (&config)) {
656  GST_ERROR_OBJECT (self, "Not configured yet");
657  return FALSE;
658  }
659 
660  if (self->decoder == NULL && !self->is_custom) {
661  GST_ERROR_OBJECT (self, "Decoder plugin is not yet configured.");
662  return FALSE;
663  }
664 
669  if (self->configured && !gst_tensordec_check_consistency (self, &config)) {
670  GstCaps *supposed;
671  gboolean compatible;
672 
673  supposed = gst_tensordec_media_caps_from_tensor (self, &config);
674  compatible = gst_caps_is_always_compatible (out_caps, supposed);
675  gst_caps_unref (supposed);
676 
678  if (!compatible) {
679  GST_ERROR_OBJECT (self, "The coming tensor config is not valid.");
680  return FALSE;
681  }
682 
684  self->decoder->init (&self->plugin_data);
685  }
686 
687  self->tensor_config = config;
688  self->configured = TRUE;
689  return TRUE;
690 }
691 
695 static GstFlowReturn
696 gst_tensordec_transform (GstBaseTransform * trans,
697  GstBuffer * inbuf, GstBuffer * outbuf)
698 {
699  GstTensorDecoder *self;
700  GstFlowReturn res;
701 
702  self = GST_TENSOR_DECODER_CAST (trans);
703 
704  if (G_UNLIKELY (!self->negotiated))
705  goto unknown_tensor;
706  if (G_UNLIKELY (!self->configured))
707  goto unknown_format;
708 
709  if (self->decoder || self->is_custom) {
710  GstMemory *in_mem[NNS_TENSOR_SIZE_LIMIT];
711  GstMapInfo in_info[NNS_TENSOR_SIZE_LIMIT];
713  guint i, num_tensors, num_mems;
714 
715  num_mems = gst_tensor_buffer_get_count (inbuf);
716  if (gst_tensors_config_is_flexible (&self->tensor_config)) {
717  self->tensor_config.info.num_tensors = num_mems;
718  }
719  num_tensors = self->tensor_config.info.num_tensors;
721  g_assert (num_mems == num_tensors);
722 
723  for (i = 0; i < num_tensors; i++) {
724  in_mem[i] = gst_tensor_buffer_get_nth_memory (inbuf, i);
725  if (!gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ)) {
726  guint j;
727  ml_logf ("Failed to map in_mem[%u].\n", i);
728 
729  for (j = 0; j < i; j++) {
730  gst_memory_unmap (in_mem[j], &in_info[j]);
731  gst_memory_unref (in_mem[j]);
732  }
733  gst_memory_unref (in_mem[i]);
734  return GST_FLOW_ERROR;
735  }
736 
737  input[i].data = in_info[i].data;
738  input[i].size = in_info[i].size;
739  }
740  if (!self->is_custom) {
741  res = self->decoder->decode (&self->plugin_data, &self->tensor_config,
742  input, outbuf);
743  } else if (self->custom.func != NULL) {
744  res = self->custom.func (input, &self->tensor_config, self->custom.data,
745  outbuf);
746  } else {
747  GST_ERROR_OBJECT (self, "Custom decoder callback is not registered.");
748  res = GST_FLOW_ERROR;
749  }
750 
751  for (i = 0; i < num_tensors; i++) {
752  gst_memory_unmap (in_mem[i], &in_info[i]);
753  gst_memory_unref (in_mem[i]);
754  }
755  } else {
756  GST_ERROR_OBJECT (self, "Decoder plugin not yet configured.");
757  goto unknown_type;
758  }
759 
760  return res;
761 
762 unknown_format:
763  GST_ERROR_OBJECT (self, "Hit unknown_format");
764  GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL), ("unknown format"));
765  return GST_FLOW_NOT_NEGOTIATED;
766 unknown_tensor:
767  GST_ERROR_OBJECT (self, "Hit unknown_tensor");
768  GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL),
769  ("unknown format for tensor"));
770  return GST_FLOW_NOT_NEGOTIATED;
771 unknown_type:
772  GST_ELEMENT_ERROR (self, CORE, NOT_IMPLEMENTED, (NULL),
773  ("not implemented decoder mode"));
774  return GST_FLOW_NOT_SUPPORTED;
775 }
776 
785 static GstCaps *
786 gst_tensordec_transform_caps (GstBaseTransform * trans,
787  GstPadDirection direction, GstCaps * caps, GstCaps * filter)
788 {
789  GstTensorDecoder *self;
790  GstCaps *result;
791 
792  self = GST_TENSOR_DECODER_CAST (trans);
793 
794  /* Not ready */
795  if (self->decoder == NULL && !self->is_custom)
796  return NULL;
797 
798  if (self->is_custom) {
799  const decoder_custom_cb_s *ptr = NULL;
800  if (self->option[0] == NULL) {
801  nns_logw ("Tensor decoder custom option is not given.");
802  return NULL;
803  }
804  self->custom.func = NULL;
805  ptr = get_subplugin (NNS_CUSTOM_DECODER, self->option[0]);
806  if (!ptr) {
807  nns_logw ("Failed to find custom subplugin of the tensor_decoder");
808  return NULL;
809  }
810  self->custom.func = ptr->func;
811  self->custom.data = ptr->data;
812  }
813 
814  silent_debug (self, "Direction = %d\n", direction);
815  silent_debug_caps (self, caps, "from");
816  silent_debug_caps (self, filter, "filter");
817 
818  if (direction == GST_PAD_SINK) {
820  GstStructure *s = gst_caps_get_structure (caps, 0);
822  } else if (direction == GST_PAD_SRC) {
825  result = gst_caps_from_string (CAPS_STRING);
826  } else {
827  g_assert (0); /* Internal logic error! */
828  return NULL;
829  }
830 
831  if (filter && gst_caps_get_size (filter) > 0) {
832  GstCaps *intersection;
833 
834  intersection =
835  gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
836 
837  gst_caps_unref (result);
838  result = intersection;
839  }
840 
841  silent_debug_caps (self, result, "to");
842 
843  GST_DEBUG_OBJECT (self, "Direction[%d] transformed %" GST_PTR_FORMAT
844  " into %" GST_PTR_FORMAT, direction, caps, result);
845  return result;
846 }
847 
851 static GstCaps *
852 gst_tensordec_fixate_caps (GstBaseTransform * trans,
853  GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
854 {
855  GstTensorDecoder *self;
856  GstCaps *supposed;
857  GstCaps *result;
858 
859  self = GST_TENSOR_DECODER_CAST (trans);
860 
861  silent_debug_caps (self, caps, "from caps");
862  silent_debug_caps (self, othercaps, "from othercaps");
863 
864  GST_DEBUG_OBJECT (self, "trying to fixate othercaps %" GST_PTR_FORMAT
865  " based on caps %" GST_PTR_FORMAT, othercaps, caps);
866 
873  if (direction != GST_PAD_SINK) {
874  ml_logf_stacktrace ("Invalid direction for tensor-decoder fixate caps.\n");
875  return NULL;
876  }
877 
878  if (gst_tensordec_configure (self, caps, othercaps)) {
879  supposed =
880  gst_tensordec_media_caps_from_tensor (self, &self->tensor_config);
881  } else {
882  GstStructure *s = gst_caps_get_structure (caps, 0);
883  supposed = gst_tensordec_media_caps_from_structure (self, s);
884  }
885 
886  result = gst_caps_intersect (othercaps, supposed);
887  gst_caps_unref (supposed);
888 
889  if (gst_caps_is_empty (result)) {
890  gst_caps_unref (result);
891  result = othercaps;
892  } else {
893  gst_caps_unref (othercaps);
894  }
895 
896  GST_DEBUG_OBJECT (self, "now fixating %" GST_PTR_FORMAT, result);
897 
898  result = gst_caps_make_writable (result);
899  result = gst_caps_fixate (result);
900 
901  if (direction == GST_PAD_SINK) {
902  if (gst_caps_is_subset (caps, result)) {
903  gst_caps_replace (&result, caps);
904  }
905  }
906  return result;
907 }
908 
912 static gboolean
913 gst_tensordec_set_caps (GstBaseTransform * trans,
914  GstCaps * incaps, GstCaps * outcaps)
915 {
917 
918  silent_debug_caps (self, incaps, "from incaps");
919  silent_debug_caps (self, outcaps, "from outcaps");
920 
921  if (gst_tensordec_configure (self, incaps, outcaps)) {
922  GstCaps *supposed = gst_tensordec_media_caps_from_tensor (self,
923  &self->tensor_config);
924 
926  if (gst_caps_is_always_compatible (outcaps, supposed)) {
927  self->negotiated = TRUE;
928  } else {
929  GST_ERROR_OBJECT (self,
930  "This is not compatible with the supposed output pad cap");
931  }
932 
933  gst_caps_unref (supposed);
934  }
935 
936  return self->negotiated;
937 }
938 
944 static gboolean
945 gst_tensordec_transform_size (GstBaseTransform * trans,
946  GstPadDirection direction, GstCaps * caps, gsize size,
947  GstCaps * othercaps, gsize * othersize)
948 {
949  GstTensorDecoder *self;
950 
951  if (direction == GST_PAD_SRC)
952  return FALSE;
954  self = GST_TENSOR_DECODER_CAST (trans);
955 
956  g_assert (self->configured);
957 
958  if (!self->is_custom && self->decoder->getTransformSize)
959  *othersize = self->decoder->getTransformSize (&self->plugin_data,
960  &self->tensor_config, caps, size, othercaps, direction);
961  else
962  *othersize = 0;
963 
964  return TRUE;
965 }
966 
971 int
973  tensor_decoder_custom func, void *data)
974 {
975  decoder_custom_cb_s *ptr;
976 
977  g_return_val_if_fail (name && strlen (name), -EINVAL);
978  g_return_val_if_fail (func, -EINVAL);
979 
980  if (!(ptr = g_try_new0 (decoder_custom_cb_s, 1)))
981  return -ENOMEM;
982 
983  ptr->func = func;
984  ptr->data = data;
985 
986  if (register_subplugin (NNS_CUSTOM_DECODER, name, ptr))
987  return 0;
988 
989  g_free (ptr);
990  return -EINVAL;
991 }
992 
997 int
999 {
1000  decoder_custom_cb_s *ptr;
1001 
1004  ml_loge ("Failed to unregister custom callback %s.", name);
1005  return -EINVAL;
1006  }
1007  g_free (ptr);
1008 
1009  return 0;
1010 }
gst_tensors_config_is_flexible
#define gst_tensors_config_is_flexible(c)
Macro to check stream format (flexible tensors for caps negotiation)
Definition: nnstreamer_plugin_api_util.h:279
_GstTensorDecoderDef
Decoder definitions for different semantics of tensors This allows developers to create their own dec...
Definition: nnstreamer_plugin_api_decoder.h:38
gst_tensors_config_is_equal
gboolean gst_tensors_config_is_equal(const GstTensorsConfig *c1, const GstTensorsConfig *c2)
Compare tensor config info (for other/tensors)
Definition: nnstreamer_plugin_api_util_impl.c:881
gst_tensordec_init
static void gst_tensordec_init(GstTensorDecoder *self)
initialize the new element instantiate pads and add them to element set pad callback functions initia...
Definition: gsttensor_decoder.c:416
NNS_SUBPLUGIN_DECODER
@ NNS_SUBPLUGIN_DECODER
Definition: nnstreamer_subplugin.h:42
g_assert
g_assert(sizeof(DTYPE_UNSIGNED)==sizeof(DTYPE_SIGNED))
gst_tensordec_set_caps
static gboolean gst_tensordec_set_caps(GstBaseTransform *trans, GstCaps *incaps, GstCaps *outcaps)
set caps. required vmethod of BaseTransform
Definition: gsttensor_decoder.c:913
PROP_MODE_OPTION3
@ PROP_MODE_OPTION3
Definition: gsttensor_decoder.c:70
gst_tensordec_set_property
static void gst_tensordec_set_property(GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
Set property (GObject vmethod)
Definition: gsttensor_decoder.c:470
data
svtc_1 data
Definition: gsttensor_if.c:844
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
FALSE
return FALSE
Definition: gsttensor_transform.c:590
result
case tensor_data_s gboolean * result
Definition: gsttensor_if.c:839
_GstTensorDecoder
Internal data structure for tensordec instances.
Definition: gsttensor_decoder.h:67
nnstreamer_decoder_probe
int nnstreamer_decoder_probe(GstTensorDecoderDef *decoder)
Decoder's sub-plugin should call this function to register itself.
Definition: gsttensor_decoder.c:155
gst_tensordec_transform
static GstFlowReturn gst_tensordec_transform(GstBaseTransform *trans, GstBuffer *inbuf, GstBuffer *outbuf)
non-ip transform. required vmethod for BaseTransform class.
Definition: gsttensor_decoder.c:696
decoder_custom_cb_s
Definition: gsttensor_decoder.h:56
ml_logf
#define ml_logf
Definition: nnstreamer_log.h:80
GstTensorMemory::data
void * data
Definition: tensor_typedef.h:254
prop
GstTensorSrcIIOChannelProperties * prop
DTYPE_UNSIGNED ( .
Definition: gsttensor_srciio.c:110
PROP_MODE_OPTION8
@ PROP_MODE_OPTION8
Definition: gsttensor_decoder.c:75
subplugin_set_custom_property_desc
void subplugin_set_custom_property_desc(subpluginType type, const char *name, const gchar *prop, va_list varargs)
common interface to set custom property description of a sub-plugin.
Definition: nnstreamer_subplugin.c:329
gst_tensordec_fixate_caps
static GstCaps * gst_tensordec_fixate_caps(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *othercaps)
fixate caps. required vmethod of BaseTransform
Definition: gsttensor_decoder.c:852
G_DEFINE_TYPE
G_DEFINE_TYPE(GstTensorDecoder, gst_tensordec, GST_TYPE_BASE_TRANSFORM)
gst_tensordec_check_consistency
static gboolean gst_tensordec_check_consistency(GstTensorDecoder *self, GstTensorsConfig *config)
Check tensor config is consistent.
Definition: gsttensor_decoder.c:269
subplugins
static GHashTable * subplugins[NNS_SUBPLUGIN_END]
Definition: nnstreamer_subplugin.c:47
gst_tensordec_media_caps_from_structure
static GstCaps * gst_tensordec_media_caps_from_structure(GstTensorDecoder *self, const GstStructure *structure)
Parse structure and return media caps.
Definition: gsttensor_decoder.c:245
GstTensorMemory
The unit of each data tensors. It will be used as an input/output tensor of other/tensors.
Definition: tensor_typedef.h:252
gsttensor_decoder.h
GStreamer plugin to convert tensors to media types.
gst_tensordec_configure
static gboolean gst_tensordec_configure(GstTensorDecoder *self, const GstCaps *in_caps, const GstCaps *out_caps)
Configure tensor metadata from sink caps.
Definition: gsttensor_decoder.c:641
GstTensorsConfig::rate_d
int rate_d
Definition: tensor_typedef.h:288
src_factory
static GstStaticPadTemplate src_factory
The capabilities of the outputs.
Definition: gsttensor_decoder.c:102
gst_tensordec_media_caps_from_tensor
static GstCaps * gst_tensordec_media_caps_from_tensor(GstTensorDecoder *self, const GstTensorsConfig *config)
Get media caps from tensor config.
Definition: gsttensor_decoder.c:217
silent_debug
#define silent_debug(self,...)
Macro for debug message.
Definition: tensor_common.h:276
sink_factory
static GstStaticPadTemplate sink_factory
The capabilities of the inputs.
Definition: gsttensor_decoder.c:94
g_free
g_free(self->option[(opnum) - 1])
opnum: \
nnstreamer_decoder_custom_register
int nnstreamer_decoder_custom_register(const gchar *name, tensor_decoder_custom func, void *data)
Registers a callback for tensor_decoder custom condition.
Definition: gsttensor_decoder.c:972
ml_logf_stacktrace
#define ml_logf_stacktrace(...)
Definition: nnstreamer_log.h:102
PROP_READ_OPTION
#define PROP_READ_OPTION(opnum)
A macro to read per-mode option.
Definition: gsttensor_decoder.c:556
nnstreamer_decoder_set_custom_property_desc
void nnstreamer_decoder_set_custom_property_desc(const char *name, const char *prop,...)
set custom property description for tensor decoder sub-plugin
Definition: gsttensor_decoder.c:186
gst_tensordec_class_finalize
static void gst_tensordec_class_finalize(GObject *object)
Finalize instance (GObject vmethod)
Definition: gsttensor_decoder.c:618
g_value_set_string
g_value_set_string(value, self->option[opnum - 1])
opnum: \
nnstreamer_decoder_validate
static gboolean nnstreamer_decoder_validate(const GstTensorDecoderDef *decoder)
Validate decoder sub-plugin's data.
Definition: gsttensor_decoder.c:134
PROP_MODE_OPTION2
@ PROP_MODE_OPTION2
Definition: gsttensor_decoder.c:69
PROP_MODE_OPTION6
@ PROP_MODE_OPTION6
Definition: gsttensor_decoder.c:73
GstTensorsConfig::rate_n
int rate_n
Definition: tensor_typedef.h:287
GST_TENSOR_DECODER
#define GST_TENSOR_DECODER(obj)
Definition: gsttensor_decoder.h:44
GstTensorMemory::size
size_t size
Definition: tensor_typedef.h:255
PROP_MODE_OPTION1
@ PROP_MODE_OPTION1
Definition: gsttensor_decoder.c:68
GST_TENSOR_DECODER_CAST
#define GST_TENSOR_DECODER_CAST(obj)
Definition: gsttensor_decoder.h:52
nnstreamer_decoder_exit
void nnstreamer_decoder_exit(const char *name)
Decoder's sub-plugin may call this to unregister itself.
Definition: gsttensor_decoder.c:166
register_subplugin
gboolean register_subplugin(subpluginType type, const char *name, const void *data)
Public function defined in the header.
Definition: nnstreamer_subplugin.c:225
_GstTensorDecoderDef::getOutCaps
GstCaps *(* getOutCaps)(void **private_data, const GstTensorsConfig *config)
Definition: nnstreamer_plugin_api_decoder.h:61
gst_tensor_decoder_clean_plugin
#define gst_tensor_decoder_clean_plugin(self)
Macro to clean sub-plugin data.
Definition: gsttensor_decoder.c:200
NNS_CUSTOM_DECODER
@ NNS_CUSTOM_DECODER
Definition: nnstreamer_subplugin.h:47
GstTensorsConfig
Internal data structure for configured tensors info (for other/tensors).
Definition: tensor_typedef.h:284
get_all_subplugins
gchar ** get_all_subplugins(subpluginType type)
Public function defined in the header.
Definition: nnstreamer_subplugin.c:176
_GstTensorDecoderDef::init
int(* init)(void **private_data)
Definition: nnstreamer_plugin_api_decoder.h:42
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
PROP_MODE_OPTION9
@ PROP_MODE_OPTION9
Definition: gsttensor_decoder.c:76
PROP_MODE
@ PROP_MODE
Definition: gsttensor_decoder.c:67
TRUE
return TRUE
Definition: gsttensor_if.c:897
PROP_SILENT
@ PROP_SILENT
Definition: gsttensor_decoder.c:66
TensorDecMaxOpNum
#define TensorDecMaxOpNum
Definition: gsttensor_decoder.h:62
nnstreamer_decoder_find
const GstTensorDecoderDef * nnstreamer_decoder_find(const char *name)
Find decoder sub-plugin with the name.
Definition: gsttensor_decoder.c:177
decoder_custom_cb_s::data
void * data
Definition: gsttensor_decoder.h:59
gst_tensordec_class_init
static void gst_tensordec_class_init(GstTensorDecoderClass *klass)
initialize the tensordec's class
Definition: gsttensor_decoder.c:287
gst_tensordec_process_plugin_options
static gboolean gst_tensordec_process_plugin_options(GstTensorDecoder *self, guint opnum)
Process plugin (self->decoder) with given options if available.
Definition: gsttensor_decoder.c:440
_GstTensorDecoderDef::modename
char * modename
Definition: nnstreamer_plugin_api_decoder.h:40
PROP_MODE_OPTION5
@ PROP_MODE_OPTION5
Definition: gsttensor_decoder.c:72
PROP_CONFIG
@ PROP_CONFIG
Definition: gsttensor_decoder.c:78
decoder_custom_cb_s::func
tensor_decoder_custom func
Definition: gsttensor_decoder.h:58
PROP_0
@ PROP_0
Definition: gsttensor_decoder.c:65
gst_tensordec_transform_caps
static GstCaps * gst_tensordec_transform_caps(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, GstCaps *filter)
configure tensor-srcpad cap from "proposed" cap.
Definition: gsttensor_decoder.c:786
PROP_MODE_OPTION
#define PROP_MODE_OPTION(opnum)
A macro to process incoming per-mode option.
Definition: gsttensor_decoder.c:457
nns_logw
#define nns_logw
Definition: nnstreamer_log.h:141
nnstreamer_decoder_custom_unregister
int nnstreamer_decoder_custom_unregister(const gchar *name)
Unregisters a callback for tensor_decoder custom condition.
Definition: gsttensor_decoder.c:998
gst_tensor_parse_config_file
void gst_tensor_parse_config_file(const gchar *config_path, const GObject *object)
Parses a configuration file and sets the corresponding properties on a GObject.
Definition: nnstreamer_plugin_api_impl.c:1902
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_DEBUG_CATEGORY_STATIC
GST_DEBUG_CATEGORY_STATIC(gst_tensordec_debug)
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
PROP_SUBPLUGINS
@ PROP_SUBPLUGINS
Definition: gsttensor_decoder.c:77
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
PROP_MODE_OPTION4
@ PROP_MODE_OPTION4
Definition: gsttensor_decoder.c:71
gst_tensordec_get_property
static void gst_tensordec_get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
Get property (GObject vmethod)
Definition: gsttensor_decoder.c:565
_GstTensorDecoderClass
GstTensorDecoderClass inherits GstBaseTransformClass.
Definition: gsttensor_decoder.h:96
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
tensor_decoder_custom
G_BEGIN_DECLS typedef int(* tensor_decoder_custom)(const GstTensorMemory *input, const GstTensorsConfig *config, void *data, GstBuffer *out_buf)
Decode from tensors to media as customized operation.
Definition: tensor_decoder_custom.h:32
opnum
Configuring option for tensor decoder opnum
Definition: gsttensor_decoder.c:463
CAPS_STRING
#define CAPS_STRING
Support multi-tensor along with single-tensor as the input.
Definition: gsttensor_decoder.c:89
DEFAULT_SILENT
#define DEFAULT_SILENT
Flag to print minimized log.
Definition: gsttensor_decoder.c:84
gst_tensordec_transform_size
static gboolean gst_tensordec_transform_size(GstBaseTransform *trans, GstPadDirection direction, GstCaps *caps, gsize size, GstCaps *othercaps, gsize *othersize)
Tell the framework the required size of buffer based on the info of the other side pad....
Definition: gsttensor_decoder.c:945
_GstTensorDecoderDef::decode
GstFlowReturn(* decode)(void **private_data, const GstTensorsConfig *config, const GstTensorMemory *input, GstBuffer *outbuf)
Definition: nnstreamer_plugin_api_decoder.h:71
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
PROP_MODE_OPTION7
@ PROP_MODE_OPTION7
Definition: gsttensor_decoder.c:74