54 #define DBG (!self->silent)
58 #define GST_CAT_DEFAULT gst_tensordec_debug
84 #define DEFAULT_SILENT TRUE
89 #define CAPS_STRING GST_TENSOR_CAP_DEFAULT ";" GST_TENSORS_CAP_DEFAULT ";" GST_TENSORS_FLEX_CAP_DEFAULT
94 static GstStaticPadTemplate
sink_factory = GST_STATIC_PAD_TEMPLATE (
"sink",
102 static GstStaticPadTemplate
src_factory = GST_STATIC_PAD_TEMPLATE (
"src",
105 GST_STATIC_CAPS (
"ANY"));
107 #define gst_tensordec_parent_class parent_class
112 const GValue * value, GParamSpec * pspec);
114 GValue * value, GParamSpec * pspec);
119 GstBuffer * inbuf, GstBuffer * outbuf);
121 GstPadDirection direction, GstCaps * caps, GstCaps * filter);
123 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps);
125 GstCaps * incaps, GstCaps * outcaps);
127 GstPadDirection direction, GstCaps * caps, gsize size,
128 GstCaps * othercaps, gsize * othersize);
136 if (!decoder || !decoder->
modename) {
191 va_start (varargs,
prop);
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); \
205 g_free (self->plugin_data); \
206 self->plugin_data = NULL; \
220 g_return_val_if_fail (config != NULL, NULL);
222 if (self->decoder == NULL) {
223 if (self->is_custom) {
225 caps = gst_caps_from_string (
"application/octet-stream");
227 gst_caps_set_simple (caps,
"framerate",
228 GST_TYPE_FRACTION, config->
rate_n, config->
rate_d, NULL);
231 GST_ERROR_OBJECT (
self,
"Decoder plugin is not yet configured.");
236 return self->decoder->getOutCaps (&self->plugin_data, config);
246 const GstStructure * structure)
257 result = gst_caps_new_any ();
272 g_return_val_if_fail (
self != NULL,
FALSE);
273 g_return_val_if_fail (config != NULL,
FALSE);
275 if (self->configured) {
289 GObjectClass *gobject_class;
290 GstElementClass *gstelement_class;
291 GstBaseTransformClass *trans_class;
294 static gchar *strprint = NULL;
296 GST_DEBUG_CATEGORY_INIT (gst_tensordec_debug,
"tensor_decoder", 0,
297 "Element to convert tensor to media stream");
299 trans_class = (GstBaseTransformClass *) klass;
300 gstelement_class = (GstElementClass *) trans_class;
301 gobject_class = (GObjectClass *) gstelement_class;
307 g_object_class_install_property (gobject_class,
PROP_SILENT,
308 g_param_spec_boolean (
"silent",
"Silent",
"Produce verbose output",
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}.",
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));
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));
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));
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));
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));
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));
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));
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));
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));
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));
370 g_param_spec_string (
"sub-plugins",
"Sub-plugins",
371 "Registrable sub-plugins list",
"",
372 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
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));
379 gst_element_class_set_details_simple (gstelement_class,
382 "Converts tensor stream of C-Array for neural network framework filters to audio or video stream",
383 "Jijoong Moon <jijoong.moon@samsung.com>");
385 gst_element_class_add_pad_template (gstelement_class,
388 gst_element_class_add_pad_template (gstelement_class,
392 trans_class->passthrough_on_same_caps =
FALSE;
393 trans_class->transform_ip_on_passthrough =
FALSE;
399 trans_class->transform_caps =
405 trans_class->transform_size =
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;
430 self->option[i] = NULL;
443 if (self->decoder == NULL)
445 if (self->decoder->setOption == NULL)
447 if (self->option[
opnum] == NULL)
449 return self->decoder->setOption (&self->plugin_data,
opnum,
450 self->option[
opnum]);
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]); \
471 const GValue * value, GParamSpec * pspec)
479 self->silent = g_value_get_boolean (value);
484 const gchar *mode_string;
487 mode_string = g_value_get_string (value);
488 if (g_ascii_strcasecmp (mode_string,
"custom-code") == 0) {
489 self->is_custom =
TRUE;
497 silent_debug (
self,
"tensor_decoder plugin mode (%s)\n", mode_string);
499 if (decoder == self->decoder) {
501 GST_WARNING_OBJECT (
self,
502 "nnstreamer tensor_decoder %s is already configured.\n",
507 self->decoder = decoder;
510 if (0 == self->decoder->init (&self->plugin_data)) {
511 ml_loge (
"Failed to initialize a decode subplugin, \"%s\".\n",
518 GST_WARNING_OBJECT (
self,
519 "Failed to configure while setting the option %d.", (i + 1));
521 GST_ERROR_OBJECT (
self,
522 "The given mode for tensor_decoder, %s, is unrecognized.\n",
525 self->decoder = NULL;
531 g_free (self->config_path);
532 self->config_path = g_strdup (g_value_get_string (value));
547 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
556 #define PROP_READ_OPTION(opnum) \
557 case PROP_MODE_OPTION
558 g_value_set_string (value, self->option[opnum - 1]); \
566 GValue * value, GParamSpec * pspec)
574 g_value_set_boolean (value, self->silent);
579 else if (self->decoder)
598 g_value_take_string (value, g_strjoinv (
",", str_array));
599 g_strfreev (str_array);
609 G_OBJECT_WARN_INVALID_PROPERTY_ID (
object, prop_id, pspec);
627 g_free (self->config_path);
631 self->custom.func = NULL;
632 self->custom.data = NULL;
634 G_OBJECT_CLASS (parent_class)->finalize (
object);
642 const GstCaps * out_caps)
644 GstStructure *structure;
648 structure = gst_caps_get_structure (in_caps, 0);
651 GST_ERROR_OBJECT (
self,
"Cannot configure tensor from structure");
656 GST_ERROR_OBJECT (
self,
"Not configured yet");
660 if (self->decoder == NULL && !self->is_custom) {
661 GST_ERROR_OBJECT (
self,
"Decoder plugin is not yet configured.");
674 compatible = gst_caps_is_always_compatible (out_caps, supposed);
675 gst_caps_unref (supposed);
679 GST_ERROR_OBJECT (
self,
"The coming tensor config is not valid.");
684 self->decoder->init (&self->plugin_data);
687 self->tensor_config = config;
688 self->configured =
TRUE;
697 GstBuffer * inbuf, GstBuffer * outbuf)
704 if (G_UNLIKELY (!self->negotiated))
706 if (G_UNLIKELY (!self->configured))
709 if (self->decoder || self->is_custom) {
713 guint i, num_tensors, num_mems;
717 self->tensor_config.info.num_tensors = num_mems;
719 num_tensors =
self->tensor_config.info.num_tensors;
723 for (i = 0; i < num_tensors; i++) {
725 if (!gst_memory_map (in_mem[i], &in_info[i], GST_MAP_READ)) {
727 ml_logf (
"Failed to map in_mem[%u].\n", i);
729 for (j = 0; j < i; j++) {
730 gst_memory_unmap (in_mem[j], &in_info[j]);
731 gst_memory_unref (in_mem[j]);
733 gst_memory_unref (in_mem[i]);
734 return GST_FLOW_ERROR;
737 input[i].
data = in_info[i].data;
738 input[i].
size = in_info[i].size;
740 if (!self->is_custom) {
741 res =
self->decoder->decode (&self->plugin_data, &self->tensor_config,
743 }
else if (self->custom.func != NULL) {
744 res =
self->custom.func (input, &self->tensor_config, self->custom.
data,
747 GST_ERROR_OBJECT (
self,
"Custom decoder callback is not registered.");
748 res = GST_FLOW_ERROR;
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]);
756 GST_ERROR_OBJECT (
self,
"Decoder plugin not yet configured.");
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;
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;
772 GST_ELEMENT_ERROR (
self, CORE, NOT_IMPLEMENTED, (NULL),
773 (
"not implemented decoder mode"));
774 return GST_FLOW_NOT_SUPPORTED;
787 GstPadDirection direction, GstCaps * caps, GstCaps * filter)
795 if (self->decoder == NULL && !self->is_custom)
798 if (self->is_custom) {
800 if (self->option[0] == NULL) {
801 nns_logw (
"Tensor decoder custom option is not given.");
804 self->custom.func = NULL;
807 nns_logw (
"Failed to find custom subplugin of the tensor_decoder");
810 self->custom.func = ptr->
func;
811 self->custom.data = ptr->
data;
818 if (direction == GST_PAD_SINK) {
820 GstStructure *s = gst_caps_get_structure (caps, 0);
822 }
else if (direction == GST_PAD_SRC) {
831 if (filter && gst_caps_get_size (filter) > 0) {
832 GstCaps *intersection;
835 gst_caps_intersect_full (filter,
result, GST_CAPS_INTERSECT_FIRST);
843 GST_DEBUG_OBJECT (
self,
"Direction[%d] transformed %" GST_PTR_FORMAT
844 " into %" GST_PTR_FORMAT, direction, caps,
result);
853 GstPadDirection direction, GstCaps * caps, GstCaps * othercaps)
864 GST_DEBUG_OBJECT (
self,
"trying to fixate othercaps %" GST_PTR_FORMAT
865 " based on caps %" GST_PTR_FORMAT, othercaps, caps);
873 if (direction != GST_PAD_SINK) {
882 GstStructure *s = gst_caps_get_structure (caps, 0);
886 result = gst_caps_intersect (othercaps, supposed);
887 gst_caps_unref (supposed);
889 if (gst_caps_is_empty (
result)) {
893 gst_caps_unref (othercaps);
896 GST_DEBUG_OBJECT (
self,
"now fixating %" GST_PTR_FORMAT,
result);
901 if (direction == GST_PAD_SINK) {
902 if (gst_caps_is_subset (caps,
result)) {
903 gst_caps_replace (&
result, caps);
914 GstCaps * incaps, GstCaps * outcaps)
923 &self->tensor_config);
926 if (gst_caps_is_always_compatible (outcaps, supposed)) {
927 self->negotiated =
TRUE;
929 GST_ERROR_OBJECT (
self,
930 "This is not compatible with the supposed output pad cap");
933 gst_caps_unref (supposed);
936 return self->negotiated;
946 GstPadDirection direction, GstCaps * caps, gsize size,
947 GstCaps * othercaps, gsize * othersize)
951 if (direction == GST_PAD_SRC)
958 if (!self->is_custom && self->decoder->getTransformSize)
959 *othersize =
self->decoder->getTransformSize (&self->plugin_data,
960 &self->tensor_config, caps, size, othercaps, direction);
977 g_return_val_if_fail (name && strlen (name), -EINVAL);
978 g_return_val_if_fail (func, -EINVAL);
1004 ml_loge (
"Failed to unregister custom callback %s.", name);